INSERT到另一个表中的表和UPDATE外键(Sql Server 2008)

时间:2016-07-29 09:10:55

标签: sql sql-server-2008 insert foreign-keys

我有两个表,TableATableB,如下所示:

TableA
-------------------------------------------
|  id  |  some_data  | new_FK_column_on_B |
| ---- | ----------- | ------------------ |
|   1  |     ...     |        null        |
|  ... |     ...     |        null        |
|  999 |     ...     |        null        |
-------------------------------------------

TableB
----------------------
|  id  |  some_data  |
| ---- | ----------- |
|      |             |
----------------------

目前,TableB为空,TableA中的FK列为null所有行。我需要编写一次性初始化scrit以填充TableB,并在TableA中通过插入TableB的行中的标识符初始化某些行(标准,而不是所有行)的FK列。 / p>

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

1)使用whilescope_identity(),在TableB中插入新行并在每次迭代时更新TableA,同时在TableA中存在行,更新

while (exists (select 1 from TableA where [condition]))
begin
    insert into TableB (some_data) values ('some_data')

    update TableA set new_FK_column_on_B
    where id = (select top 1 id from TableA where [condition])
end

2)在TableB中创建临时列,在id中存储TableA行,为其插入,然后使用TableA更新join

alter table TableB add temp int
go

insert into TableB (some_data, temp) select 'some_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

此外,我试图以某种方式使用output这样的insert,但它的语法不正确:

update TableA
set new_FK_column_on_B =
(
    select insertedId from 
    (
        insert into TableB (some_data)
        output inserter.id as insertedId
        values ('some_data')
    )
)
where [condition]

有没有更简单的方法可以在不使用while或修改任何表格的情况下执行此操作?

3 个答案:

答案 0 :(得分:0)

您可以执行以下操作:

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;

这假设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;

不需要while循环。

答案 1 :(得分:0)

免责声明:我没有经过测试,我在记事本中写道:

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

注意:我在内存表中使用,但是如果你担心内存使用情况,你可能只需将它们转换为磁盘上的临时表。

我想去的想法:

  1. 抓取表A(ID +数据)中的行,我们将用它来填充B并存储它们(我使用的是内存表)
  2. 将这些行插入B并存储相应的B ID(再次在内存表中)
  3. 我假设内存表中的两行中的行顺序现在都匹配,所以我们的想法是我们可以将两个内存表一起加入行号以获得表A Id及其表B Id - 其中我们用来更新表A的外键。
  4. 如果上面的代码示例按原样工作,我会非常惊讶,但希望这个想法有用,如果不是我的执行。

答案 2 :(得分:0)

我在寻找类似案例的解决方案时发现了这个问题。唯一的区别是,我想在TableB中为TableA中的每一行填充一行(无子句)。

我找到了建议的第三个选项的解决方案(使用insert的输出),但是,由于将INSERT与SELECT中的数据一起使用,因此无法使用OUTPUT子句。 This为我指明了正确的方向:

DECLARE @MyTableVar table(tableBId int, tableAId int)

MERGE INTO TableB
using TableA AS AP
on 1=0
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)

我还没有尝试为您的情况运行此确切的脚本,但是距离应该不会太远。