3

すべての外部キーに適切な制約があると仮定すると、DB のどこにも参照されていない行を削除する単純な SQL ステートメントはありますか?

delete from the_table子レコードを持つ行をスキップするだけの簡単なものですか?

テーブルを手動でループしたり、のようなものを追加したりしないようにしていwhere the_SK not in (a,b,c,d)ます。

4

4 に答える 4

6

DELETEエラーロギングを含む10gの拡張ステートメントを使用できる場合があります。

最初DBMS_ERRLOGにログテーブルを作成するために使用します(これは、いくつかの追加のプレフィックス列を含む元のテーブルの単なるコピーですORA_ERR_MESG$, ..., ORA_ERR_TAG$:)

execute dbms_errlog.create_error_log('parent', 'parent_errlog');

これで、deleteステートメントのLOG ERRORS句を使用して、既存の整合性制約を持つすべての行をキャプチャできます。

delete from parent
   log errors into parent_errlog ('holding-breath')
   reject limit unlimited;

この場合、「holding-breath」コメントがORA_ERR_TAG$列に表示されます。

ここで完全なドキュメントを読むことができます。

親テーブルが巨大で、数行の漂遊行のみを削除しようとしている場合parent_errlogは、基本的にテーブルの複製であるparentテーブルになります。これがうまくいかない場合は、長い道のりでそれを行う必要があります。

  1. 子テーブルを直接参照する(Tonyのソリューションに従う)、または、
  2. PL / SQLの表をループして、例外をキャッチします(ConfusionBobのソリューションに従います)。
于 2010-01-08T10:22:45.533 に答える
1

これを行う 1 つの方法は、次のように記述することです。

eForeign_key_violation EXCEPTION;
PRAGMA EXCEPTION_INIT(eForeign_key_violation, -2292);

FOR aRow IN (SELECT primary_key_field FROM A_TABLE) LOOP
  BEGIN
    DELETE FROM A_TABLE A
    WHERE A.PRIMARY_KEY_FIELD = aRow.PRIMARY_KEY_FIELD;
  EXCEPTION
    WHEN eForeign_key_violation THEN
      NULL;  -- ignore the error
  END;
END LOOP;

子行が存在する場合、DELETE は失敗し、行は削除されず、次のキーに進むことができます。

テーブルが大きい場合、これにはかなりの時間がかかる場合があることに注意してください。

于 2010-01-08T12:28:42.060 に答える