2

深刻なXmlを細断処理した後、ほぼ必要なものが得られましたが、結果を確認したところ、解析の1つのセクションで、次のすべての行の詳細を反復するこのパターンを簡単に解決できないことがわかりました。各サブヘッダー(たとえば、すべてのラインアイテムに対して合計3つのレコードを書き出すのではなく、サブヘッダーごとに3つのラインアイテムを書き出す)のうち、2つあるとします。全部で6つになります!:-(次のコードでは、パターンを一般的なヘッダー/サブヘッダー/詳細関係モデルとして抽出しました。

    DECLARE @MetroXML xml
    SET @MetroXML =
    '<Header>
       <col1>Conoco</col1>
       <col2>ORD-1111</col2>
       <SubHeaders>
         <SubHeader>
          <col1>Dallas</col1>
          <col2>BOL-2213</col2>
         <Details>
          <Detail>
            <col1>Diesel</col1>
            <col2>7600.00</col2>
          </Detail>
         </Details>
        </SubHeader>
        </SubHeaders>
        <SubHeaders>
         <SubHeader>
          <col1>Fort Worth</col1>
          <col2>BOL-2216</col2>
         <Details>
          <Detail>
            <col1>Ethanol</col1>
            <col2>1852.00</col2>
          </Detail>
          <Detail>
            <col1>Unleaded</col1>
            <col2>900.00</col2>
          </Detail>
         </Details>
       </SubHeader>
      </SubHeaders>
     </Header>';


    INSERT INTO [scratch].GenericHeader
     SELECT T.c.value('col1[1]','varchar(10)') AS 'col1',
            T.c.value('col2[1]','varchar(10)') AS 'col2'
       FROM @MetroXML.nodes('/Header') T(c);


    INSERT [scratch].GenericSubHeader
     (id,col1,col2)
    SELECT 
      h.id,
      n.x.value('col1[1]','varchar(10)') AS 'col1',
      n.x.value('col2[1]','varchar(10)') AS 'col2'
     FROM [scratch].GenericHeader h
      CROSS APPLY @MetroXML.nodes('/Header/SubHeaders/SubHeader') n(x);


     INSERT [scratch].GenericDetail
     (id,subid,col1,col2)
      SELECT 
       s.id,
       s.subid,
       n.x.value('col1[1]','varchar(10)') AS 'col1',
       n.x.value('col2[1]','varchar(10)') AS 'col2'
     FROM [scratch].GenericSubHeader s
      CROSS APPLY @MetroXML.nodes('/Header/SubHeaders/SubHeader/Details/Detail') as n(x);


     select * from [scratch].GenericHeader
      where id = 24;

     select * from [scratch].GenericSubHeader
      where id = 24;

     select * from [scratch].GenericDetail
      where id = 24;

注:id、subid、detidはINT IDENTITY(1,1)の結果として定義されます

私が得るもの:

id|subid|detid|col1     |col2
--------------------------------
24|44   |22   |Diesel   |7600.00
24|44   |23   |Ethanol  |1852.00
24|44   |24   |Unleaded |900.00
24|48   |25   |Diesel   |7600.00
24|48   |26   |Ethanol  |1852.00
24|48   |27   |Unleaded |900.00

私が欲しいもの:

id|subid|detid|col1     |col2
--------------------------------
24|44   |22   |Diesel   |7600.00
24|48   |23   |Ethanol  |1852.00
24|48   |24   |Unleaded |900.00
4

1 に答える 1

3

行が重複する理由は、の各行のXML全体に対してクロスアプライを使用しているためですGenericSubHeaderID生成されたinGenericHeaderと生成さsubidれたinGenericSubHeaderをXMLの関連部分にマップする方法を理解する必要があります。

SQL Server 2008以降を使用している場合は、出力とマージして、生成されたIDとそれに属するxmlサブノードを保持するテーブル変数を作成できます。

declare @GH table
(
  id int,
  sub xml
);

merge scratch.GenericHeader as T
using 
  (
    select T.c.value('col1[1]','varchar(10)'),
           T.c.value('col2[1]','varchar(10)'),
           T.c.query('SubHeaders')
    from @MetroXML.nodes('/Header') T(c)
  ) as S(col1, col2, sub)
on 0 = 1
when not matched then
  insert (col1, col2) values(S.col1, S.col2)
output inserted.id, S.sub into @GH;  

declare @GSH table
(
  id int,
  subid int,
  det xml
);

merge scratch.GenericSubHeader as T
using
  (
    select h.id,
           n.x.value('col1[1]','varchar(10)'),
           n.x.value('col2[1]','varchar(10)'),
           n.x.query('Details')
    from @GH as h
      cross apply h.sub.nodes('/SubHeaders/SubHeader') n(x)
  ) as S(id, col1, col2, det)
on 0 = 1
when not matched then
  insert (id, col1, col2) values (S.id, S.col1, S.col2)
output inserted.id, inserted.subid, S.det into @GSH;

insert into scratch.GenericDetail(id, subid, col1, col2)
select s.id,
       s.subid,
       n.x.value('col1[1]','varchar(10)') AS 'col1',
       n.x.value('col2[1]','varchar(10)') AS 'col2'
from @GSH as s
  cross apply s.det.nodes('/Details/Detail') as n(x);
于 2012-10-12T05:57:04.637 に答える