11

新しいデータベースに移行する古いデータベースがあります。新しいものには、わずかに異なるスキーマがありますが、ほとんど互換性があります。さらに、すべてのテーブルの番号をゼロから変更したいと考えています。

現在、古いレコードを手動で取得し、それを新しいデータベースに挿入し、古いデータベースの v2 ID フィールドを更新して、新しいデータベースの対応する ID の場所を表示するツールを使用しています。

たとえば、MV5.Posts から選択して MV6.Posts に挿入しています。挿入時に、MV6.Posts の新しい行の ID を取得し、古い MV5.Posts.MV6ID フィールドで更新します。

すべてのレコードを手動で処理する必要がないように、INSERT INTO SELECT FROM を介してこの UPDATE を行う方法はありますか? SQL Server 2005 の開発版を使用しています。

4

7 に答える 7

10

移行で重要なことは、いくつかのことを行うことです。まず、現在のバックアップがなければ何もしないでください。第 2 に、キーが変更される場合は、新しい構造に古いものと新しいものの両方を少なくとも一時的に格納する必要があります (ユーザーが古いレコードを取得するためにキー フィールドを検索している可能性があるため、キー フィールドがユーザーに公開されている場合)。

次に、子テーブルへの関係を完全に理解する必要があります。キー フィールドを変更すると、関連するすべてのテーブルも変更する必要があります。ここで、古いキーと新しいキーの両方を保管しておくと便利です。それらのいずれかを変更するのを忘れると、データは正しくなくなり、役に立たなくなります。したがって、これは重要なステップです。

特に複雑なデータのテスト ケースをいくつか選び、関連するテーブルごとに 1 つ以上のテスト ケースを含めるようにします。既存の値を作業テーブルに格納します。

移行を開始するには、古いテーブルからの選択を使用して新しいテーブルに挿入します。レコードの量によっては、(一度に 1 つのレコードではなく) バッチをループしてパフォーマンスを向上させることができます。新しいキーが ID の場合は、古いキーの値をそのフィールドに入力するだけで、データベースに新しいキーを作成させます。

次に、関連するテーブルで同じことを行います。次に、テーブル内の古いキー値を使用して、外部キー フィールドを次のように更新します。

Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield

テスト ケースを実行し、データを移行前に保存したものと比較して、移行をテストします。移行データを徹底的にテストすることは非常に重要です。そうしないと、データが古い構造と一致していることを確認できません。移行は非常に複雑なアクションです。時間をかけて非常に系統的かつ徹底的に行うことには価値があります。

于 2009-04-13T13:56:58.347 に答える
5

おそらく最も簡単な方法は、MV6.Posts に oldId の列を追加し、古いテーブルのすべてのレコードを新しいテーブルに挿入することです。最後に、新しいテーブルの oldId に一致する古いテーブルを次のように更新します。

UPDATE mv5.posts
SET newid = n.id
FROM mv5.posts o, mv6.posts n 
WHERE o.id = n.oldid

必要に応じて、後で oldId 列をクリーンアップして削除できます。

于 2009-04-12T22:44:11.897 に答える
3

私が知っている最善の方法は、output 句を使用することです。SQL 2005 または 2008 を使用しているとします。

USE AdventureWorks;
GO
DECLARE @MyTableVar table( ScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

元のテーブルを更新するには、2 回目のパスが必要です。ただし、ロジックを単純化するのに役立つ場合があります。ソース テーブルを更新する必要がありますか? 新しい ID を 3 番目の相互参照テーブルに格納するだけです。

于 2009-04-12T22:33:49.877 に答える
2

へー。移行でこれを行ったことを覚えています。

新しいテーブルに old_id を入れると、更新が簡単になり、 , を実行するだけで済みinsert into newtable select ... from oldtable、その後のレコードの「ステッチング」も簡単になります。「ステッチ」では、新しい親 ( insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild) で副選択を実行して挿入で子テーブルの外部キーを更新するか、子を挿入して別の更新を実行して外部キーを修正します。

1回の挿入で行う方が高速です。別のステップでそれを行うと、挿入は順序に依存せず、必要に応じてやり直すことができます。

移行後、列を削除するかold_id、レガシー システムで ID が公開されていて、ユーザーがキーをデータとして使用していた場合は、それらを保持して、old_id に基づくルックアップを使用できるようにすることができます。

実際、外部キーが正しく定義されている場合は、systables/information-schema を使用して挿入ステートメントを生成できます。

于 2009-04-12T22:40:00.970 に答える
2

すべてのレコードを手動で処理する必要がないように、INSERT INTO SELECT FROM を介してこの UPDATE を行う方法はありますか?

手動ではなく自動的に実行したいので、に挿入すると自動的に発生するMV6.Postsようにon のトリガーを作成します。UPDATEMV5.PostsMV6.Posts

そして、トリガーは次のようになります。

create trigger trg_MV6Posts
on MV6.Posts
after insert
as
begin
    set identity_insert MV5.Posts on

    update  MV5.Posts
    set ID = I.ID
    from    inserted I

    set identity_insert MV5.Posts off
end
于 2009-04-12T22:50:01.977 に答える
1

私の知る限り、単一のSQLステートメントで2つの異なるテーブルを更新することはできません

ただし、トリガーを使用して、やりたいことを達成できます。

于 2009-04-12T22:33:32.733 に答える
1

MV6.Post.OldMV5Id に列を作る

MV6.Post への挿入 MV5.Post からの選択 ..

次に、MV5.Post.MV6ID を更新します。

于 2009-04-12T22:44:53.657 に答える