4

あるデータベースから別のデータベースに行を移動するプロセスがあります。一部の循環外部キー参照チェーンのため、古いデータベースから行を削除したり、新しいデータベースに行を挿入したりすることはできません。

操作全体がトランザクション1で発生するため、SQL Serverは、を呼び出すまで参照整合性の失敗を無視する必要がありますCOMMIT TRANSACTION

2

   Table: Turboencabulators         Table: Marselvanes
   =========================        =======================
PK TurboencabulatorID int    /-> PK MarselvaneID       int
^  MarselvanesID      int --/       HasGrammeter       bit
|                                   PantametricFan     varchar(50)
+-------------------------------    TurboencabulatorID int

ターボエンカビュレーターを新しいテーブルに挿入しようとすると、マーセルベーンがすでに存在しないと失敗します。順序を逆にしても同じ問題があります。

古い行を削除しようとすると、もう一方が削除されるまで一方を削除できません。

私はnフェーズシステムを実行しようとしました。このシステムでは、すべての行が、外部キー制約がnullに設定されている列とともに挿入されます。次に、挿入されたすべての行を更新し、適切な欠落値を配置します。次に、ソース行を削除するために、FKの影響を受けるすべての列を無効にしてから、実際の行を削除します。3

私が本当に望んでいるのは、T-SQL操作を実行し、commitを呼び出そうとするまでSQLServerに通知しないようにすることです。

ノート

1分散
2私がもうやっていない架空の
3を考案しました

4

2 に答える 2

11

あなたが使用することができます...

ALTER TABLE whatever_table NOCHECK CONSTRAINT ALL 

開始する前に制約チェックを削除します

完了したら、...でオンに戻します。

ALTER TABLE whatever_table CHECK CONSTRAINT ALL 

それはとにかく私がすることです。

-ドン

于 2010-02-26T22:06:07.150 に答える
2

それをどのように実装するか想像してみてください。

外部キーの結果がトランザクションのコミットまで延期される場合、コミットは、挿入/削除/更新時に発生しなかったすべてのルックアップ/チェック/カスケード操作を実行する必要があります。FK制約が実際に何を意味するかを考えてください。挿入実行プランは、FK制約を検証および適用するための追加の操作で「注釈付き」になります。制約を延期する場合、クエリプランの追加ロジックは、実行の瞬間からバインドを解除し、コミット時に実行されるようにトランザクションコンテキストにプッシュする必要があります。突然のコミットはすべて、「ログでコミットされたトランザクションをマークする」操作から、実際のトランザクション中にスキップされたすべてのことを実行する操作に変わります。最悪の部分は、制約が失敗する可能性があることであり、アプリケーションが失敗をどのように処理するかを考えます?挿入の実行時に制約が適用されると、アプリケーションはエラーをキャッチして修正アクションを実行できます。つまり、失敗したものを正確に把握できます。しかし、これをコミットするまで延期すると、コミットして例外をキャッチしようとします。次に、取得した例外から、何が失敗したかを何らかの方法で把握する必要があります。その場合、アプリケーション開発者の生活はどれほど複雑になるか考えてみてください。

これが機能しない2つ目の理由は、まだ問題を解決していないことです。BにFK制約のあるテーブルAがあります。トランザクションを開始し、Bに挿入し、次にAに挿入し、次にAから削除し、次にBから削除し、次にコミットします。すべての操作は、発生した時点でFKを満たしていました。データベースは、コミット時にFKを満たしています。ただし、制約チェックを延期すると、コミット時に失敗します!!

したがって、参照整合性はそのままで正常に機能すると思いますが、サイクルのないカスケード階層に基づいて設計されています。多くのCSデータ構造とアルゴリズムと同様に、サイクルが導入されると壊れます。最善の解決策は、スキーマを分析し、サイクルが本当に避けられないかどうかを確認することです。それを除けば、NULLを挿入し、挿入後を更新することが最善の解決策です。

残念ながら、制約を無効にして元に戻すことは大したことではありません。再度有効にすると、テーブル内のすべての行をチェックして制約を確認する必要があり、永久に存続します。それ以外の場合、制約はデータベースメタデータで「信頼できない」とマークされ、オプティマイザーは基本的にそれを無視します(引き続き適用されますが、プランの最適化のメリットは得られません)。

于 2010-02-26T23:24:43.217 に答える