【问题标题】:Convert XML column to Table Data in SQL Query在 SQL 查询中将 XML 列转换为表数据
【发布时间】:2019-01-13 00:44:12
【问题描述】:

我有这个 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


测试1

然后,我就可以将数据插入到 sql 中的表中了。

【问题讨论】:

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


    【解决方案1】:
    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'等。

    【讨论】:

      【解决方案2】:

      您需要在使用 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)
      

      【讨论】:

        【解决方案3】:

        此 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 中的表中了。

        ...让我想,real-world 用例将包含不止一列。在这种情况下,你的表现还不够。

        此查询将以惰性方式仅读取 &lt;Col1&gt; 内容:

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

        一般来说,尽可能具体是好的,但实际问题看起来,好像你最好使用命名空间通配符和 深度搜索 (//) &lt;DocumentElement&gt;:

        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
        

        【讨论】:

        猜你喜欢
        • 2021-07-17
        • 2014-07-04
        • 1970-01-01
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多