XML将SQL Server中的几个具有相同名称的元素分成不同的列

时间:2017-02-28 13:45:31

标签: sql sql-server xml database

机器在测试后生成xml文件。问题是元素都被命名为相同但我需要它们在不同的列中。

这是XML的样子:

<WorkProcess xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Header>
    <Element>
      <Name>
        <string>CONTINENTAL_PART_NO</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Continental_Part_No</Name>
          <Value>A2C73661103</Value>
          <Comment />
        </Header-Item>
      </Content>
    </Element>
    <Element>
      <Name>
        <string>KENDRION_PART_NO</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Kendrion_Part_No</Name>
          <Value>4191506A00-O</Value>
          <Comment />
        </Header-Item>
      </Content>
    </Element>
    <Element>
      <Name>
        <string>PRODOCTION_DATE</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Prodoction_Date</Name>
          <Value>20170222</Value>
          <Comment />
        </Header-Item>
      </Content>
    </Element>
    <Element>
      <Name>
        <string>COUNTING_NO</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Counting_No</Name>
          <Value>0068</Value>
          <Comment>Count of IO-Parts</Comment>
        </Header-Item>
      </Content>
    </Element>

从这个XML我需要Name作为列名,而Value需要在该列中。

用我的代码:

DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)

SELECT @XML = XMLData FROM XMLwithOpenXML

EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML

SELECT *
FROM OPENXML(@hDoc, 'WorkProcess/Header/Element/Content/Header-Item',2)
WITH 
    (Continental_Part_No [varchar](50) 'Value')

EXEC sp_xml_removedocument @hDoc
GO

我只能获得1列中的所有值,因为它们都有相同的路径。

有没有解决方案可以解决这个问题?

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

首先:不要使用FROM OPENXML,这已经过时了。

您可以在派生表

中将数据读作键值对

可以针对已知列名称旋转此表。如果您事先没有knwo(all)列名,则可以动态创建语句。

试试这个:

DECLARE @xml XML=
N'<WorkProcess xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Header>
    <Element>
      <Name>
        <string>CONTINENTAL_PART_NO</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Continental_Part_No</Name>
          <Value>A2C73661103</Value>
          <Comment />
        </Header-Item>
      </Content>
    </Element>
    <Element>
      <Name>
        <string>KENDRION_PART_NO</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Kendrion_Part_No</Name>
          <Value>4191506A00-O</Value>
          <Comment />
        </Header-Item>
      </Content>
    </Element>
    <Element>
      <Name>
        <string>PRODOCTION_DATE</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Prodoction_Date</Name>
          <Value>20170222</Value>
          <Comment />
        </Header-Item>
      </Content>
    </Element>
    <Element>
      <Name>
        <string>COUNTING_NO</string>
      </Name>
      <Content>
        <Header-Item>
          <Name>Counting_No</Name>
          <Value>0068</Value>
          <Comment>Count of IO-Parts</Comment>
        </Header-Item>
      </Content>
    </Element>
  </Header>
</WorkProcess>';

SELECT p.*
FROM
(
    SELECT e.value(N'(Content/Header-Item/Name/text())[1]','nvarchar(max)') AS ColumnName
          ,e.value(N'(Content/Header-Item/Value/text())[1]','nvarchar(max)') AS ColumnValue
    FROM @xml.nodes(N'/WorkProcess/Header/Element') AS A(e)
) AS t
PIVOT
(
    MIN(ColumnValue) FOR ColumnName IN(Continental_Part_No
                                      ,Kendrion_Part_No
                                      ,Prodoction_Date
                                      ,Counting_No)
) AS p;

结果

Continental_Part_No Kendrion_Part_No    Prodoction_Date Counting_No
A2C73661103         4191506A00-O        20170222        0068

UPDATE从文件中读取XML

尝试这样

WITH MyXmlFile(TheFile) AS
(
    SELECT CAST(BulkColumn AS XML) FROM OPENROWSET(BULK 'C:\YourPath\YourFile.xml', SINGLE_BLOB ) a
)
SELECT p.*
FROM
(
    SELECT e.value(N'(Content/Header-Item/Name/text())[1]','nvarchar(max)') AS ColumnName
          ,e.value(N'(Content/Header-Item/Value/text())[1]','nvarchar(max)') AS ColumnValue
    FROM MyXmlFile
    CROSS APPLY MyXmlFile.TheFile.nodes(N'/WorkProcess/Header/Element') AS A(e)
) AS t
PIVOT
(
    MIN(ColumnValue) FOR ColumnName IN(Continental_Part_No
                                      ,Kendrion_Part_No
                                      ,Prodoction_Date
                                      ,Counting_No)
) AS p;