繁体   English   中英

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

[英]INSERT into table and UPDATE foreign key in another table (Sql Server 2008)

我有两个表, TableATableB像这样:

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)使用whilescope_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

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

我想去的想法:

  1. 从表A(ID +数据)中获取行,我们将使用它来填充B并存储它们(我使用的是内存表)
  2. 将这些行插入B并存储相应的B ID(再次存入内存表中)
  3. 我假设内存表中的两个行的顺序现在都匹配,所以我们的想法是我们可以将两个内存表一起连接到行号上以获得表A Id和它的表B Id - 我们用它来更新表A的外来键。

如果上面的代码示例按原样工作,我会非常惊讶,但希望这个想法有用,如果不是我的执行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM