自律トランザクションを使用して、トリガーがそのテーブル自体を照会できないという事実を回避しています。悪名高いミューティングテーブルエラーが発生し、トリガーを自律型トランザクションとして宣言すると、エラーが解消されることがわかりました。
運が悪いですが、これでは問題はまったく解決しません:
- まず、トランザクションロジックが失われます。
suscription_fact
の変更をロールバックすることはできません テーブル、それらはコミット 、メイントランザクションはロールバックされておらず、ロールバックされる可能性があります。そのため、データの整合性も失われます。 - 新しい行がまだコミットされていないため、トリガーは新しい行を見ることができません。トリガーは独立したトランザクションで実行されるため、メイントランザクションによって行われたコミットされていない変更を確認できません。完全に間違った結果が発生します。
これが、自律型トランザクションでビジネスロジックを実行してはならない理由です。 (正当なアプリケーションがありますが、それらはほぼ完全にロギング/デバッグに限定されています。)
あなたの場合、次のいずれかを行う必要があります。
- テーブルをクエリする必要がないようにロジックを更新します(
suscription_fact
を更新します) 新しい行がid_date_unsuscription
に保存されている古い値よりも新しい場合のみ 。 - トリガーでビジネスロジックを使用することを忘れ、すべてのテーブルを正しく更新するプロシージャを使用するか、ビューを使用します。これは、冗長データの明確なケースがあるためです。
- 実際に機能する回避策を使用します(TomKyteによる) 。
ここで(2)を使用することを強くお勧めします。トリガーを使用してビジネスロジックをコーディングしないでください。それらはバグなしで書くのは難しく、それでも維持するのは難しいです。プロシージャを使用すると、関連するすべてのコードが1つの場所(パッケージまたはプロシージャ)にグループ化され、読みやすく、従うことが容易になり、予期しない結果が生じることはありません。