Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用PK反馈循环复制行_Sql_Sql Server 2005 - Fatal编程技术网

Sql 使用PK反馈循环复制行

Sql 使用PK反馈循环复制行,sql,sql-server-2005,Sql,Sql Server 2005,鉴于以下情况(表1): 我想将Field1和Field2的值插入另一个表(表2)。表2有一个自动递增整数主键。我想从表2中检索新的PKs并更新上面的Id列(表1) 我意识到这不是常规做法——这不是我需要经常做的事情,只是一些迁移工作的一次性工作。我尝试使用插入、输出、插入.Id,但失败。“环回”到表1中的PK必须与插入的Field1/Filed2的值相关联。假设您完全控制架构定义,请向表2添加一个外键,该外键引用表1的主键。 执行数据插入: INSERT INTO Table2 (Field1,

鉴于以下情况(表1):

我想将Field1和Field2的值插入另一个表(表2)。表2有一个自动递增整数主键。我想从表2中检索新的PKs并更新上面的Id列(表1)


我意识到这不是常规做法——这不是我需要经常做的事情,只是一些迁移工作的一次性工作。我尝试使用
插入、输出、插入.Id
,但失败。“环回”到表1中的PK必须与插入的Field1/Filed2的值相关联。

假设您完全控制架构定义,请向表2添加一个外键,该外键引用表1的主键。
执行数据插入:

INSERT INTO Table2 (Field1, Field2, T1PK)
SELECT Field1, Field2, PK FROM Table1
然后回填表1:

UPDATE t1 SET Id = t2.PK
FROM Table1 t1 INNER JOIN Table2 t2 ON t2.T1PK = t1.PK
然后从表2中删除额外的列(
T1PK

编辑:

由于
Table1
中没有PK,只需在
Table1
中添加一个PK,使用它,然后将其放在末尾

例如

ALTER TABLE Table1 ADD COLUMN T1PK UNIQUEIDENTIFIER CONSTRAINT Table1_PK PRIMARY KEY DEFAULT NEWID();

ALTER TABLE Table2 ADD COLUMN T1PK UNIQUEIDENTIFIER NULL

INSERT INTO Table2 (Field1, Field2, T1PK)
SELECT Field1, Field2, T1PK FROM Table1

UPDATE t1 SET Id = t2.PK
FROM Table1 t1 INNER JOIN Table2 t2 ON t2.T1PK = t1.T1PK

ALTER TABLE Table1 DROP CONSTRAINT Table1_PK

ALTER TABLE Table1 DROP COLUMN T1PK

ALTER TABLE Table2 DROP COLUMN T1PK

您应该能够先插入,然后删除并重新插入

create table t1
( id int, f1 int, f2 int);

create table t2
( id int primary key IDENTITY , f1 int, f2 int);

insert into t1 (id, f1, f2) values (null, 1, 2);    
insert into t1 (id, f1, f2) values (null, 3, 4);
insert into t1 (id, f1, f2) values (null, 5, 6);
insert into t1 (id, f1, f2) values (null, 5, 6);

insert into t2 (f1, f2) 
select f1, f2 from t1 where id is null;

delete t1 
  from t1 join t2 on (t1.f1 = t2.f1 and t1.f2 = t2.f2);

insert into t1
select id, f1, f2 from t2;

select * from t1;

请参见上的示例。

您需要某种类型的唯一键来匹配每个表中的行。我已经在每个表中添加了一个TempGuid列(以后可以删除该列):

如果您在表1上已经有一个要插入到表2中的唯一键,
输出将是可行的。您也可以在循环或游标中执行一个临时唯一键(可能再次使用GUID),然后一次处理一行,但这对我来说似乎更糟

更新

以下是要在表上运行的实际SQL:

-- Add TempGuid columns
alter table Table1 add TempGuid uniqueidentifier null
update Table1 set TempGuid = newid()
alter table Table2 add TempGuid uniqueidentifier not null

-- Fill Table2
insert into Table2 (Field1, Field2, TempGuid)
select Field1, Field2, TempGuid
from Table1

-- Update Table1 with the identity values from Table2
update a
set a.Id = b.Id
from Table1 a
    join Table2 b on a.TempGuid = b.TempGuid

-- Remove TempGuid columns
alter table Table1 drop column TempGuid
alter table Table2 drop column TempGuid

这并不漂亮,但应该一次性完成

create table tableA
(
id int,
field1 int,
field2 int
)

create table tableB
(
id int identity(1,1),
field1 int,
field2 int
)

insert into tableA select NULL, 1, 2
insert into tableA select NULL, 2, 3

declare @field1_value int;
declare @field2_value int;
declare @lastInsertedId int;

DECLARE tableA_cursor CURSOR FOR 
    select field1, field2 from tableA

    OPEN tableA_cursor
    FETCH NEXT FROM tableA_cursor INTO @field1_value, @field2_value 

    WHILE @@FETCH_STATUS = 0
    BEGIN

        insert into tableB select @field1_value, @field2_value
        set @lastInsertedId = (SELECT SCOPE_IDENTITY())
        update a
            set id = @lastInsertedId
            from tableA a
        where field1 = @field1_value
            and field2 = @field2_value
    print @field1_value

    FETCH NEXT FROM tableA_cursor 
    INTO @field1_value, @field2_value
    END
CLOSE tableA_cursor
DEALLOCATE tableA_cursor
不存在检查时:

declare @field1_value int;
declare @field2_value int;
declare @lastInsertedId int;

DECLARE tableA_cursor CURSOR FOR 
    select field1, field2 from tableA

    OPEN tableA_cursor
    FETCH NEXT FROM tableA_cursor INTO @field1_value, @field2_value 

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF NOT EXISTS    
            (
                select * from tableB 
                where field1 = @field1_value 
                and field2 = @field2_value   
            )    
            BEGIN
                insert into tableB 
                select @field1_value, @field2_value

                set @lastInsertedId = (SELECT SCOPE_IDENTITY())

                update a
                    set id = @lastInsertedId
                    from tableA a
                where field1 = @field1_value
                    and field2 = @field2_value
            END     

    FETCH NEXT FROM tableA_cursor 
    INTO @field1_value, @field2_value
    END
CLOSE tableA_cursor
DEALLOCATE tableA_cursor

在每次插入到表2中之后,可能会出现“SELECT SCOPE_IDENTITY()”?您在插入到/OUTPUT/Inserted.Id时使用了什么代码?你应该能够让它工作。Field1/Field2是否能生成唯一的键?Tim-不,Field1/Field2不能保证生成唯一的键。因此必须有某种inserts.mwigdahl顺序的内存-insert-into Table2(Field1,Field)OUTPUT Inserted.Id into Table1从Table1中选择Field1,Field2。在他的例子中,表1没有主键——ID字段为空,他需要对其进行回填。问题是我的字段没有创建唯一的值集。即使他们这么做了,我也必须为他们编制索引。想象一个包含许多字段的大表。这是否排除了你的答案?@SFun28-你说“Field1”和“Field2”的组合不是唯一的,但就数据库而言,它们是相同的。我想您必须删除“重复”行,因为您无法将它们识别为与任何其他匹配行不同。@SFun28您不必对所有行进行索引-在这种情况下,完全扫描可能更好,因为您正在将记录从一个表加载到另一个表,并对所有列进行筛选。多个索引扫描会很慢,一次完整扫描就可以了。如果字段不唯一,可以尝试插入记录,然后从表1中删除并重新插入。我会更新我的答案。如果您只需要插入表A中的唯一组合,那么在插入之前,我们只需要添加“不存在”复选框;我将在我的答案中添加此变体。
create table tableA
(
id int,
field1 int,
field2 int
)

create table tableB
(
id int identity(1,1),
field1 int,
field2 int
)

insert into tableA select NULL, 1, 2
insert into tableA select NULL, 2, 3

declare @field1_value int;
declare @field2_value int;
declare @lastInsertedId int;

DECLARE tableA_cursor CURSOR FOR 
    select field1, field2 from tableA

    OPEN tableA_cursor
    FETCH NEXT FROM tableA_cursor INTO @field1_value, @field2_value 

    WHILE @@FETCH_STATUS = 0
    BEGIN

        insert into tableB select @field1_value, @field2_value
        set @lastInsertedId = (SELECT SCOPE_IDENTITY())
        update a
            set id = @lastInsertedId
            from tableA a
        where field1 = @field1_value
            and field2 = @field2_value
    print @field1_value

    FETCH NEXT FROM tableA_cursor 
    INTO @field1_value, @field2_value
    END
CLOSE tableA_cursor
DEALLOCATE tableA_cursor
declare @field1_value int;
declare @field2_value int;
declare @lastInsertedId int;

DECLARE tableA_cursor CURSOR FOR 
    select field1, field2 from tableA

    OPEN tableA_cursor
    FETCH NEXT FROM tableA_cursor INTO @field1_value, @field2_value 

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF NOT EXISTS    
            (
                select * from tableB 
                where field1 = @field1_value 
                and field2 = @field2_value   
            )    
            BEGIN
                insert into tableB 
                select @field1_value, @field2_value

                set @lastInsertedId = (SELECT SCOPE_IDENTITY())

                update a
                    set id = @lastInsertedId
                    from tableA a
                where field1 = @field1_value
                    and field2 = @field2_value
            END     

    FETCH NEXT FROM tableA_cursor 
    INTO @field1_value, @field2_value
    END
CLOSE tableA_cursor
DEALLOCATE tableA_cursor