web-dev-qa-db-ja.com

IDENTITYを保持したまま別のテーブルに行を挿入する

SQL ServerテーブルでETLロジックを実行しています。あるテーブルから別のテーブルにデータを同期します。ソーステーブルに基づいてターゲットテーブルに追加する必要のあるすべてのレコードについて、ターゲットテーブルのそれらの行で挿入を行っています。スキーマは、列の1つをID列として定義します。したがって、SQL Serverは、挿入される新しい行のIDを自動的にインクリメントします。既存のIDを移動しているので、IDを削除し、それらの行を挿入してから、IDを再適用し、シードをリセットしてソーステーブルと一致させる必要があります。これをプログラムでどのように行うことができますか?

  1. 既存の列からID宣言を削除できますか?
  2. 既存の列をIDとしてマークできますか?
  3. ID列のシードをリセットするにはどうすればよいですか?
3
MacGyver

自動的に重複が防止されるわけではありませんが、以下を使用して一時的にIDを無効にすることができます。その場合、IDシードをテーブル内の最も高い値に設定することになるでしょう。

 SET IDENTITY_INSERT dbo.tablename ON;

 INSERT ...

 SET IDENTITY_INSERT dbo.tablename OFF;

 DECLARE @sql NVARCHAR(MAX);

 SELECT @sql = N'DBCC CHECKIDENT(''dbo.tablename'', RESEED, '
   + RTRIM(MAX(id_column_name)) + ');' FROM dbo.tablename;

 EXEC sp_executesql @sql;

重複を修正するための最善の策は何なのかわかりません。再シード後に1000個の新しい行を挿入すると、ソースシステムが競合する新しいID値を生成する可能性があります。あなたがすることを検討するかもしれないことは、他のテーブルがこれまで到達できない範囲(例えば10億)をはるかに超える数を生成するためにアイデンティティ値の1つを単に設定することです。引き続き使用できますIDENTITY_INSERTマージしますが、競合することはありません。これにより、行がローカルで生成されたか、インポートされたかを非常に簡単に判別できます。

14
Aaron Bertrand

簡単なテストの後、列を変更してIDプロパティを削除できませんでした。これはうまくいくと思いましたが、そうではありません。

ALTER TABLE dbo.FOO 
ALTER COLUMN myId int;

IDプロパティを既存の列に追加することはできません。 SQL Server 2012では、 [〜#〜] sequence [〜#〜] オブジェクトを使用して同じ動作を実行できますが、IDにはなりません

-- does not work
ALTER TABLE dbo.FOO 
ALTER COLUMN myId int identity(1,1);

ID値をリセットするには、RESEEDを指定した DBCC CHECKIDENT に関心があります。

DBCC CHECKIDENT ("dbo.FOO", RESEED, 123456);

そうは言っても、シナリオでアイデンティティプロパティを削除することはありません。単純に IDENTITY_INSERT をターゲットテーブルに設定し、データをロードして完了したら、ソーステーブルと一致するように再シードします。

2
billinkc

ロード後にマージするテーブルのIDを本当に一致させる必要がありますか?それとも、子レコードを取得して適切に関連付けるためだけに必要ですか?子tbalesを適切に関連付けるためだけに使用する場合、これは私たちが時々使用したプロセスです。

すべてのデータを作業テーブルにステージングします。他のテーブルのIDの列を、ロード先のテーブルに追加します。

プロセスに、親テーブルのIDを使用して新しいレコードを作成させます。

追加した列を結合して、新しいIDを使用するようにステージングされた子テーブルを更新します。

プロセスに子テーブルをロードさせます。

0
HLGEM