导入具有不同节点数的XML

时间:2015-04-08 08:31:54

标签: sql sql-server xml bulk

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

我使用此查询导入得很好:

SELECT
  number = deltagere.value('(number)[1]', 'bigint'),
  dato = deltagere.value('(date)[1]', 'varchar(10)'),
  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)

现在的问题是,并非所有<deltager>个节点都有<name>个节点。它可能看起来像这样:

    <deltager>
      <number>1234134982</number>
      <date>05-12-2007</date>
      <information>
        <deltagertype>person</deltagertype>
        <leader>Wolfgang Smith</leader>
        <status>Active</status>
      </information>
      <role>Responsible</role>
    </deltager>

如果缺少名称节点,我希望该节点的名称列填充NULL。像这样:

| number     | dato       | nameFrom   | nameTo     | nameText | deltagertype | ...
-------------+------------+------------+------------+----------+--------------+ ...
| 1234134982 | 29-12-2006 | NULL       | NULL       | NULL     | person       | ...

我希望你们任何一位专家都知道如何解决我的问题。

1 个答案:

答案 0 :(得分:1)

您可以使用OUTER APPLY代替CROSS APPLY。

DECLARE @XmlFile XML
SET @XmlFile =
'
<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>
    <deltager>
      <number>1234134982</number>
      <date>05-12-2007</date>
      <information>
        <deltagertype>person</deltagertype>
        <leader>Wolfgang Smith</leader>
        <status>Active</status>
      </information>
      <role>Responsible</role>
    </deltager>
  </deltagere>
</report>
'
SELECT
  number = deltagere.value('(number)[1]', 'bigint'),
  dato = deltagere.value('(date)[1]', 'varchar(10)'),
  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)
OUTER APPLY
  deltagere.nodes('name/name') AS XT2(XC)

<强>输出

number      dato        nameFrom    nameTo      nameText    deltagertype    leader          deltagerStatus  deltagerRole
142555267   29-12-2006  01-05-2000  01-01-2003  foo         person          John Smith      Active          Responsible
142555267   29-12-2006  01-01-2003  29-12-2006  bzz         person          John Smith      Active          Responsible
4000134982  05-12-2007  07-07-2007  05-12-2007  bar         person          Wolfgang Smith  Active          Responsible
1234134982  05-12-2007  NULL        NULL        NULL        person          Wolfgang Smith  Active          Responsible