3

これは少し奇妙なことですが、誰か助けがあれば大歓迎です。

シナリオでは、リモートサイトに本番データベースがあり、ローカルオフィスに開発者データベースがあります。開発者は開発者データベースに直接変更を加え、展開プロセスの一部としてC#アプリケーションが実行され、リモート側で実行できる一連の.sqlスクリプトを生成します(基本的に*を削除、挿入)が、少し何かを探しています削除*によるダウンタイムは許容できないため、より複雑になります。これは、主要なWebサイトのメニュー項目や機能などを制御するすべての参照データです。

基本的に2つのテーブルの差分を返すsprocがあります。私の考えでは、期待されるすべてのデータをtmpテーブルに挿入し、diffを実行し、ソースにない宛先テーブルから何かを削除してから、他のすべてをアップサートすることができます。

問題は、カーソルを使用せずにこれを行う簡単な方法があるかどうかです。sprocは、次のような構造のレコードセットを返します。

TableName Col1 Col2 Col3 Dest Src

TableName = Destのレコードセット内のものはすべて削除する必要があり(srcには存在しないため)、Src内のものはすべてdestにアップサートする必要があります。これを純粋にセットベースで行う方法は考えられませんが、私のDB-fuは弱いです。

どんな助けでもいただければ幸いです。説明が大雑把な場合はお詫びします。詳細が必要な場合はお知らせください。

4

4 に答える 4

3

ええ、そのsprocは機能します。そのテーブルで完全結合を使用し、挿入、更新、または削除を示す列を追加します。次に、列インジケーターに基づいて、それらに対して個別のSQLステートメントを作成します。セットベース。


完全結合ではありません。左結合と右結合を分離するには、それらを分解する必要があります。これはメモ帳で行ったので、機能しない場合はお詫びします。

INSERT INTO tempDeployData(ID,IUDType)
SELECT ed.id, 'D'
FROM    tmpDeployData td
    RIGHT JOIN existingData ed ON td.id = ed.id
WHERE td.id IS NULL     


UPDATE td
SET td.IUDType = CASE WHEN ed.id IS NULL THEN
                         'I'
                         ELSE
                         'U'
                         END
FROM    tmpDeployData td
    LEFT JOIN existingData ed ON td.id = ed.id


INSERT INTO existingData(ID,a,b,c)
SELECT td.ID,td.a,td.b,td.c
FROM tmpDeployData td
WHERE td.IUDType = 'I'

DELETE ed
FROM existingData ed
    INNER JOIN tmpDeployData td ON ed.ID = td.ID
WHERE td.IUDType = 'D'

UPDATE  ed
SET     ed.a = td.a,
        ed.b = td.b,
        ed.c = td.c
FROM existingData ed
INNER JOIN tmpDeployData td ON ed.ID = td.ID
WHERE td.IUDType = 'U' 

データのソースではなく、ステージングテーブルとして情報をtemptableにプルしていることに気づきました。その場合、FULLJOINを使用できます。

INSERT INTO tmpDeployData(ID,a,b,c,IUDType)
SELECT  sd.ID, 
        sd.a, 
        sd.b, 
        sd.c
        'IUDType' = CASE WHEN ed.id IS NULL THEN
                         'I'
                         WHEN sd.id IS NULL THEN
                         'D'
                         ELSE
                         'U'
                         END
FROM    sourceData sd
    FULL JOIN existingData ed ON sd.id = ed.id

次に、前と同じDMLステートメント。

于 2010-06-11T00:44:24.207 に答える
1

SQL Server 2008を使用していると仮定すると、これを行うためのはるかに簡単な方法があります。MERGEステートメントです。

あるテーブルから別のテーブルへのすべての変更の移行は、次のように簡単です。

MERGE DestinationTable d
USING SourceTable s
    ON d.Id = s.Id
WHEN MATCHED THEN UPDATE
    SET d.Col1 = s.Col1, d.Col2 = s.Col2, ...
WHEN NOT MATCHED BY TARGET THEN
    INSERT (Id, Col1, Col2, ...)
    VALUES (s.Id, s.Col1, s.Col2, ...)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;

それでおしまい。 その後DestinationTableと同じになります。SourceTable

于 2010-06-11T01:30:59.807 に答える
1

tablediffで取った

ユーティリティを実行するために、テーブルがレプリケーションに参加する必要はありません。テーブルを「同期」させるためのt-sqlを生成するための素晴らしい-fスイッチがあります。

Transact-SQLスクリプトを生成して、宛先サーバーのテーブルをソースサーバーのテーブルと収束させます。オプションで、生成されたTransact-SQLスクリプトファイルの名前とパスを指定できます。file_nameが指定されていない場合、Transact-SQLスクリプトファイルは、ユーティリティが実行されるディレクトリに生成されます。

于 2010-06-11T01:42:47.650 に答える
0

本番データベースのバックアップを取り、開発データベースに復元してみませんか?復元後にデータベースで実行できる本番データベースとのすべてのddlの違いに対する変更スクリプトが必要です。これにより、本番へのデプロイメントがテストされます。

編集:申し訳ありませんが、質問を読み直してください。構成情報を開発データベースに保存し、そこから変更スクリプトを生成しているようですので、これは機能しません。

変更スクリプトを手動で作成し、ソース管理に保存することをお勧めします。次に、sqlcmdまたはosqlとバッチファイルを使用して、データベースで変更スクリプトを実行します。

于 2010-06-11T21:54:33.720 に答える