【问题标题】:Import XML file to SQL Server Horizontally将 XML 文件水平导入 SQL Server
【发布时间】:2015-08-26 03:45:51
【问题描述】:

我正在尝试将 XML 数据导入 SQL Server。我找到了下面的链接。

Import XML to SQL Server

我的要求略有不同,我需要创建以<name> 作为列名和<value> 作为列值的表。如下所示

XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:toatech:ResourceManagement:1.0">
   <SOAP-ENV:Body>
      <ns1:get_resources_list_response>
         <result_code>0</result_code>
         <resources>
            <resource>
               <properties>
                  <property>
                     <name>id</name>
                     <value>CAP_LOAD_TEST</value>
                  </property>
                  <property>
                     <name>status</name>
                     <value>inactive</value>
                  </property>
                  <property>
                     <name>parent_id</name>
                     <value>ABC_CO</value>
                  </property>
                  <property>
                     <name>type</name>
                     <value>GR</value>
                  </property>
                  <property>
                     <name>name</name>
                     <value>Capacity LoadTesting</value>
.
.
.
.

代码:

DECLARE @XmlFile XML

SELECT @XmlFile = BulkColumn  
FROM OPENROWSET(BULK 'C:\Users\GET_RESOURCE_LIST.xml', SINGLE_BLOB) x

SELECT 
    Resource_id = resource.value('(value)[1]', 'varchar(255)'),
    Resource_status = resource.value('(value)[2]', 'varchar(255)')
 FROM
@XmlFile.nodes('//resources/resource/properties/property') AS XTbl1(resource)

因此,当“资源”项重复时,它应该是表中具有新值集的新行

预期的表格输出:

    id              status      parent_id   type    name
    ==              ======      =========   ====    ====
    CAP_LOAD_TEST   inactive    ABC_CO      GR      Capacity LoadTesting

... 

使用上面的代码,所有值都填充到一列。这就是问题所在。

【问题讨论】:

    标签: sql sql-server xml


    【解决方案1】:

    你需要PIVOT操作动态查询:

    DECLARE @xml XML = N'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:toatech:ResourceManagement:1.0">
       <SOAP-ENV:Body>
          <ns1:get_resources_list_response>
             <result_code>0</result_code>
             <resources>
                <resource>
                   <properties>
                      <property>
                         <name>id</name>
                         <value>CAP_LOAD_TEST</value>
                      </property>
                      <property>
                         <name>status</name>
                         <value>inactive</value>
                      </property>
                      <property>
                         <name>parent_id</name>
                         <value>ABC_CO</value>
                      </property>
                      <property>
                         <name>type</name>
                         <value>GR</value>
                      </property>
                      <property>
                         <name>name</name>
                         <value>Capacity LoadTesting</value>
                      </property>
                    </properties>
                 </resource>
                 </resources>
        </ns1:get_resources_list_response>
                </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>'
    
    DECLARE @Output nvarchar(max) = N''
    DECLARE @PivotList nvarchar(max)
    
    
    SELECT 
        @PivotList = COALESCE(@PivotList + ', ', N'') + N'[' + XC.value('./name[1]', 'varchar(255)') + N']'
    FROM 
        @xml.nodes('//resources/resource[1]/properties/property') AS XT(XC)
    
    SET @Output = N'SELECT 
        '+@PivotList+N'
    FROM
    (
        SELECT 
            Resource_id = resource.value(''(name)[1]'', ''varchar(255)''),
            Resource_status = resource.value(''(value)[1]'', ''varchar(255)''),
            unique_b_node = resource.value(''for $i in . return count(../../../*[. << $i]) + 1'', ''int'')
         FROM
        @xml.nodes(''//resources/resource/properties/property'') AS XTbl1(resource)
    ) AS s
    PIVOT
    (
        MAX(Resource_status)
        FOR Resource_id IN ('+@PivotList+N')
    ) AS t;'
    
    EXEC sp_executesql @Output, N'@xml xml', @xml = @xml;
    

    【讨论】:

    • 感谢您的回复。这里当&lt;resource&gt; ... &lt;/resource&gt; 元素重复时,我得到错误The column 'id' was specified multiple times for 't'. 我们需要单独处理吗?
    • @shabar 你知道你想得到的列列表吗?还是它的动态?
    • 是的,目前已修复。如果也能支持动态情况,那就太好了
    • @shabar 我修改了我的答案,试试这个
    【解决方案2】:

    试试下面的代码 sn-p,如果你提供多个 &lt;resource&gt; ... &lt;/resource&gt; 节点,这应该可以工作。 根据不同属性名称的数量,我在下面硬编码了 5。这也可以通过从临时表中查找 Resource_id 的不同名称的计数来解决。

    DECLARE @XmlFile XML = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:toatech:ResourceManagement:1.0">
       <SOAP-ENV:Body>
          <ns1:get_resources_list_response>
             <result_code>0</result_code>
             <resources>
                <resource>
                   <properties>
                      <property>
                         <name>id</name>
                         <value>CAP_LOAD_TEST1</value>
                      </property>
                      <property>
                         <name>status</name>
                         <value>inactive1</value>
                      </property>
                      <property>
                         <name>parent_id</name>
                         <value>ABC_CO1</value>
                      </property>
                      <property>
                         <name>type</name>
                         <value>GR1</value>
                      </property>
                      <property>
                         <name>name</name>
                         <value>Capacity LoadTesting1</value>
                      </property>
                    </properties>
                </resource>
             </resources>
                  <resources>
                <resource>
                   <properties>
                      <property>
                         <name>id</name>
                         <value>CAP_LOAD_TEST2</value>
                      </property>
                      <property>
                         <name>status</name>
                         <value>inactive2</value>
                      </property>
                      <property>
                         <name>parent_id</name>
                         <value>ABC_CO2</value>
                      </property>
                      <property>
                         <name>type</name>
                         <value>GR2</value>
                      </property>
                      <property>
                         <name>name</name>
                         <value>Capacity LoadTesting2</value>
                      </property>
                    </properties>
                </resource>
             </resources>
          </ns1:get_resources_list_response>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>'
    CREATE TABLE #tab (groupID INT IDENTITY(1,1), Resource_id NVARCHAR(50),Resource_status VARCHAR(255))
    INSERT INTO #tab
    SELECT 
        Resource_id = resource.value('(name)[1]', 'nvarchar(50)'),
        Resource_status = resource.value('(value)[1]', 'varchar(255)')
    FROM
    @XmlFile.nodes('//resources/resource/properties/property') AS XTbl1(resource)
    
    ;WITH cte AS(SELECT Resource_id,Resource_status,(groupID-1)/5 groupID FROM #tab)
    SELECT id,status,parent_id,type,name
    FROM cte
    PIVOT (MAX(Resource_status) FOR Resource_ID IN ( id,status,parent_id,type,name)) A
    

    【讨论】:

    • 感谢 Abhishek,感谢
    猜你喜欢
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 2015-06-08
    • 2023-03-04
    • 2013-05-26
    • 2023-03-16
    • 2013-10-18
    相关资源
    最近更新 更多