ds1*_*709 5 sql foreign-keys insert sql-server-2008
我有两个表,TableA而TableB像这样:
TableA
-------------------------------------------
| id | some_data | new_FK_column_on_B |
| ---- | ----------- | ------------------ |
| 1 | ... | null |
| ... | ... | null |
| 999 | ... | null |
-------------------------------------------
TableB
----------------------------
| id | some_other_data |
| ---- | ----------------- |
| | |
----------------------------
Run Code Online (Sandbox Code Playgroud)
此刻,TableB是空的,FK列TableA是null对所有行。我需要编写一次初始化脚本TableB,以便TableA通过插入的行中的标识符填充和初始化某些行(标准的,不是全部)的FK列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
Run Code Online (Sandbox Code Playgroud)
2)在中创建临时列,在TableB中存储id行TableA,为此插入临时行,然后TableA使用更新join
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
Run Code Online (Sandbox Code Playgroud)
我也试图以某种方式使用output从insert这样的,但它的语法不正确:
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]
Run Code Online (Sandbox Code Playgroud)
有没有更简单的方法可以在不使用while或修改任何表的情况下进行此操作?
我在寻找类似案例的解决方案时发现了这个问题。唯一的区别是我想为 TableA 中的每一行填充一行(没有 where 子句)。
我找到了您建议的第三个选项的解决方案(使用 insert 的输出),但是,由于您对来自 SELECT 的数据使用 INSERT,因此不能使用 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)
Run Code Online (Sandbox Code Playgroud)
请注意,执行此操作几秒钟将在 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;
Run Code Online (Sandbox Code Playgroud)
Gor*_*off -1
您可以将所有这些作为集合操作来完成:
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;
Run Code Online (Sandbox Code Playgroud)
这假设id中的列b被声明为identity(),因此它会自动分配。这是一个好主意,但如果您想手动执行此操作,那么第一个查询将类似于:
insert into b(some_data)
select row_number() over (order by (select null)), some_data
from (select distinct some_data
from a
) a;
Run Code Online (Sandbox Code Playgroud)
不需要循环while。