5

編集:最初に説明したようなXMLの方法があるかどうかわからないので、これを完全に言い換えましょう。

さらに別の編集:これは繰り返し可能なプロセスである必要があり、C# コードで呼び出すことができるように設定できる必要があります。

データベース A には、PK と FK によって関連付けられた一連のテーブルがあります。子テーブルと孫テーブルを持つ親テーブルとしましょう。

データベース A から同じ名前のテーブルとフィールドを持つデータベース B に一連の行をコピーしたいと考えています。各テーブルについて、データベース B の同じテーブルに挿入したいのですが、同じ主キーを使用するように制限することはできません。 コピー ルーチンは、データベース B の各行に対して新しい PK を作成し、それらを子行に伝達する必要があります。つまり、データ間の同じ関係を維持していますが、まったく同じ PK と FK ではありません。

これをどのように解決しますか?私は提案を受け入れます。SSIS が完全に除外されているわけではありませんが、これとまったく同じことを行うようには見えません。また、LINQ でのソリューション、型指定された DataSet の使用、XML の使用、または SQL Server 2005 や C# (.NET 3.5) で動作するほぼすべてのソリューションに対してオープンです。最適なソリューションは、SSIS を必要とせず、多くのコードを記述する必要もありません。しかし、この「最善の」解決策が存在しない可能性があることは認めます。

(私は自分でこのタスクを作成したわけでも、制約を作成したわけでもありません。これが私に与えられた方法です。)

4

11 に答える 11

2

SQL Server ユーティリティのtablediff.exeが探しているものかもしれません。

このスレッドも参照してください。

于 2008-09-30T14:10:26.407 に答える
1

まず、SSIS が最善の策であると言っておきましょう。しかし、あなたが尋ねた質問に答えるために...

新しい ID をあちこちに作成してもうまくいくとは思えませんが、検索に使用するために元の ID を取得する必要があります。

あなたが得ることができる最高のものは、テーブルの挿入ステートメントです。SELECTXML サンプルからデータを取得するために s を実行するコードの例を次に示します。

declare @xml xml 
set @xml='<People Key="1" FirstName="Bob" LastName="Smith">
  <PeopleAddresses PeopleKey="1" AddressesKey="1">
    <Addresses Key="1" Street="123 Main" City="St Louis" State="MO" ZIP="12345" />
  </PeopleAddresses>
</People>
<People Key="2" FirstName="Harry" LastName="Jones">
  <PeopleAddresses PeopleKey="2" AddressesKey="2">
    <Addresses Key="2" Street="555 E 5th St" City="Chicago" State="IL" ZIP="23456" />
  </PeopleAddresses>
</People>
<People Key="3" FirstName="Sally" LastName="Smith">
  <PeopleAddresses PeopleKey="3" AddressesKey="1">
    <Addresses Key="1" Street="123 Main" City="St Louis" State="MO" ZIP="12345" />
  </PeopleAddresses>
</People>
<People Key="4" FirstName="Sara" LastName="Jones">
  <PeopleAddresses PeopleKey="4" AddressesKey="2">
    <Addresses Key="2" Street="555 E 5th St" City="Chicago" State="IL" ZIP="23456" />
  </PeopleAddresses>
</People>
'

select t.b.value('./@Key', 'int') PeopleKey,
    t.b.value('./@FirstName', 'nvarchar(50)') FirstName,
    t.b.value('./@LastName', 'nvarchar(50)') LastName
from @xml.nodes('//People') t(b)

select t.b.value('../../@Key', 'int') PeopleKey,
    t.b.value('./@Street', 'nvarchar(50)') Street,
    t.b.value('./@City', 'nvarchar(50)') City,
    t.b.value('./@State', 'char(2)') [State],
    t.b.value('./@Zip', 'char(5)') Zip
from 
@xml.nodes('//Addresses') t(b)

これが行うことは、XML からノードを取得し、データを解析することです。人々からリレーショナル ID を取得するには、../../ を使用してチェーンを上ります。

于 2008-09-12T16:08:03.533 に答える
0

毎回宛先テーブルをクリアしてから再開していますか?これにより、実装する必要のあるソリューションに大きな違いが生まれます。毎回完全な再インポートを行う場合は、次のようなことを行うことができます。

親テーブルの新旧の主キーを記録するための一時テーブルまたはテーブル変数を作成します。

親テーブルのデータを宛先に挿入し、OUTPUT句を使用して新しいIDをキャプチャし、古いIDとともに一時テーブルに挿入します。注:output句を使用すると効率的であり、挿入する各レコードを循環することなく、一括で挿入を実行できます。

子テーブルデータを挿入します。一時テーブルに参加して、必要な新しい外部キーを取得します。

上記のプロセスは、T-SQLスクリプト、C#コード、またはSSISを使用して実行できます。私の好みはSSISです。

于 2008-09-17T06:00:18.743 に答える
0

毎回追加する場合は、ソースデータベースの主キーと宛先データベースの主キーの間の関係を追跡するために永続的なテーブルを保持する必要がある場合があります(少なくとも親テーブルの場合)。この種のデータを宛先データベースから除外する必要がある場合は、SSISに、ある種のログデータベースまたはフラットファイルからデータを保存/取得させることができます。

親テーブルにそのレコードを一意に識別し、宛先データベースでそのレコードの主キーを「検索」するために使用できるフィールドの組み合わせがある場合は、上記のシナリオを回避できる可能性があります。

于 2008-09-18T00:54:41.747 に答える
0

私は Red Gate の SQL Compare と Data Compare も気に入っていますが、私が知る限り、主キーの変更に関する彼の要件を満たしていません。

クロス データベース クエリ/リンク サーバーがオプションである場合は、DB A の親/子からレコードを DB B の一時テーブルにコピーし、一時子テーブルに新しい主キーの列を追加するストアド プロシージャを使用してこれを行うことができます。ヘッダーを挿入した後に更新します。

私の質問は、レコードが同じ主キーを持っていない場合、それが新しいレコードかどうかをどのように見分けるのですか? 他の候補キーはありますか?これらが新しいテーブルである場合、同じ主キーを持つことができないのはなぜですか?

于 2008-09-13T16:38:31.067 に答える
0

私が使用しようとしているのは、型付きデータセットである可能性が最も高いと思います。これは一般化されたソリューションではありません。いずれかのテーブルが変更された場合は、それらを再生成する必要があります。しかし、私が聞いたことによると、それは問題ではありません。テーブルはあまり変わらないと予想されます。

データセットを使用すると、データを階層的にループし、挿入後にデータベースから PK を更新することがかなり簡単になります。

于 2008-09-18T01:54:45.173 に答える
0

私なら、Insert を使用して難しい作業を行うため、ストアド プロシージャでスクリプトを作成します。あなたのコードはテーブル A から PK を取得します (おそらく @@Scope_Identity 経由) - テーブル A の PK は Identity フィールドだと思いますか?

一時テーブルやカーソルを使用することも、CLR を使用することもできます。この種の操作に適している場合があります。

a) 事前に決定されたキー、または b) ID フィールド (明らかに、表 B と C にはそれらがありません) のいずれかを使用して、これをすぐに実行できるツールを見つけたら、私は驚くでしょう。

于 2008-09-16T11:33:06.953 に答える
0

一連のストアド プロシージャを使用して同じものを作成しました。

データベース B は独自の主キーを持ちますが、デバッグのためにデータベース A の主キーを保存します。これは、複数のデータベース A を持つことができることを意味します。

データはリンク サーバー経由でコピーされます。速すぎません。SSIS の方が高速です。しかし、SSIS は初心者向けではなく、ソース テーブルの変更に対応するコードを作成するのは簡単ではありません。

また、ストアド プロシージャは C# から簡単に呼び出すことができます。

于 2008-09-16T10:24:45.400 に答える
0

同様のタスクを処理するときは、ジョブを実行する一連のストアド プロシージャを作成するだけでした。

指定したタスクはかなりカスタマイズされているため、「すぐに使用できる」ソリューションが見つからない可能性があります。

いくつかのヒントを与えるために:

  • データベースが異なるサーバー上にある場合は、リンク サーバーを使用して、TSQL を介してソース テーブルと宛先テーブルの両方に簡単にアクセスできるようにします。

ストアド プロシージャの場合:

  • コピーする必要がある親アイテムを特定します - 主キーが異なるため、代わりに一意の制約を使用する必要があると言われました (テーブルが正規化されている場合は、それらを定義できるはずです)。
  • 特定された親に基づいてコピーする必要がある子アイテムを特定し、それらの一部が宛先データベースに既に存在するかどうかを確認するために、一意の制約アプローチを再度使用します
  • 孫アイテムを特定する (親子と同じロジック)
  • 下位レベル (孫、子、親) からデータをコピーします。

カーソルなどは必要ありません。即時の結果を一時テーブル (または 1 つのストアド プロシージャ内で作業している場合はテーブル変数) に格納するだけです。

そのアプローチは私にとってかなりうまくいきました。

もちろん、メインのストアド プロシージャにパラメーターを追加して、すべての新しいレコードまたは指定したレコードのみをコピーできます。

それが助けになるかどうか教えてください。

于 2008-09-30T14:05:32.393 に答える
0

最も簡単な方法は、Red Gate の SQL Data Compare です。説明したことを 1、2 分で実行できるように設定できます。

于 2008-09-12T21:47:16.120 に答える
0

XML アプローチをダンプし、インポート ウィザード/SSIS を使用します。

于 2008-09-12T15:50:21.907 に答える