[英]SQL Before Insert Trigger - insert into another table and update foreign key
[英]INSERT into table and UPDATE foreign key in another table (Sql Server 2008)
我有两个表, TableA
和TableB
像这样:
TableA
-------------------------------------------
| id | some_data | new_FK_column_on_B |
| ---- | ----------- | ------------------ |
| 1 | ... | null |
| ... | ... | null |
| 999 | ... | null |
-------------------------------------------
TableB
----------------------------
| id | some_other_data |
| ---- | ----------------- |
| | |
----------------------------
目前, TableB
为空, TableA
FK列对所有行都为null
。 我需要一次性初始化scrit填充写TableB
和初始化一些行(严格标准,不是所有)在FK列TableA
的标识从行插入TableB
。
我知道有两种方法可以做到这一点:
1)使用while
和scope_identity()
,在TableB
插入新行并在每次迭代时更新TableA
,同时在TableA
存在行,应该更新
while (exists (select 1 from TableA where [condition]))
begin
insert into TableB (some_other_data) values ('some_other_data')
update TableA set new_FK_column_on_B
where id = (select top 1 id from TableA where [condition])
end
2)在TableB
创建临时列,在TableA
存储行的id
,为其插入,然后使用join
更新TableA
alter table TableB add temp int
go
insert into TableB (some_other_data, temp) select 'some_other_data', id from TableA where [condition]
update TableA
set new_FK_column_on_B = b.id
from TableB as b
join TableA as a on a.id = b.temp
alter table TableB drop column temp
另外我试图以某种方式使用insert
output
,但它的语法不正确:
update TableA
set new_FK_column_on_B =
(
select insertedId from
(
insert into TableB (some_other_data)
output inserter.id as insertedId
values ('some_other_data')
)
)
where [condition]
有没有更简单的方法来做这个while
使用或修改任何表?
在寻找类似案例的解决方案时,我发现了这个问题。 唯一的区别是我想用TableA中的每一行填充TableB(没有where子句)。
我找到了你建议的第三个选项的解决方案(使用insert的输出),但是,由于你使用INSERT和SELECT中的数据,你不能使用OUTPUT子句。 这使我指出了正确的方向:
DECLARE @MyTableVar table(tableBId int, tableAId int)
MERGE INTO TableB
using TableA AS AP
on 1=0
WHEN NOT MATCHED THEN
Insert(some_other_data)
Values('some_other_data')
Output inserted.ID, AP.ID INTO @MyTableVar;
update TableA set new_FK_column_on_B = (select tableBId from @MyTableVar where tableAId = TableA.ID)
请注意,执行此秒时间将在TableB中创建新条目。 如果您只想在TableB中创建新行,而TableA中没有设置外键,则可以使用此脚本:
DECLARE @MyTableVar TABLE(tableBId int, tableAId int)
MERGE INTO TableB AS B
USING TableA AS AP
ON A.new_FK_column_on_B = B.id
WHEN NOT MATCHED THEN
INSERT(some_data)
VALUES(AP.some_data)
OUTPUT inserted.ID, AP.ID INTO @MyTableVar;
UPDATE TableA SET new_FK_column_on_B = (
SELECT tableBId
FROM @MyTableVar
WHERE tableAId = TableA.ID )
WHERE TableA.new_FK_column_on_B IS NULL;
你可以做所有这些作为设置操作:
insert into b(some_data)
select distinct some_data
from a;
update a
set new_FK_column_on_B = b.id
from a join
b
on a.some_data = b.some_data;
这假设b
中的id
列声明为identity()
,因此它会自动分配。 这是一个好主意,但如果你想手动完成,那么第一个查询就像:
insert into b(some_data)
select row_number() over (order by (select null)), some_data
from (select distinct some_data
from a
) a;
不需要while
循环。
免责声明:我没有经过测试,我在记事本中写道:
DECLARE @TableAValues TABLE (IdTableA int, SomeData varchar)
INSERT INTO @TableAValues(IdTableA, SomeData)
SELECT id, 'some_data' FROM TableA
DECLARE @TableBIds TABLE (IdTableB int)
INSERT INTO TableB(SomeData)
OUTPUT INSERTED.ID INTO @TableBIds
SELECT SomeData FROM @TableAValues
UPDATE ta
SET ta.new_FK_column_on_B = tbi.IdTableB
FROM dbo.TableA AS ta
INNER JOIN @TableAValues AS tav ON ta.id = tav.IdTableA -- used in case more records were added to table in the interim.
LEFT OUTER JOIN @TableBIds tbi On tav.RowNum = tbi.RowNum
注意:我在内存表中使用,但是如果你担心内存使用情况,你可能只需将它们转换为磁盘上的临时表。
我想去的想法:
如果上面的代码示例按原样工作,我会非常惊讶,但希望这个想法有用,如果不是我的执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.