简体   繁体   English

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

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

I have two tables, TableA and TableB like this: 我有两个表, TableATableB像这样:

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

TableB
----------------------------
|  id  |  some_other_data  |
| ---- | ----------------- |
|      |                   |
----------------------------

At the moment, TableB is empty, and FK column in TableA is null for all rows. 目前, TableB为空, TableA FK列对所有行都为null I need to write one-time initializing scrit to populate TableB and initialize FK column for some rows (criterial, not for all) in TableA by identifiers from rows, inserted in TableB . 我需要一次性初始化scrit填充写TableB和初始化一些行(严格标准,不是所有)在FK列TableA的标识从行插入TableB

I know two ways to do this: 我知道有两种方法可以做到这一点:

1) using while and scope_identity() , inserting new row into TableB and updating TableA on each iteration, while exists rows in TableA , which should be updated 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) create temp column in TableB , storing id of row in TableA , for which it was inserted, and then update TableA using join 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

Also I was trying to use somehow output from insert like this, but it's syntax is incorrect: 另外我试图以某种方式使用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]

Is there any easier way to do this whithout using while or modifing any table? 有没有更简单的方法来做这个while使用或修改任何表?

I found this question when searching for a solution a similar case. 在寻找类似案例的解决方案时,我发现了这个问题。 The only difference was that I wanted to fill TableB with an row for each row in TableA (no where-clause). 唯一的区别是我想用TableA中的每一行填充TableB(没有where子句)。

I found a solution to the third option you suggeted (using output from insert), however, since you are using INSERT with data from a SELECT, you cannot use the OUTPUT clause. 我找到了你建议的第三个选项的解决方案(使用insert的输出),但是,由于你使用INSERT和SELECT中的数据,你不能使用OUTPUT子句。 This pointed me in the right direction: 这使我指出了正确的方向:

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)

Be aware that executing this a seconds time will create new entries in TableB. 请注意,执行此秒时间将在TableB中创建新条目。 If you only want to create new rows in TableB, where there is no foreign key set in TableA, you can use this script: 如果您只想在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;

You can do all this as set operations: 你可以做所有这些作为设置操作:

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;

This assumes that the id column in b is declared as identity() , so it gets assigned automatically. 这假设b中的id列声明为identity() ,因此它会自动分配。 This is a good idea, but if you want to do this manually, then the first query would be something like: 这是一个好主意,但如果你想手动完成,那么第一个查询就像:

insert into b(some_data)
    select row_number() over (order by (select null)), some_data
    from (select distinct some_data
          from a
         ) a;

There is no need for a while loop. 不需要while循环。

DISCLAIMER: This is not tested at all, I wrote this in notepad: 免责声明:我没有经过测试,我在记事本中写道:

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

Note: I am using In memory tables, but if you were concerned about memory usage, you could probably just switch those out for temp tables on disk. 注意:我在内存表中使用,但是如果你担心内存使用情况,你可能只需将它们转换为磁盘上的临时表。

The idea I was going for here: 我想去的想法:

  1. Grab the rows from table A (ID + data) that we will use to populate B and store them (I am using an In memory table) 从表A(ID +数据)中获取行,我们将使用它来填充B并存储它们(我使用的是内存表)
  2. Insert those rows into B and store the corresponding ID of B (again in an in memory table) 将这些行插入B并存储相应的B ID(再次存入内存表中)
  3. I assume the order of rows in both in memory tables will now match, so the idea is that we can join both in memory tables together on row number to get Table A Id with it's Table B Id - which we use to update table A's foreign key. 我假设内存表中的两个行的顺序现在都匹配,所以我们的想法是我们可以将两个内存表一起连接到行号上以获得表A Id和它的表B Id - 我们用它来更新表A的外来键。

I'd be very surprised if my code sample above works as is, but hopefully the idea will be useful, if not my execution. 如果上面的代码示例按原样工作,我会非常惊讶,但希望这个想法有用,如果不是我的执行。

暂无
暂无

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

相关问题 SQL插入触发器之前-插入另一个表并更新外键 - SQL Before Insert Trigger - insert into another table and update foreign key SQL Server 2008-在插入/更新时触发将值复制到另一个表的触发器吗? - SQL Server 2008 - On Insert/Update Trigger that copies values to another table? SQL Server 2008:使用主键更新表 - SQL Server 2008 : update the table with primary key 使用来自另一个表的外键将数据插入或更新到表中 - Insert or Update Data into Table with Foreign Key from Another Table 可以更新到ParentTable在SQL SERVER 2008中具有外键关系的子表中查找原因 - Can update to a ParentTable cause lookup in Child table with foreign Key relationship in SQL SERVER 2008 SQL-SERVER 程序如何在一个表中插入行,然后将行插入到另一个表中作为外键链接到另一个表 - SQL-SERVER Procedure How do i insert row one table then insert row into another table link to another table as foreign key 外键约束-写入错误表-SQL Server 2008 - Foreign key Constraints - Writing to Error Table - SQL Server 2008 在临时表中插入另一个表的名称SQL Server 2008 - Insert in a temporal table the names of another table SQL Server 2008 使用 SQL 服务器中另一个表的 id 更新现有表的新外键列 - Update new foreign key column of existing table with ids from another table in SQL Server SQL Server 2008更新表包含另一个表中的值 - SQL Server 2008 update table with values from another table
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM