3

私はツリー(BOM)を構築して、データを変換しています。次の表を考えてみます。T-SQL:ID列を持つCTE

with BOM as 
(
select @@identity as BomId, null as ParentId <some other fields> from MyTable 
union all 
select @@identity as BomId, 
     parent.BomId as ParentId, 
     some other fields 
from MyTable2 
inner join BOM parent on blabla) 

insert into MyTable3 
select * from BOM 

問題は次のとおりです:今、私はそれを埋めるためにCTEを使用してい

BillOfMaterials

  • BomId
  • ParentIdは

@@アイデンティティは、私に、ユニオンの前に挿入された最後のレコードのアイデンティティーだけを与えます。

アイデンティティを取得するにはどうすればよいですか?テーブル3は変更できますが、テーブル1やテーブル2は変更できません

row_number()は再帰的クエリの動作が未定義であるため、ここでは使用できません。

私はGUIDを使用できることを知っています、それは唯一のオプションですか?

答えて

3

あなたがで生成されたIDをキャプチャすることはできませんCTE。ただし、すべての行をnullとしてParentIDというターゲット表に挿入し、別の更新文でParentIDを更新できます。これを行うには、mergeと、hereと記載されているテクニックを使用できます。ここで

-- Helper table to map new id's from source 
-- against newly created id's in target 
declare @IDs table 
( 
    TargetID int, 
    SourceID int, 
    SourceParentID int 
) 

-- Use merge to capture generated id's 
merge BillOfMaterials as T 
using SourceTable as S 
on 1 = 0 
when not matched then 
insert (SomeColumn) values(SomeColumn) 
output inserted.BomId, S.BomID, S.ParentID into @IDs; 

-- Update the parent id with the new id 
update T 
set ParentID = I2.TargetID 
from BillOfMaterials as T 
    inner join @IDs as I1 
    on T.BomID = I1.TargetID 
    inner join @IDs as I2 
    on I1.SourceParentID = I2.SourceID 

は(SE-Data

+2

よく遊んだ、ありがとう! :) – Bas

2

@@identityには、セッションの実際のID値が表示されます。

あなたはIDENTITY FUNCTIONCTEを使用することはできませんが、一時テーブルを使用することができます。

SELECT IDENTITY(int,1,1) AS BomId, un.* 
INTO #BOM 
FROM <your union> as un 

あなたはCTEを使用する場合:

with BOM as 
(
    SELECT ROW_NUMBER() OVER(ORDER BY <column>) AS BomId, un.* 
    FROM <your union> as un 
) 
+0

ROW_NUMBERで完全に動作するサンプルです)再帰クエリのための未定義の動作を持っています。 – Bas

+0

うーん、私はそれについて知りませんでした。それは奇妙だ。私は良い/他のオプションを見つけることができません。おそらくNEWID()を使う必要があります。 – devarc

+0

私のチームでは、CTEでrow_number()を長時間、さまざまな実装で使用してきました。私たちは何の問題も発見していません。あなたはどういう意味ですか? – Vladislav