在SQL Server中从xml剥离数据

时间:2018-07-26 08:37:28

标签: sql xml sql-server-2012

我的一个具有xml数据类型的表具有以下xml信息:

<RequestMetaData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <MetaData Type="DocImport">
    <Keywords>
      <Key Name="Zone" Value="MIO" />
      <Key Name="ClassificationStrategy" Value="NeedClassification" />
      <Key Name="Folder" Value="0456e6ca" />
    </Keywords>
  </MetaData>
  <MetaData Type="SourceResponse">
    <Keywords>
      <Key Name="NotificationResponse_20180427-150426" Value="Received successful response from Source" />
    </Keywords>
  </MetaData>
</RequestMetaData>

我需要编写一个SQL查询来获取基于键名的分类策略的值。

我已将xml添加到变量@xml中,并使用了以下代码。它返回NULL。

select A.b.value('ClassificationStrategy[1]', 'VARCHAR(30)') AS CS
FROM @xml.nodes('/RequestMetaData/MetaData/Keywords') AS A(b) 

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

您可以通过多种方式读取XML。使用带有.value()表达式的简单XPath/XQuery检索单个值,使用.query检索XML的一部分,或使用.nodes()返回重复的元素作为派生表:

DECLARE @xml XML=
N'<RequestMetaData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <MetaData Type="DocImport">
    <Keywords>
      <Key Name="Zone" Value="MIO" />
      <Key Name="ClassificationStrategy" Value="NeedClassification" />
      <Key Name="Folder" Value="0456e6ca" />
    </Keywords>
  </MetaData>
  <MetaData Type="SourceResponse">
    <Keywords>
      <Key Name="NotificationResponse_20180427-150426" Value="Received successful response from Source" />
    </Keywords>
  </MetaData>
</RequestMetaData>';

--Read the whole lot
SELECT md.value('@Type','nvarchar(max)') AS MetaDataType
      ,k.value('@Name','nvarchar(max)') AS KeyName
      ,k.value('@Value','nvarchar(max)') AS KeyValue
FROM @xml.nodes('/RequestMetaData/MetaData') A(md)
OUTER APPLY md.nodes('Keywords/Key') B(k);

--Get one key's value by name (anywhere in the doc)
DECLARE @keyName VARCHAR(100)='ClassificationStrategy';
SELECT @xml.value('(//Key[@Name=sql:variable("@keyName")]/@Value)[1]','nvarchar(max)');

--Use the meta data type as additional filter (if key names are not unique per doc)
DECLARE @kName VARCHAR(100)='ClassificationStrategy';
DECLARE @mdType VARCHAR(100)='DocImport';
SELECT @xml.value('(/RequestMetaData
                    /MetaData[@Type=sql:variable("@mdType")]
                    /Keywords
                    /Key[@Name=sql:variable("@kName")]
                    /@Value)[1]','nvarchar(max)');