插入表并在另一个表中更新UPDATE外键(SQL Server 2008)

ds1*_*709 5 sql foreign-keys insert sql-server-2008

我有两个表,TableATableB像这样:

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列TableAnull对所有行。我需要编写一次初始化脚本TableB,以便TableA通过插入的行中的标识符填充和初始化某些行(标准的,不是全部)的FK列TableB

我知道两种方法可以做到这一点:

1)使用whilescope_identity(),将新行插入TableBTableA在每次迭代中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中存储idTableA,为此插入临时行,然后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)

我也试图以某种方式使用outputinsert这样的,但它的语法不正确:

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或修改任何表的情况下进行此操作?

Eir*_*ske 6

我在寻找类似案例的解决方案时发现了这个问题。唯一的区别是我想为 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