将XML插入SQL Server表中

4

鉴于这个XML:

<Documents>
    <Batch BatchID = "1" BatchName = "Fred Flintstone">
        <DocCollection>
            <Document DocumentID = "269" KeyData = "" />
            <Document DocumentID = "6"   KeyData = "" />
            <Document DocumentID = "299" KeyData = ""     ImageFile="Test.TIF" />
        </DocCollection>    
    </Batch>    
    <Batch BatchID = "2" BatchName = "Barney Rubble">
        <DocCollection>
            <Document DocumentID = "269" KeyData = "" />
            <Document DocumentID = "6"   KeyData = "" />
        </DocCollection>
    </Batch>
</Documents>

我需要将其以以下格式插入SQL Server表中:
BatchID   BatchName           DocumentID
1         Fred Flintstone     269
1         Fred Flintstone     6
1         Fred Flintstone     299
2         Barney Rubble       269
2         Barney Rubble       6

这是SQL语句:
   SELECT
        XTbl.XCol.value('./@BatchID','int') AS BatchID,
        XTbl.XCol.value('./@BatchName','varchar(100)') AS BatchName,
        XTbl.XCol.value('DocCollection[1]/DocumentID[1]','int') AS DocumentID
   FROM @Data.nodes('/Documents/Batch') AS XTbl(XCol)

这个命令会给我返回这个结果:

BatchID BatchName       DocumentID
1       Fred Flintstone NULL
2       Barney Rubble   NULL

我做错了什么?

此外,有没有人能推荐一份关于SQL Server中XML的好教程?

谢谢。

卡尔

1个回答

7
你离答案很接近。
使用通配符和CROSS APPLY,你可以生成多条记录。
将别名更改为 lvl1lvl2 以更好地说明。
Declare @XML xml = '
<Documents>
    <Batch BatchID = "1" BatchName = "Fred Flintstone">
        <DocCollection>
            <Document DocumentID = "269" KeyData = "" />
            <Document DocumentID = "6"   KeyData = "" />
            <Document DocumentID = "299" KeyData = ""     ImageFile="Test.TIF" />
        </DocCollection>    
    </Batch>    
    <Batch BatchID = "2" BatchName = "Barney Rubble">
        <DocCollection>
            <Document DocumentID = "269" KeyData = "" />
            <Document DocumentID = "6"   KeyData = "" />
        </DocCollection>
    </Batch>
</Documents>
'

Select BatchID    = lvl1.n.value('@BatchID','int') 
      ,BatchName  = lvl1.n.value('@BatchName','varchar(50)') 
      ,DocumentID = lvl2.n.value('@DocumentID','int') 
 From  @XML.nodes('Documents/Batch') lvl1(n)
 Cross Apply lvl1.n.nodes('DocCollection/Document') lvl2(n)

返回值

BatchID BatchName       DocumentID
1       Fred Flintstone 269
1       Fred Flintstone 6
1       Fred Flintstone 299
2       Barney Rubble   269
2       Barney Rubble   6

1
好的解决方案,我给你点赞,但是为什么第一个.nodes()中要加上*呢? - Shnugo
@Shnugo,既然你提到了,/Batch会更安全/更具体。或者你有其他想法吗? - John Cappelletti
不,只是为了避免错误,如果可能会有其他名称的节点... - Shnugo
@Shnugo 已更新,但Cross Apply仍将针对DocCollection/Document。只是为了好玩,我在一个批次中添加了<MiscOther><Document DocumentID = "269" KeyData = "" /></MiscOther> ...并列出了它们。 - John Cappelletti
这真是高端啊 :-D 试过用<DocCollcetion>将你的测试<Document>包含起来了吗? - Shnugo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接