将XML导入SQL Server,拆分为多行

时间:2015-03-31 15:20:33

标签: sql sql-server xml

我有一个XML文件,我需要将其导入SQL Server数据库。 XML文件的构建如下:

<report>
  <deltagere>
    <deltager>
    <number>142555267</number>
    <date>29-12-2006</date>
    <name>
      <name>
        <from>01-05-2000</from>
        <to>01-01-2003</to>
        <text>foo</text>
      </name>
      <name>
        <from>01-01-2003</from>
        <to>29-12-2006</to>
        <text>bzz</text>
      </name>
    </name>
    <information>
      <deltagertype>person</deltagertype>
      <leader>John Smith</leader>
      <status>Active</status>
    </information>
    <role>Responsible</role>
    </deltager>
    <deltager>
      <number>4000134982</number>
      <date>05-12-2007</date>
      <name>
        <name>
          <from>07-07-2007</from>
          <to>05-12-2007</to>
          <text>bar</text>
        </name>
      </name>
      <information>
        <deltagertype>person</deltagertype>
        <leader>Wolfgang Smith</leader>
        <status>Active</status>
      </information>
      <role>Responsible</role>
    </deltager>
    ...
  </deltagere>
</report>

如您所见,name属性可以包含多个名称。我已经设法将XML导入到我的数据库中,但只使用了第一个名称属性。 我到目前为止编写的代码是:

DECLARE @XmlFile XML

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

INSERT INTO dbo.deltagere(number, dato, nameFrom, nameTo, nameText, deltagertype, leader, deltagerStatus, deltagerRole)
SELECT
  number = deltagere.value('(number)[1]', 'bigint'),
  dato = deltagere.value('(date)[1]', 'varchar(10)'),
  nameFrom = deltagere.value('(name/name/from)[1]', 'varchar(10)'),
  nameTo = deltagere.value('(name/name/to)[1]', 'varchar(10)'),
  nameText = deltagere.value('(name/name/text)[1]', 'varchar(30)'),
  deltagertype = deltagere.value('(information/deltagertype)[1]', 'varchar(20)'),
  leader = deltagere.value('(information/leader)[1]', 'varchar(50)'),
  deltagerStatus = deltagere.value('(information/status)[1]', 'varchar(50)'),
  deltagerRole = deltagere.value('(role)[1]', 'varchar(50)')
FROM
  @XmlFile.nodes('/report/deltagere/deltager') AS XTbl(deltagere);

这给了我这个输出:

| number     | dato       | nameFrom   | nameTo     | nameText | deltagertype | ...
| 142555267  | 29-12-2006 | 01-05-2000 | 01-01-2003 | foo      | person       | ...
| 4000134982 | 05-12-2007 | 07-07-2007 | 05-12-2007 | bar      | person       | ...

我想为每个名称/名称添加一行。所以像这样:

-------------------------------------------------------
| number     | dato       | nameFrom   | nameTo     | nameText | deltagertype | ...
| 142555267  | 29-12-2006 | 01-05-2000 | 01-01-2003 | foo      | person       | ...
| 142555267  | 29-12-2006 | 01-01-2003 | 29-12-2006 | bzz      | person       | ...
| 4000134982 | 05-12-2007 | 07-07-2007 | 05-12-2007 | bar      | person       | ...

等等。

我真的迷失了如何做到这一点。所以我希望你们中的任何人都有关于如何修改我的代码的想法,以允许这个或者可能采用不同的方法解决问题。

1 个答案:

答案 0 :(得分:2)

尝试此操作 - 您需要进行第二次.nodes()调用以枚举所有<name>个子节点:

SELECT
    number = deltagere.value('(number)[1]', 'bigint'),
    dato = deltagere.value('(date)[1]', 'varchar(10)'),
    -- NEW NEW NEW - read from `XC` pseudo columns to get 1-n names
    nameFrom = XC.value('(from)[1]', 'varchar(10)'),
    nameTo = XC.value('(to)[1]', 'varchar(10)'),
    nameText = XC.value('(text)[1]', 'varchar(30)'),
    deltagertype = deltagere.value('(information/deltagertype)[1]', 'varchar(20)'),
    leader = deltagere.value('(information/leader)[1]', 'varchar(50)'),
    deltagerStatus = deltagere.value('(information/status)[1]', 'varchar(50)'),
    deltagerRole = deltagere.value('(role)[1]', 'varchar(50)')
FROM
    @XmlFile.nodes('/report/deltagere/deltager') AS XTbl(deltagere)
CROSS APPLY
    deltagere.nodes('name/name') AS XT2(XC)