将 OUTPUT insert.id 与选定行的值相结合 [英] Combine OUTPUT inserted.id with value from selected row

查看:24
本文介绍了将 OUTPUT insert.id 与选定行的值相结合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行 SQL Server 2014.如何从表中插入多行并将插入的数据与新 ID 合并?

Running SQL Server 2014. How can I insert multiple rows from a table and combine the inserted data with the new IDs?

让我们看一个精简的例子!

Let's look at a stripped-down example!

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] 上加入.)

I need to combine the inserted IDs with the data that is being inserted. Can I assume that the inserted rows are in the same order as the selected rows? (I will not be able to join on [Data] after the insert operation.)

以下似乎是一个可能的解决方案,但我找不到证明它有效的证据.能保证有效吗?

The following seems like a possible solution, but I cannot find proof that it works. Is it guaranteed to work?

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.

The trick here is to use a separate identity column and ORDER BY for the selected rows, and then joining on RowID.

推荐答案

您可以 (ab) 使用 MERGEOUTPUT 子句.

You can (ab)use MERGE with OUTPUT clause.

MERGE 可以INSERTUPDATEDELETE 行.在我们的例子中,我们只需要INSERT.1=0 总是假的,所以 NOT MATCHED BY TARGET 部分总是被执行.通常,可能还有其他分支,请参阅文档.WHEN MATCHED 通常用于UPDATEWHEN NOT MATCHED BY SOURCE 通常用于DELETE,但我们这里不需要它们.

MERGE can INSERT, UPDATE and DELETE rows. In our case we need only to INSERT. 1=0 is always false, so the NOT MATCHED BY TARGET part is always executed. In general, there could be other branches, see docs. WHEN MATCHED is usually used to UPDATE; WHEN NOT MATCHED BY SOURCE is usually used to DELETE, but we don't need them here.

这种复杂形式的 MERGE 等价于简单的 INSERT,但与简单的 INSERT 不同,它的 OUTPUT 子句允许引用我们需要的列.它允许从源表和目标表中检索列,从而节省旧 ID 和新 ID 之间的映射.

This convoluted form of MERGE is equivalent to simple INSERT, but unlike simple INSERT its OUTPUT clause allows to refer to the columns that we need. It allows to retrieve columns from both source and destination tables thus saving a mapping between old and new IDs.

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 列,然后 INSERTORDER BY 保证生成的 IDENTITY 值将按指定的顺序排列.请参阅SQL Server 中的订购保证中的第 4 点.请注意,它不保证插入行的物理顺序,但它保证生成 IDENTITY 值的顺序.

In the simple case, when [dbo].[Test] has IDENTITY column, then INSERT with ORDER BY will guarantee that the generated IDENTITY values would be in the specified order. See point 4 in Ordering guarantees in SQL Server. Mind you, it doesn't guarantee the physical order of inserted rows, but it guarantees the order in which IDENTITY values are generated.

INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]

但是,当您使用 OUTPUT 子句时:

But, when you use the OUTPUT clause:

INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]

OUTPUT 流中的行没有排序.至少,严格来说,查询中的 ORDER BY 适用于主要的 INSERT 操作,但没有说明OUTPUT<的顺序是什么/代码>.所以,我不会试图依赖它.使用 MERGE 或添加额外的列来显式存储 ID 之间的映射.

the rows in the OUTPUT stream are not ordered. At least, strictly speaking, ORDER BY in the query applies to the primary INSERT operation, but there is nothing there that says what is the order of the OUTPUT. So, I would not try to rely on that. Either use MERGE or add an extra column to store the mapping between IDs explicitly.

这篇关于将 OUTPUT insert.id 与选定行的值相结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆