将 OUTPUT inserted.id 与所选行的值合并
Combine OUTPUT inserted.id with value from selected row
运行SQL Server 2014
。如何从 table 插入多行并将插入的数据与新 ID 合并?
让我们看一个精简的例子!
DECLARE @Old TABLE
(
[ID] [int] PRIMARY KEY,
[Data] [int] NOT NULL
)
DECLARE @New TABLE
(
[ID] [int] PRIMARY KEY,
[OtherID] [int] NULL
)
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID], [@Old].[ID] /* <--- not supported :( */ INTO @New
SELECT [Data]
FROM @Old
我需要将插入的 ID 与正在插入的数据结合起来。我可以假设插入的行与所选行的顺序相同吗? (插入操作后我将无法在 [Data]
上加入。)
更新
以下似乎是一个可能的解决方案,但我找不到证明它有效的证据。保证有效吗?
DECLARE @Old TABLE
(
[RowID] [int] PRIMARY KEY IDENTITY, -- Guaranteed insert order?
[ID] [int] NOT NULL,
[Data] [int] NOT NULL
)
DECLARE @New TABLE
(
[RowID] [int] PRIMARY KEY IDENTITY, -- Guaranteed insert order?
[ID] [int] NOT NULL,
[OtherID] [int] NULL
)
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
这里的技巧是对选定的行使用单独的 identity
列和 ORDER BY
,然后 加入 RowID
。
唉,OUTPUT
子句的目的不是为了输出不进入目标 table 的内容(或者在 update
的情况下来自 table ).
如果你修改 Data
为旧 id 添加一个虚拟列,那么你可以输出它。
事实上,如果table不大,可以考虑添加列进行插入,然后删除。
您可以(滥用)使用带有 OUTPUT
子句的 MERGE
。
MERGE
可以 INSERT
、UPDATE
和 DELETE
行。在我们的例子中,我们只需要 INSERT
。
1=0 始终为假,因此始终执行 NOT MATCHED BY TARGET
部分。
通常,可能还有其他分支,请参阅文档。
WHEN MATCHED
通常用于UPDATE
;
WHEN NOT MATCHED BY SOURCE
通常用于DELETE
,但我们这里不需要。
MERGE
的复杂形式等同于简单的 INSERT
,
但与简单的 INSERT
不同,它的 OUTPUT
子句允许引用我们需要的列。
它允许从源表和目标表中检索列,从而保存新旧 ID 之间的映射。
MERGE INTO [dbo].[Test]
USING
(
SELECT [Data]
FROM @Old AS O
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT ([Data])
VALUES (Src.[Data])
OUTPUT Src.ID AS OldID, inserted.ID AS NewID
INTO @New(ID, [OtherID])
;
关于您的更新并依赖生成的 IDENTITY
值的顺序。
在简单的情况下,当 [dbo].[Test]
有 IDENTITY
列时,INSERT
和 ORDER BY
将保证 生成的 IDENTITY
值将按指定顺序排列。请参阅 Ordering guarantees in SQL Server 中的第 4 点。请注意,它不保证插入行的物理顺序,但它保证生成 IDENTITY
值的顺序。
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
但是,当您使用 OUTPUT
子句时:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
OUTPUT
流中的行未排序。至少,严格来说,查询中的 ORDER BY
适用于主要的 INSERT
操作,但没有任何内容说明 OUTPUT
的顺序是什么。所以,我不会试图依赖它。使用 MERGE
或添加一个额外的列来显式存储 ID 之间的映射。
运行SQL Server 2014
。如何从 table 插入多行并将插入的数据与新 ID 合并?
让我们看一个精简的例子!
DECLARE @Old TABLE
(
[ID] [int] PRIMARY KEY,
[Data] [int] NOT NULL
)
DECLARE @New TABLE
(
[ID] [int] PRIMARY KEY,
[OtherID] [int] NULL
)
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID], [@Old].[ID] /* <--- not supported :( */ INTO @New
SELECT [Data]
FROM @Old
我需要将插入的 ID 与正在插入的数据结合起来。我可以假设插入的行与所选行的顺序相同吗? (插入操作后我将无法在 [Data]
上加入。)
更新
以下似乎是一个可能的解决方案,但我找不到证明它有效的证据。保证有效吗?
DECLARE @Old TABLE
(
[RowID] [int] PRIMARY KEY IDENTITY, -- Guaranteed insert order?
[ID] [int] NOT NULL,
[Data] [int] NOT NULL
)
DECLARE @New TABLE
(
[RowID] [int] PRIMARY KEY IDENTITY, -- Guaranteed insert order?
[ID] [int] NOT NULL,
[OtherID] [int] NULL
)
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
这里的技巧是对选定的行使用单独的 identity
列和 ORDER BY
,然后 加入 RowID
。
唉,OUTPUT
子句的目的不是为了输出不进入目标 table 的内容(或者在 update
的情况下来自 table ).
如果你修改 Data
为旧 id 添加一个虚拟列,那么你可以输出它。
事实上,如果table不大,可以考虑添加列进行插入,然后删除。
您可以(滥用)使用带有 OUTPUT
子句的 MERGE
。
MERGE
可以 INSERT
、UPDATE
和 DELETE
行。在我们的例子中,我们只需要 INSERT
。
1=0 始终为假,因此始终执行 NOT MATCHED BY TARGET
部分。
通常,可能还有其他分支,请参阅文档。
WHEN MATCHED
通常用于UPDATE
;
WHEN NOT MATCHED BY SOURCE
通常用于DELETE
,但我们这里不需要。
MERGE
的复杂形式等同于简单的 INSERT
,
但与简单的 INSERT
不同,它的 OUTPUT
子句允许引用我们需要的列。
它允许从源表和目标表中检索列,从而保存新旧 ID 之间的映射。
MERGE INTO [dbo].[Test]
USING
(
SELECT [Data]
FROM @Old AS O
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT ([Data])
VALUES (Src.[Data])
OUTPUT Src.ID AS OldID, inserted.ID AS NewID
INTO @New(ID, [OtherID])
;
关于您的更新并依赖生成的 IDENTITY
值的顺序。
在简单的情况下,当 [dbo].[Test]
有 IDENTITY
列时,INSERT
和 ORDER BY
将保证 生成的 IDENTITY
值将按指定顺序排列。请参阅 Ordering guarantees in SQL Server 中的第 4 点。请注意,它不保证插入行的物理顺序,但它保证生成 IDENTITY
值的顺序。
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
但是,当您使用 OUTPUT
子句时:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
OUTPUT
流中的行未排序。至少,严格来说,查询中的 ORDER BY
适用于主要的 INSERT
操作,但没有任何内容说明 OUTPUT
的顺序是什么。所以,我不会试图依赖它。使用 MERGE
或添加一个额外的列来显式存储 ID 之间的映射。