sql >> データベース >  >> RDS >> Oracle

BEFOREINSERTトリガーでIFEXISTS(SELECT ...)を使用する(Oracle)

    まず、SQL * Plusを使用している場合、オブジェクトを作成してコンパイルエラーがあると通知されたら、コマンドshow errors エラーが表示されます。

    show errorsを実行した場合 、IF EXISTS は有効な構文ではありません。あなたは

    のようなことをすることができます
    SELECT COUNT(*)
      INTO l_cnt
      FROM <<rest of query>>
    
    IF( l_cnt > 0 )
    THEN
      RAISE_APPLICATION_ERROR ...
    END IF;
    

    ただし、コンパイルエラーを修正すると、ランタイムエラーが発生します。 surveillanceの行レベルのトリガー 、通常、surveillanceをクエリすることはできません (実行しているのがINSERT VALUESだけの場合は可能です これは、単一の行のみを挿入することが保証されています)。これを行うと、実行時に変更トリガーエラーが発生します。

    データモデルの観点から、特定の行の有効なデータが同じテーブルの他の行に格納されているデータに依存するテーブルを設計していることに気付いた場合、通常は正規化の原則に違反しているため、基礎となるデータモデル。

    データモデルを保持することに本当に決心している場合は、コミット時に更新されるマテリアライズドビューを作成します。このビューには、条件に違反する行のデータのみが含まれます。次に、基準に違反した場合にコミット時にエラーをスローするマテリアライズドビューに制約を設定できます。これには、テーブルにマテリアライズドビューログが必要です。

    本当にデータモデルを保持し、トリガーを使用してロジックを適用する場合は、従来の3つのトリガーソリューション(または11.2以降を使用している場合は3つの部分からなる複合トリガー)が必要になります。主キー値のコレクションを使用してパッケージを作成します。 beforeステートメントトリガーはコレクションを初期化します。行レベルのトリガーは、このコレクションに挿入および/または更新された行の主キーを挿入します。そして、afterステートメントトリガーはこのコレクションを繰り返し処理し、必要なチェックを実装します。しかし、それは多くの感動的な部分です、それが私が一般的にそれに反対する理由です。

    さらに、これらすべての要素が機能していても、マルチユーザー環境ではロジックで保護されません。複数のユーザーが同時にシステムにアクセスしている場合、1人のユーザーが行を挿入し、2番目のユーザーが範囲が重複する別の行を挿入してから、各セッションがコミットされる可能性があります。その場合、両方のトリガーセットで変更が許可されますが、要件に違反するデータがテーブルに残ります。マテリアライズド・ビューは、挿入時ではなくコミット時に適用されるため、マルチユーザー環境で適切に機能します。マルチユーザー環境でトリガーを機能させる場合は、2番目のセッションのinsertをブロックするシリアル化を強制するロジックを追加して、トリガーをさらに複雑にする必要があります。 実行から最初のセッションがコミットまたはロールバックされるまで。これにより、複雑さが増し、スケーラビリティが低下し、実装方法によっては、サポートの悪夢になる可能性があります。




    1. MySQLでタイムスタンプを丸める方法

    2. EbeanはPlayFramework2で間違ったシーケンス名を探します

    3. Laravel5Migrateでタイムゾーンを使用してTimeStampを設定する方法

    4. OracleでMySQLのGROUP_CONCATに似たようなクエリを作成するにはどうすればよいですか?