将复杂的XML插入SQL Server表

时间:2017-07-17 23:32:15

标签: sql sql-server xml tsql

鉴于此XML:

<Documents>
  <Batch BatchID="1" BatchName="Fred Flintstone">
    <DocCollection>
      <Document DocumentID="269" FileName="CoverPageInstructions.xsl">
        <MergeFields>
          <MergeField FieldName="A" Value="" />
          <MergeField FieldName="B" Value="" />
          <MergeField FieldName="C" Value="" />
          <MergeField FieldName="D" Value="" />
        </MergeFields>
      </Document>
      <Document DocumentID="6" FileName="USform8802.pdf">
        <MergeFields>
          <MergeField FieldName="E" Value="" />
          <MergeField FieldName="F" Value="" />
          <MergeField FieldName="G" Value="" />
          <MergeField FieldName="H" Value="" />
          <MergeField FieldName="I" Value="" />
        </MergeFields>
      </Document>
      <Document DocumentID="299" FileName="POASIDE.TIF">
        <MergeFields />
      </Document>
    </DocCollection>
  </Batch>
  <Batch BatchID="2" BatchName="Barney Rubble">
    <DocCollection>
      <Document DocumentID="269" FileName="CoverPageInstructions.xsl">
        <MergeFields>
          <MergeField FieldName="A" Value="" />
          <MergeField FieldName="B" Value="" />
          <MergeField FieldName="C" Value="" />
          <MergeField FieldName="D" Value="" />
        </MergeFields>
      </Document>
      <Document DocumentID="6" FileName="USform8802.pdf">
        <MergeFields>
          <MergeField FieldName="E" Value="" />
          <MergeField FieldName="F" Value="" />
          <MergeField FieldName="G" Value="" />
          <MergeField FieldName="H" Value="" />
          <MergeField FieldName="I" Value="" />
        </MergeFields>
      </Document>
    </DocCollection>
  </Batch>
</Documents>

我试图达到这个结果:

BatchID BatchName DocumentID FieldName
1   Fred Flintstone 269 A
1   Fred Flintstone 269 B
1   Fred Flintstone 269 C
1   Fred Flintstone 269 D
1   Fred Flintstone 6   E
1   Fred Flintstone 6   F
1   Fred Flintstone 6   G
1   Fred Flintstone 6   H
1   Fred Flintstone 6   I
1   Fred Flintstone 299 Null
2   Barney Rubble   269 A
2   Barney Rubble   269 B
2   Barney Rubble   269 C
2   Barney Rubble   269 D
2   Barney Rubble   6   E
2   Barney Rubble   6   F
2   Barney Rubble   6   G
2   Barney Rubble   6   H
2   Barney Rubble   6   I

我似乎正在用这个获得Cartesian JOIN(每个文档都包含所有文档中的MergeField的完整列表:

SELECT lvl1.n.value('@BatchID','int'), 
       lvl1.n.value('@BatchName','varchar(50)'), 
       lvl2.n.value('@DocumentID','int'), 
       lvl3.n.value('@FieldName','varchar(50)') 
FROM  @Data.nodes('Documents/*') lvl1(n)
CROSS APPLY lvl1.n.nodes('DocCollection/Document') lvl2(n)
CROSS APPLY lvl1.n.nodes('DocCollection/Document/MergeFields/MergeField') lvl3(n)   

我想知道如何获得我需要的结果,批处理1中没有MergeField元素的299 DocumentID的Null值。

感谢任何帮助。

由于

卡尔

更新:以下是使用OpenXML执行相同操作的方法:

 SELECT   
   BatchID,   
   BatchName,   
   DocumentID,   
   FileName,   
   KeyData,   
   FieldName  
   FROM OPENXML(@hdoc, '/Documents/Batch/DocCollection/Document/MergeFields/MergeField', 11)  
      WITH (BatchID varchar(100) '../../../../@BatchID',  
            BatchName varchar(100) '../../../../@BatchName',   
            DocumentID varchar(100) '../../@DocumentID',  
            FileName varchar(100) '../../@FileName',   
            KeyData varchar(100) '../../@KeyData',   
            FieldName varchar(100) '@FieldName');  

1 个答案:

答案 0 :(得分:3)

  

编辑 - 抱歉,我错过了Fred上的NULL。刚刚改变了Cross Apply   如果需要,其他交叉申请可以是外部申请

通知Lvl3

不清楚为什么不为每个字段创建别名。例如,我希望BatchID = lvl1.n.value('@BatchID','int'),

之类的东西
SELECT lvl1.n.value('@BatchID','int'), 
       lvl1.n.value('@BatchName','varchar(50)'),
       lvl2.n.value('@DocumentID','int'),
       lvl3.n.value('@FieldName','varchar(50)') 
FROM  @Data.nodes('Documents/Batch') lvl1(n)
CROSS APPLY lvl1.n.nodes('DocCollection/Document') lvl2(n)
Outer APPLY lvl2.n.nodes('MergeFields/MergeField') lvl3(n)   

<强>返回

enter image description here