1

我正在尝试复制表中的记录并使用 SQL Server 2005 中的存储过程更改一些值。这很简单,但我还需要使用新的主键复制其他表中的关系。由于这个过程被用来批量复制记录,我发现很难存储旧键和新键之间的一些关系。现在,我正在使用 OUTPUT INTO 从批量插入中获取新密钥。前任:

INSERT INTO table
 (column1, column2,...)
 OUTPUT INSERTED.PrimaryKey INTO @TableVariable
 SELECT column1, column2,...

有没有这样的方法可以在我插入新密钥的同时轻松插入旧密钥(以确保我已经配对了正确的相应密钥)?

我知道光标是一种选择,但我从未使用过它们,只听说过以恐怖故事的方式引用它们。我更喜欢使用 OUTPUT INTO 或类似的东西。

4

2 回答 2

4

如果您需要跟踪临时表中的新旧密钥,则需要作弊并使用MERGE

数据设置:

create table T (
    ID int IDENTITY(5,7) not null,
    Col1 varchar(10) not null
);
go
insert into T (Col1) values ('abc'),('def');

并替换您的INSERT声明:

declare @TV table (
    Old_ID int not null,
    New_ID int not null
);
merge into T t1
using (select ID,Col1 from T) t2
on 1 = 0
when not matched then insert (Col1) values (t2.Col1)
output t2.ID,inserted.ID into @TV;

并且(实际上需要在同一批次中,以便您可以访问表变量):

select * from T;
select * from @TV;

产生:

ID  Col1
5   abc
12  def
19  abc
26  def

Old_ID  New_ID
5       19
12      26

您必须这样做的原因是因为使用 with 时对OUTPUT子句INSERT的一个令人讨厌的限制- 您只能访问该inserted表,而不能访问任何可能属于SELECT.


MERGE相关 -滥用的更多解释

于 2013-05-02T06:24:13.820 回答
0

INSERT将数据加载到具有IDENTITY列的表中的语句保证以ORDER BYSELECT.

如果您希望按照 ORDER BY 子句中的顺序以顺序方式分配 IDENTITY 值,请创建一个包含具有 IDENTITY 属性的列的表,然后运行 ​​INSERT .. SELECT ... ORDER BY 查询来填充此表.

From:与 SELECT INTO 或 INSERT 一起使用时 IDENTITY 函数的行为 .. 包含 ORDER BY 子句的 SELECT 查询

您可以使用此事实将您的旧身份值与新身份值相匹配。首先收集您打算复制到临时表中的主键列表。如果需要,您还可以包含修改后的列值:

select
    PrimaryKey,
    Col1
    --Col2... etc
into #NewRecords
from Table
--where whatever...

然后INSERT使用OUTPUT子句将您的新 id 捕获到表变量中:

declare @TableVariable table (
    New_ID int not null
);

INSERT INTO #table
    (Col1 /*,Col2... ect.*/)
OUTPUT INSERTED.PrimaryKey INTO @NewIds
SELECT Col1 /*,Col2... ect.*/
from #NewRecords
order by PrimaryKey

由于该ORDER BY PrimaryKey声明,您将保证您的编号将按照与复制记录New_ID的字段相同的顺序生成。PrimaryKey现在,您可以通过按 ID 值排序的行号来匹配它们。以下查询将为您提供配对:

select PrimaryKey, New_ID
from
    (select PrimaryKey, 
        ROW_NUMBER() over (order by PrimaryKey) OldRow
    from #NewRecords
    ) PrimaryKeys
join
    (
    select New_ID, 
        ROW_NUMBER() over (order by New_ID) NewRow
    from @NewIds
    ) New_IDs
on OldRow = NewRow
于 2015-07-20T19:25:19.233 回答