对于每个插入的行,使用外键约束在其他表中创建行

时间:2014-11-07 15:35:29

标签: sql sql-server sql-server-2008-r2

我有2个具有外键约束的表:

Table A:
[id] int identity(1, 1) PK,
[b_id] INT

Table B:
[id] int identity(1, 1) PK

其中[b_id]指的是表B的[id]列。

任务是: 每次插入表A,并将新记录放入表B并更新[b_id]。

使用Sql Server 2008 r2。

感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

第一次误解了这个,我发布了一个完全不同的答案。

首先,如果表B是父表,则首先插入其中。然后你获取id值并插入表A。

最好这样做是一次交易。根据其他字段的不同,您可以使用表B中的触发器填充表A,或者您可能需要编写直接的SQL代码或存储过程来完成工作。

如果您有两个表的表模式,将更容易描述要执行的操作。但是,假设表B只有一列而表A只有ID和B_id,这就是代码可以工作的方式(您可能希望为生产代码添加显式事务)。该示例用于单个记录插入,这不会从触发器发生。触发器应始终处理多个记录插入,然后必须以不同方式编写。但是,如果不知道表中的列是什么,很难提供一个很好的例子。

create table #temp (id int identity)
create table #temp2 (Id int identity, b_id int)
declare @b_id int
insert into #temp default values
select @B_id = scope_identity()
insert into #temp2 (B_id)
values(@B_id)

select * from #temp2

如果有其他列,问题会变得更复杂,因为你也必须为它们提供值。

答案 1 :(得分:0)

如果不删除标识规范,您可以使用以下选项: SET IDENTITY_INSERT B ON

试试这个:

CREATE TRIGGER trgAfterInsert ON [dbo].[A] 
FOR INSERT
AS 



IF @@ROWCOUNT = 0 RETURN;
SET NOCOUNT ON;
SET IDENTITY_INSERT B ON

DECLARE @B_Id INT 
SELECT @B_Id = ISNULL(MAX(Id), 0) FROM B;

WITH RES (ID, BIDS)
AS
(SELECT Id, @B_Id + ROW_NUMBER() OVER (ORDER BY Id) FROM INSERTED)
UPDATE A SET [b_Id] = BIDS
FROM A 
    INNER JOIN RES ON A.ID = RES.ID 

INSERT INTO B (Id) 
SELECT @B_Id + ROW_NUMBER() OVER (ORDER BY Id) FROM INSERTED

SET IDENTITY_INSERT B OFF

GO

答案 2 :(得分:-1)

虽然Nadeem的回答是正确的,但由于某种原因,他的触发器需要max.id而不是NEW.id,并且不会相应地更新A.

对于你要求触发器可用的内容,你需要表A中的FK是可以为空的,否则表之间会有竞争条件。

编辑:正如SpectralGhost指出的那样,我的原始代码不支持多行,这一行会做:

CREATE TRIGGER trgAfterInsertA ON TableA
FOR INSERT
AS  

DECLARE db_cursor CURSOR FOR
SELECT id FROM INSERTED

DECLARE @an_id int

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @an_id   
WHILE @@FETCH_STATUS = 0
BEGIN

INSERT INTO TableB VALUES(VALUE_PLACEHOLDER)

UPDATE TableA
SET b_id = SCOPE_IDENTITY()
WHERE id = @an_id

FETCH NEXT FROM db_cursor INTO @an_id  
END

GO

VALUE_PLACEHOLDER是使用。初始化TableB的值。