Sql server 2008 T-SQL:CTE与标识列

Sql server 2008 T-SQL:CTE与标识列,sql-server-2008,common-table-expression,identity-column,Sql Server 2008,Common Table Expression,Identity Column,我正在构建一个树型BOM表样式,并转换一些数据。考虑下表: 物料清单 波米德 父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 field

我正在构建一个树型BOM表样式,并转换一些数据。考虑下表:

物料清单

波米德 父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
问题是:@@标识将只提供在联合之前插入的最后一条记录的标识

我能做些什么来获得身份?我可以修改表3,但不能修改表1或表2


行号对于递归查询有未定义的行为,所以我不能在这里使用它

我知道我可以使用GUID,这是唯一的选项吗?

@@identity显示会话的实际标识值

不能将CTE与标识功能一起使用,但可以使用临时表:

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
)

无法在CTE中捕获生成的标识。但是,您可以将所有行插入到目标表中,并将null作为ParentID,然后在单独的update语句中更新ParentID。要做到这一点,您可以使用merge和下面描述的技术


这是一个完整的工作示例,用于递归查询的行数有未定义的行为。嗯,我不知道这一点。真奇怪。我找不到更好的/其他的选择。因此,您可能必须使用NEWID.Bas,在我的团队中,我们已经在CTE中使用了很多时间和各种实现。我们没有发现任何问题。你到底是什么意思?
-- 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