我正在构建一个树(物料清单样式),并转换一些数据。请考虑下表:
BillOfMaterials
现在我正在使用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
问题是:@@ identity只会给我联盟之前插入的最后一条记录的身份。
我该怎么做才能获得身份?我可以修改Table3但不能修改Table1或Table2
row_number()
对递归查询有未定义的行为,所以我不能在这里使用它。
我知道我可以使用GUID,这是唯一的选择吗?
答案 0 :(得分:3)
您无法在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
上的完整工作示例答案 1 :(得分:2)
@@identity
会显示您会话的实际身份值。
您不能将CTE
与IDENTITY FUNCTION
一起使用,但可以使用临时表:
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
)