3

次の場合 (表 1):

Id    Field1  Field2     ...
--    ------  -------
NULL  1        2
NULL  3        4
...

Field1 と Field2 の値を別のテーブル (Table2) に挿入したいと思います。Table2 には、自動インクリメント整数の主キーがあります。Table2 から新しい PK を取得し、上記の Id 列 (Table1) を更新したいと考えています。

これは慣習的ではないことを認識しています。これは、定期的に行う必要があるものではなく、移行作業のために 1 回限りのことです。を使用していくつか試みましINSERT INTO, OUTPUT, INSERTED.Idたが、失敗しました。Table1 に「ループバック」される PK は、挿入された Field1/Filed2 の値に関連付ける必要があります。

4

4 に答える 4

2

各テーブルの行を一致させるには、ある種の一意のキーが必要です。各テーブルに TempGuid 列を自由に追加しました (後で削除できます)。

-- Setup test data
declare @Table1 table (
      Id int null
    , Field1 int not null
    , Field2 int not null
    , TempGuid uniqueidentifier not null unique
)
insert into @Table1 (Field1, Field2, TempGuid) select 1, 2, newid()
insert into @Table1 (Field1, Field2, TempGuid) select 3, 4, newid()

declare @Table2 table (
      Id int not null primary key identity(1, 1)
    , Field1 int not null
    , Field2 int not null
    , TempGuid uniqueidentifier not null unique
)

-- 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

-- Show results
select * from @Table1

OutputTable2 に挿入している Table1 に一意のキーが既にある場合は、実行可能です。ループまたはカーソルで一時的な一意のキー (おそらく GUID) を実行して、一度に 1 行ずつ処理することもできますが、それは私には悪いように思えます。

アップデート

テーブルで実行する実際の 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
于 2012-07-16T14:51:12.423 に答える
2

挿入してから、削除して再挿入できるはずです。

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;

SQLFiddle のこの例を参照してください。

于 2012-07-16T14:35:39.277 に答える
1

スキーマ定義を完全に制御できると仮定して、Table2その参照Table1の主キーに外部キーを追加します。
データの挿入を実行します。

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

次に、Table1 を埋め戻します。

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

次に、余分な列 ( T1PK) を から削除しTable2ます。

編集:

には PK がないのでTable1、 に 1 つ追加しTable1、それを使用して、最後にドロップします。

例えば...

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
于 2012-07-16T14:33:21.370 に答える
0

これはきれいではありませんが、1 回限りの作業として行う必要があります。

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
于 2012-07-16T15:04:59.193 に答える