6

对于表 AI 中的每条记录,希望根据表 B 中新插入记录的 scope_identity 更新其中一个字段的外键值。

我需要在表 B 中为表 A 中的每条记录创建一个新记录,以便接收外键(scope_identity)值。

例如,对于下表中的每一行,我想根据在表 B 中创建新的行/外键来更新空外键字段。

表 A:

|Id|ForeignKey|
|1 |NULL      |
|2 |NULL      |
|3 |NULL      |
|4 |NULL      |
|5 |NULL      |

作为伪代码,我想到了类似这样的 sql:

update TableA 
set ForeignKey = (INSERT INTO TableB VALUES (value1) select SCOPE_IDENTITY())

任何想法?

4

3 回答 3

6

您可以使用游标遍历 TableA 并创建记录:

DECLARE @Id int
DECLARE @ForeignKey int

DECLARE C CURSOR FOR SELECT Id FROM TableA

OPEN C

FETCH NEXT FROM C INTO @Id

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO TableB VALUES (value1)
    SET @ForeignKey = SCOPE_IDENTITY()

    UPDATE TableA
    SET ForeignKey = @ForeignKey
    WHERE Id = @Id

    FETCH NEXT FROM C INTO @Id
END

CLOSE C
DEALLOCATE C
于 2012-07-29T17:06:48.470 回答
0

在 SQL Server 2008 及更高版本中执行与 INSERT 相关的 UPDATE 的基于集合的方法是使用MERGE...OUTPUT语句。

-- This table variable will hold the correlation between the two tables
declare @NewLinks table (dst_id int, src_id int)

merge TableB dst
using TableA src
    on 1 = 0 --inserts all from src into dst, add WHERE-like limit here
when not matched --should never match, since this is an INSERT-like query
    insert (<dst_column_list>) values (<src_column_list>)
output INSERTED.<dst_surrogate_key>, src.<src_surrogate_key>
into @NewLinks

update src
set src.ForeignKey = nl.dst_id
from TableA src
join @NewLinks nl
    on nl.src_id = src.Id

由于 INSERT 语句(即使在 INSERT...SELECT 形式中)没有 FROM 子句,from_table_name因此无法在其 OUTPUT 子句中引用以捕获完整的相关性。由于 MERGE 始终将其 USING 子句视为 FROM 子句,因此它可用于模仿 INSERT...SELECT 构造,同时提供对 OUTPUT 中源表和目标表的访问权限。

使用 MERGE...OUTPUT 创建与 INSERT 相关的 UPDATE 以维护单个临时表或表值变量来替换使用游标或循环的 RBAR 解决方案的低效使用。

于 2015-03-30T20:39:46.203 回答
0

我发现的另一种方法是使用ROW_NUMBER 函数任意连接表,然后使用该派生查询来更新 FK。我们的想法是tableA 和 tableB之间还没有关系,我们只需要链接它们来获取新的外键。将它们加入到 ROW_NUMBER 之类的任意对象上,我们可以从中挑选出一行来获取 Id。

首先创建新记录

INSERT INTO TableB VALUES (value1)

在 ROW_NUMBER 上编写任意连接它们的查询(我们在下一步中使用它)

SELECT
    tableARows.Id, 
    tableBRows.TheNewId
FROM
(
    SELECT Id, Row =  ROW_NUMBER() OVER (ORDER BY Id) FROM tableA
)tableARows INNER JOIN
(
    SELECT TheNewId, Row = ROW_NUMBER() OVER (ORDER BY TheNewId) FROM tableB
)tableBRows ON tableARows.Row = tableBRows.Row

然后是一个完整的 UPDATE 语句,用来自 tableB 的新 FK 填充 tableA

UPDATE tableA 
SET tableA.ForeignKey = LinkedKeys.TheNewId
FROM
(
    SELECT
        tableARows.Id, 
        tableBRows.TheNewId
    FROM
    (
        SELECT Id, Row =  ROW_NUMBER() OVER (ORDER BY Id) FROM tableA
    )tableARows INNER JOIN
    (
        SELECT TheNewId, Row = ROW_NUMBER() OVER (ORDER BY TheNewId) FROM tableB
    )tableBRows ON tableARows.Row = tableBRows.Row
)LinkedKeys INNER JOIN
tableA  ON tableA.Id = LinkedKeys.Id

这是我使用的示例表定义。

CREATE TABLE tableA (Id INT, ForeignKey INT)
INSERT INTO tableA VALUES (100,NULL),(200,NULL),(300,NULL)


CREATE TABLE tableB (TheNewId INT)
INSERT INTO tableB VALUES(5000),(6000),(7000)
于 2020-01-10T16:34:41.227 回答