【问题标题】:How to return multiple values from XML element in SQL?如何从 SQL 中的 XML 元素返回多个值?
【发布时间】:2021-09-08 00:28:34
【问题描述】:

我需要从 SQL 中 XML 列的“名称”元素中提取信息。 XML 示例如下:

<ArrayOfTarget xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes">
  <Target>
    <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
    <AgencyName i:nil="true" />
    <Id>19bc33e1-a788-cd99-3dab-08d92aa7d030</Id>
    <Name>Case Number WB21-006637</Name>
    <Type>Case Management</Type>
  </Target>
  <Target>
    <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
    <AgencyName i:nil="true" />
    <Id>cb4d829b-c31a-cadb-5c9e-08d934b7404d</Id>
    <Name>Incident Supplement Number WB21-006637.006</Name>
    <Type>Data Entry</Type>
  </Target>
  <Target>
    <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
    <AgencyName i:nil="true" />
    <Id>6b23195c-4650-c0c9-925d-08d71a88f611</Id>
    <Name i:nil="true" />
    <Type>Template</Type>
  </Target>
  <Target>
    <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
    <AgencyName i:nil="true" />
    <Id>b465517c-5926-c6b3-1cc6-08d6fbe6da27</Id>
    <Name>Default Workflow</Name>
    <Type>Workflow</Type>
  </Target>
  <Target>
    <AgencyId i:nil="true" />
    <AgencyName i:nil="true" />
    <Id i:nil="true" />
    <Name>Complete</Name>
    <Type>Workflow Step</Type>
  </Target>
</ArrayOfTarget>

我有这个用于返回五个“名称”元素的 SQL 查询:

;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS i,
                    'http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes' AS s)
SELECT TOP 100
TargetData_Xml,
Description,
TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[1]', 'varchar(100)') as Context1,
TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[2]', 'varchar(100)') as Context2,
TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[3]', 'varchar(100)') as Context3,
TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[4]', 'varchar(100)') as Context4,
TargetData_Xml.value('(/s:ArrayOfTarget/s:Target/s:Name)[5]', 'varchar(100)') as Context5
FROM
[InformRMSAudit].[dbo].[AuditEntities]
WHERE
CaseNumber = 'RP21-010802'
ORDER BY
Date desc

如果每条记录在 XML 中只有五个“Name”元素就足够了,但“Name”元素的数量因记录而异。

如何更改我的查询以处理记录之间的差异?

【问题讨论】:

  • 您是否需要将值放在单独的列而不是一行中?如果是这样,唯一的方法就是使用动态 SQL。结果集必须定义良好,因此如果需要动态列数,则需要动态语句。如果你不知道你在用这种语法做什么,我个人建议不要这样做。
  • 由于我没有使用动态 SQL 的经验,我会听取您的建议。如果这些值是在行中而不是在单独的列中,您会如何建议这样做?

标签: sql xml tsql


【解决方案1】:

请尝试以下解决方案。

正如@Larnu 所指出的,最好将XML 分解为行。

如果需要,很容易过滤掉具有 NULL 值的名称。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, TargetData_Xml XML);
INSERT INTO @tbl (TargetData_Xml) VALUES
(N'<ArrayOfTarget xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
               xmlns="http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes">
    <Target>
        <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
        <AgencyName i:nil="true"/>
        <Id>19bc33e1-a788-cd99-3dab-08d92aa7d030</Id>
        <Name>Case Number WB21-006637</Name>
        <Type>Case Management</Type>
    </Target>
    <Target>
        <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
        <AgencyName i:nil="true"/>
        <Id>cb4d829b-c31a-cadb-5c9e-08d934b7404d</Id>
        <Name>Incident Supplement Number WB21-006637.006</Name>
        <Type>Data Entry</Type>
    </Target>
    <Target>
        <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
        <AgencyName i:nil="true"/>
        <Id>6b23195c-4650-c0c9-925d-08d71a88f611</Id>
        <Name i:nil="true"/>
        <Type>Template</Type>
    </Target>
    <Target>
        <AgencyId>ca2fa1dd-2cd4-c219-bea5-08d6fbe6d96c</AgencyId>
        <AgencyName i:nil="true"/>
        <Id>b465517c-5926-c6b3-1cc6-08d6fbe6da27</Id>
        <Name>Default Workflow</Name>
        <Type>Workflow</Type>
    </Target>
    <Target>
        <AgencyId i:nil="true"/>
        <AgencyName i:nil="true"/>
        <Id i:nil="true"/>
        <Name>Complete</Name>
        <Type>Workflow Step</Type>
    </Target>
</ArrayOfTarget>');
-- DDL and sample data population, end

WITH XMLNAMESPACES (DEFAULT 'http://schemas.datacontract.org/2004/07/TriTech.InformRMS.Domain.Core.ComplexTypes')
SELECT ID
    , c.value('(Name/text())[1]', 'VARCHAR(100)') AS [Name]
FROM @tbl
    CROSS APPLY TargetData_Xml.nodes('/ArrayOfTarget/Target') AS t(c);

输出

+----+--------------------------------------------+
| ID |                    Name                    |
+----+--------------------------------------------+
|  1 | Case Number WB21-006637                    |
|  1 | Incident Supplement Number WB21-006637.006 |
|  1 | NULL                                       |
|  1 | Default Workflow                           |
|  1 | Complete                                   |
+----+--------------------------------------------+

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    相关资源
    最近更新 更多