【问题标题】:SQL Server return sub nodes (values) by querying parent node attribute nameSQL Server 通过查询父节点属性名返回子节点(值)
【发布时间】:2019-11-04 22:55:04
【问题描述】:

我有以下问题:我无法更改的 SQL 数据库。带有字段“ID”(自动编号)和“详细信息”(纯文本)的表“LogEntries”。 详细信息字段包含纯文本条目以及 xml 数据。 需要进行双重转换或转换以将“详细信息”转换为我想要的记录的 xml。

XML结构是这样的:

    <?xml version="1.0" encoding="utf-16"?>
<changes typeName="Document" name="005019 (0)" id="8567">
    <propertyChange name="OwnerPersonName" typeName="System.String" systemName="OwnerPersonID">
        <from id="541">Thomas, Marcus</from>
        <to id="103">Murphy, Tony</to>
    </propertyChange>
    <propertyChange name="AuthorPersonName" typeName="System.String" systemName="AuthorPersonID">
        <from id="10">Witten, Howard</from>
        <to id="750">Atukorala, Anu</to>
    </propertyChange>
    <propertyChange name="ReviewDateTime" typeName="System.DateTime">
        <from>2008-04-28T00:00:00</from>
        <to>2010-04-28T00:00:00</to>
    </propertyChange>
    <collectionChanges typeName="DocumentRelatedStandardsCollection" name="DocumentRelatedStandardsCollection">
        <addition typeName="DocumentRelatedStandard" name="Integrated Management System\Implementation\Quality\7.2 Customer related processes" id="239">
            <propertyChange name="StandardDescription" typeName="System.String">
                <from></from>
                <to>Integrated Management System\Implementation\Quality\7.2 Customer related processes</to>
            </propertyChange>
            <propertyChange name="StandardName" typeName="System.String">
                <from></from>
                <to>7.2 Customer related processes</to>
            </propertyChange>
        </addition>
    </collectionChanges>
</changes>

我要做的是获取&lt;propertyChange&gt; 父元素的&lt;from&gt;&lt;to&gt; 的子元素值,其中属性name = "ReviewDateTime"

尝试过交叉应用、直接访问(强制转换值)等,并不断出错。最后一次尝试似乎让我接近,但它告诉我子节点不存在。

这就是我的交叉申请:

    Select
            [QPulseAuditLog].dbo.LogEntries.ID as [LogId]
            ,t.c.value('/(to)[1]','nvarchar(10)') as [from]

FROM        [QPulseAuditLog].[dbo].[LogEntries]

cross apply (select cast(cast([Details] as ntext) as xml) where [QPulseAuditLog].[dbo].[LogEntries].[Details] LIKE '%ReviewDateTime%') as t0(x)
cross apply t0.x.nodes('/changes/propertyChange/@ReviewDateTime') t(c)

这是错误: 消息 2256,第 16 层,状态 1,第 5 行 XQuery [t0.x.value()]: '(' 附近的语法错误,需要“节点测试”。

这就是我获得的直接价值访问:

    use [QPulseAuditLog]

SELECT 
            ID
            [Details],
            CONVERT(XML,CONVERT(Ntext,[Details])).value('/changes/propertyChange/@ReviewDateTime/from[1]', 'NVARCHAR(MAX)') AS StatusChangeFrom


FROM        [QPulseAuditLog].[dbo].[LogEntries]

这是错误: 消息 2261,第 16 层,状态 1,第 6 行 XQuery [value()]: 在类型 'attribute(ReviewDateTime,xdt:untypedAtomic) *' 中没有名为 'from' 的元素。

选项 2 是首选,因为它使我的事情变得更容易(根本没有 XML 经验)。知道我哪里出错了吗?希望这是我的语法。感谢所有帮助......它把我逼到了墙边。

干杯 博多

【问题讨论】:

    标签: sql sql-server xml attributes nodes


    【解决方案1】:

    这是一个完整的 DDL 和一个工作示例。最好把 XML 当作 XML 数据类型,使用 XQuery 来查询。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Details NVARCHAR(MAX));
    INSERT INTO @tbl (Details)
    VALUES
    (N'<?xml version="1.0" encoding="utf-16"?>
    <changes typeName="Document" name="005019 (0)" id="8567">
        <propertyChange name="OwnerPersonName" typeName="System.String" systemName="OwnerPersonID">
            <from id="541">Thomas, Marcus</from>
            <to id="103">Murphy, Tony</to>
        </propertyChange>
        <propertyChange name="AuthorPersonName" typeName="System.String" systemName="AuthorPersonID">
            <from id="10">Witten, Howard</from>
            <to id="750">Atukorala, Anu</to>
        </propertyChange>
        <propertyChange name="ReviewDateTime" typeName="System.DateTime">
            <from>2008-04-28T00:00:00</from>
            <to>2010-04-28T00:00:00</to>
        </propertyChange>
        <collectionChanges typeName="DocumentRelatedStandardsCollection"
                           name="DocumentRelatedStandardsCollection">
            <addition typeName="DocumentRelatedStandard"
                      name="Integrated Management System\Implementation\Quality\7.2 Customer related processes"
                      id="239">
                <propertyChange name="StandardDescription" typeName="System.String">
                    <from></from>
                    <to>Integrated Management System\Implementation\Quality\7.2 Customer related processes</to>
                </propertyChange>
                <propertyChange name="StandardName" typeName="System.String">
                    <from></from>
                    <to>7.2 Customer related processes</to>
                </propertyChange>
            </addition>
        </collectionChanges>
    </changes>'),
    ('Plain text');
    -- DDL and sample data population, end
    
    ;WITH rs AS
    (
        SELECT *, TRY_CAST(CAST(Details AS NTEXT) AS XML) AS xml_data FROM @tbl
    )
    SELECT ID
        , col.value('(from/text())[1]','DATETIME') AS [From]
        , col.value('(to/text())[1]','DATETIME') AS [To]
    FROM rs
          CROSS APPLY rs.[xml_Data].nodes('/changes/propertyChange[@name="ReviewDateTime"]') AS tab(col);
    

    输出

    +----+-------------------------+-------------------------+
    | ID |          From           |           To            |
    +----+-------------------------+-------------------------+
    |  1 | 2008-04-28 00:00:00.000 | 2010-04-28 00:00:00.000 |
    +----+-------------------------+-------------------------+
    

    【讨论】:

    • 谢谢。这似乎想工作......除了现在我得到可怕的“XML解析:第4行,字符32,非法xml字符”错误。我发誓,设计那张桌子的人应该受到……严厉的惩罚。
    • 请与有问题的字符共享那个“XML”。
    • 好吧,我查过了。错误信息说第 49 行,字符 40。没有非法字符。啊!!!
    • 第 49 行:Hoppe, PeterHone, Dianne2007-04-02T00:00:002010-08-07T00:00:00
    • 您可以使用以下 SQL 识别该行:SELECT *, TRY_CAST(Details AS XML) AS xml_data FROM @tbl;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多