2015-03-31 63 views
3

我有一个XML文件,我需要导入到SQL Server数据库中。 XML文件是这样构建的:将XML导入到SQL Server中,分成多行

<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  | ... 

等等。

我真的迷失在如何做到这一点。所以我希望你们中的任何一位对如何修改我的代码有任何想法,以允许这个或者对这个问题采取不同的方法。

回答

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) 
+1

你是惊人的。这正是我需要的。谢谢 – Kasperhogh 2015-03-31 17:52:21

+0

也许你可以帮我解决另一个问题。 如果某些节点没有任何节点会怎么样?然后插入0行。任何只在名称列中写入NULL的方法(如果是这种情况)? – Kasperhogh 2015-04-07 23:18:13