我正在从另一个表 B 向表 A 插入多条记录。有没有一种方法可以获取表 A 记录的标识值并更新表 B 记录,而无需执行游标?
Create Table A
(id int identity,
Fname nvarchar(50),
Lname nvarchar(50))
Create Table B
(Fname nvarchar(50),
Lname nvarchar(50),
NewId int)
Insert into A(fname, lname)
SELECT fname, lname
FROM B
我正在使用 MS SQL Server 2005。
使用 2005 年的输出子句:
DECLARE @output TABLE (id int)
Insert into A (fname, lname)
OUTPUT inserted.ID INTO @output
SELECT fname, lname FROM B
select * from @output
现在您的表变量具有您插入的所有行的标识值。
仔细阅读你的问题,你只想根据表A中的新身份值更新表B。
插入完成后,只需运行更新...
UPDATE B
SET NewID = A.ID
FROM B INNER JOIN A
ON (B.FName = A.Fname AND B.LName = A.LName)
这假设 FName / LName 组合可用于对表之间的记录进行键匹配。如果不是这种情况,您可能需要添加额外的字段以确保记录正确匹配。
如果您没有允许您匹配记录的备用键,那么它根本没有意义,因为表 B 中的记录无法相互区分。
据我了解,您遇到的问题是您想要插入到具有标识列的表 A 中,而您想要保留表 B 中没有标识列的标识。
为此,您只需在表 A 上打开身份插入即可。这将允许您在插入时定义 ID,只要它们不冲突,就应该没问题。然后你就可以这样做:
Insert into A(identity, fname, lname) SELECT newid, fname, lname FROM B
不确定您使用的是什么数据库,但对于 sql server,打开身份插入的命令是:
set identity_insert A on
我建议使用 uniqueidentifier 类型而不是身份。在这种情况下,您可以在插入之前生成 ID:
update B set NewID = NEWID()
insert into A(fname,lname,id) select fname,lname,NewID from B
如果您总是想要这种行为,您可以在 TableA 上放置一个 AFTER INSERT 触发器来更新表 B。
您可以通过加入行号来获取。这是可能的,因为由于它是一个身份,因此它只会在您添加项目时增加,这将按照您选择它们的顺序进行。
-- first create a table for show how its works
CREATE TABLE [dbo].[myTable]
(
[id] [INT] IDENTITY(1, 1) NOT NULL,
[text] [VARCHAR](10) NULL
)
ON [PRIMARY]
GO
-- var table for keep new inserted id
DECLARE @tblNewInserted TABLE
(
newids INT
)
--use the output clause in insert statement
INSERT INTO [dbo].[myTable]
output inserted.id
INTO @tblNewInserted
VALUES ('aa'),('bb'),('cc')
SELECT *
FROM @tblNewInserted
DECLARE @InsertedIds TABLE (
ID INT,
);
Insert into A(fname, lname)
OUTPUT inserted.ID INTO @InsertedIds(ID)
SELECT fname, lname
FROM B
SELECT ID FROM @InsertedPayments;
MBelly 是对的 - 但是触发器将始终尝试更新表 B,即使这不是必需的(因为您也从表 C 插入?)。
Darren 在这里也是正确的,您无法将多个身份作为结果集返回。您的选择是使用游标并获取插入的每一行的标识,或者使用 Darren 的方法来存储前后的标识。只要您知道身份的增量,只要您确保表针对所有三个事件都被锁定,这就应该起作用。
如果是我,而且时间不紧的话我会用光标。