【问题标题】:XML into SQL Server several elements with same name into different columnsXML 到 SQL Server 几个同名的元素到不同的列
【发布时间】:2017-02-28 13:45:30
【问题描述】:

一台机器在测试后生成 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 中,我需要将名称作为列名,并将值作为该列中的值。

使用我的代码:

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 列中的所有值,因为它们都具有相同的路径。

有解决这个问题的办法吗?

感谢您的帮助!

【问题讨论】:

    标签: sql sql-server xml database


    【解决方案1】:

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

    您可以在派生表

    中将数据读取为键值对

    此表可以针对已知的列名进行透视。如果您事先不知道(所有)列名,则可以动态创建语句。

    试试这个:

    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
    

    更新从文件中读取 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;
    

    【讨论】:

    • 几乎每次我用 FROM OpenXML 找到它时,我都会在 google 上搜索 xml to ms sql。接下来的事情是,我需要为未来所有即将到来的 XML 执行此操作,作为一项自动工作。因此,只需声明 XML 代码实际上不起作用。它也不是整个文件,还有大约 40.000 行。
    • @Andi This article 8 岁以上...
    • @Andi,FROM OPENXML 可能仍然占有一席之地的唯一一种情况是,当您必须从同一个相当大的 XML 中读取各种值和子集时。在这种情况下,准备工作只完成一次,随后的子调用将很快工作。
    • 有这方面的教程吗?
    • @Andi 只需搜索sql server xml tutorial,您就会找到很多。另一个很好的来源可能是在 SO 上阅读一些相关答案。访问一个叫 Shnugo 的人的个人资料可能是一个好的开始:-)
    猜你喜欢
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 1970-01-01
    相关资源
    最近更新 更多