在SQL查询中将XML列转换为表数据

时间:2018-08-06 05:40:53

标签: sql xml web-services sql-server-2008 datatable

我有这个XML文件,它是Web服务返回的数据表:

        DECLARE @MyXML XML = 
        '<?xml version="1.0" encoding="utf-8"?>
        <DataTable xmlns="http://tempuri.org/">
          <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
            <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Blah" msdata:UseCurrentLocale="true">
              <xs:complexType>
                <xs:choice minOccurs="0" maxOccurs="unbounded">
                  <xs:element name="Blah">
                    <xs:complexType>
                      <xs:sequence>
                        <xs:element name="Col1" type="xs:string" minOccurs="0" />
                      </xs:sequence>
                    </xs:complexType>
                  </xs:element>
                </xs:choice>
              </xs:complexType>
            </xs:element>
          </xs:schema>
          <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
            <DocumentElement xmlns="">
              <Blah diffgr:id="Blah1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
                <Col1>testing1</Col1>
              </Blah>
            </DocumentElement>
          </diffgr:diffgram>
        </DataTable>'

我想要这样的输出:    选择Col1

Col1


testing1

然后,我将能够将数据插入sql中的表中。

3 个答案:

答案 0 :(得分:1)

使用XQuery之前,您需要设置XML命名空间:

;WITH XMLNAMESPACES('http://tempuri.org/' AS ns, 'urn:schemas-microsoft-com:xml-diffgram-v1' AS dg)

SELECT
    Col1 = XC.value('(Col1)[1]', 'varchar(50)')
FROM
    @MyXML.nodes('/ns:DataTable/dg:diffgram/DocumentElement/Blah') AS XT(XC)

答案 1 :(得分:1)

此XML是否在您的控制之下?

我对此特别恼火

<DocumentElement xmlns="">

此行正在重新定义默认名称空间。

您显示的XML由模式部分和数据部分组成

DECLARE @MyXML XML = 
'<?xml version="1.0" encoding="utf-8"?>
<DataTable xmlns="http://tempuri.org/">

    <!-- This schema is describing your data''s structure -->

    <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Blah" msdata:UseCurrentLocale="true">
        <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="Blah">
            <xs:complexType>
                <xs:sequence>
                <xs:element name="Col1" type="xs:string" minOccurs="0" />
                </xs:sequence>
            </xs:complexType>
            </xs:element>
        </xs:choice>
        </xs:complexType>
    </xs:element>
    </xs:schema>

    <!-- End of schema -->
    <!-- Begin of data -->

    <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <DocumentElement xmlns="">
        <Blah diffgr:id="Blah1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
        <Col1>testing1</Col1>
        </Blah>
    </DocumentElement>
    </diffgr:diffgram>

    <!-- End of data -->

</DataTable>';

您的声明

  

然后,我将能够将数据插入sql中的表中。

...让我想一想,真实世界用例将包含多个列。在这种情况下,您的显示不够。

此查询将以一种惰性方式仅读取<Col1>内容:

SELECT @MyXML.value('(//*:Col1/text())[1]','nvarchar(max)');

通常最好尽可能具体一些,但实际问题看起来就好像使用名称空间通配符和深度搜索(//可能会更好降到<DocumentElement>

SELECT de.query('.')
FROM @MyXml.nodes('//DocumentElement') A(de)

此查询将返回此区域的各种内容:

SELECT de.value('(Blah/@*:id)[1]','nvarchar(max)') DiffGr_ID
      ,de.value('(Blah/@*:rowOrder)[1]','int') MsData_RowOrder
      ,de.value('(Blah/@*:hasChanges)[1]','nvarchar(max)') diffgr_HasChanges
      ,de.value('(Blah/Col1/text())[1]','nvarchar(max)') Col1_Text
FROM @MyXml.nodes('//DocumentElement') A(de);

结果

DiffGr_ID   MsData_RowOrder diffgr_HasChanges   Col1_Text
-----------------------------------------------------------
Blah1       0               inserted            testing1

答案 2 :(得分:0)

INSERT INTO sampletable
    (
        col1,
        col2
    )
    SELECT
        t.value('(col1/text())[1]', 'nvarchar(10)') ---colum name of the xml
        t.value('(col2/text())[1]', 'nvarchar(10)') ---colum name of the xml
    FROM @xmlData.nodes('/NewDataSet/MYTABLE') AS TempTable(t)

不接受,当xml中列的类型为float时,您需要将'narchar(10)'更改为'float',或者如果date使用'date'等。