我正在编写批处理插入语句,并希望使用临时表来跟踪插入的 ID,而不是自己循环遍历项目并为每个插入的行调用 SCOPE_IDENTITY()。
需要插入的数据具有(临时)ID 将其链接到也应插入另一个表的其他数据,因此我需要实际 Id 和临时 Id 的交叉引用。
这是我到目前为止的一个例子:
-- The existing table
DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX));
-- My data I want to insert
DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
INSERT INTO @MyInsertData ( ID,Name)
VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');
DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);
INSERT INTO @MyTable ( [Name] )
OUTPUT Inserted.ID, INS.ID INTO @MyCrossRef
SELECT [NAME] FROM @MyInsertData INS
-- Check the result
SELECT * FROM @MyCrossRef
问题是我无法让 OUTPUT INTO 子句接受 ID,我已经尝试过@MyInsertData.ID
将表连接到自身的其他技巧,但似乎没有任何效果。
实际上,您可以通过将您的更改
INSERT
为MERGE
. 虽然该MERGE
语句实际上是在 SQL Server 中执行“upserts”的一种非常巧妙的方式,但没有什么可以阻止您将其仅用于插入目的:关于它的好处之一
MERGE
是它允许您访问源列以及子句中的内置inserted
和deleted
表。OUTPUT
我的代码可能包含错误,因为我还没有实际测试过它。我几年前的博客文章更详细地介绍了一些细节,包括查询性能。
输出子句只能访问目标行和常量/变量中的数据,不能访问源中其他地方的数据
SELECT
,就像您在触发器中操作一样。https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql状态:
因此,要获取原始 ID,您需要将其包含在目标表中,以便输出子句可以回显它,如下所示:
尽管在您的情况下更改目标对象的架构可能不切实际,因此这可能不适用。