[英]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.