正在运行var dr = dt.AsEnumerable().Where(row => row.Field<string>("Vards") == "Name").SingleOrDefault();
dt.Rows.Remove(dr);
。如何从表中插入多行并将插入的数据与新ID组合?
让我们看看一个精简的例子!
SQL Server 2014
我需要将插入的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
。)
以下似乎是一种可能的解决方案,但我无法找到有效的证据。它能保证有效吗?
[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
。
答案 0 :(得分:9)
您可以(ab)将MERGE
与OUTPUT
条款一起使用。
MERGE
可以INSERT
,UPDATE
和DELETE
行。在我们的例子中,我们只需要INSERT
。
1 = 0始终为false,因此始终执行NOT MATCHED BY TARGET
部分。
一般来说,可能还有其他分支,请参阅docs。
WHEN MATCHED
通常用于UPDATE
;
WHEN NOT MATCHED BY SOURCE
通常用于DELETE
,但我们在这里不需要它们。
这种令人费解的MERGE
形式相当于简单INSERT
,
但与简单INSERT
不同,它的OUTPUT
子句允许引用我们需要的列。
它允许从源表和目标表中检索列,从而保存旧ID和新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
将保证生成的{{1} }值将按指定的顺序排列。见Ordering guarantees in SQL Server中的第4点。请注意,它不保证插入行的物理顺序,但它保证了生成IDENTITY
值的顺序。
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
或添加额外的列以明确存储ID之间的映射。
答案 1 :(得分:1)
唉,OUTPUT
子句的目的不是为了输出不会进入目标表的东西(或者在update
的情况下来自表格。)
如果您修改Data
以获得旧ID的虚拟列,则可以输出它。
实际上,如果表格不大,您可以考虑为插入添加列,然后再将其删除。