私が持っているコードは機能しません。Oracleは、トリガーがビルドエラーで作成されたと言っています。どうやら私はビルドエラーが何であるかについてこれ以上正確な情報を得ることができません...
私はこれまでSQLをあまり行ったことがないので、構文にあまり詳しくありません。オラクルが気に入らないのはIFEXISTS(SELECT ...)THENステートメントだという予感があります。同様の例をグーグルで探していましたが、自分の状況で機能するものは実際には見つかりませんでした。
だからコードについて:
そして、その選択に何かが存在する場合、私はエラーを発生させます。
CREATE OR REPLACE TRIGGER chev_surv
BEFORE INSERT OR UPDATE ON surveillance
FOR EACH ROW
BEGIN
IF EXISTS (
SELECT * FROM surveillance
WHERE surveillance.numInfirmier = :NEW.numInfirmier
AND ((surveillance.debut > :NEW.debut AND surveillance.debut < :NEW.fin)
OR (surveillance.fin > :NEW.debut AND surveillance.fin < :NEW.fin))
) THEN
RAISE_APPLICATION_ERROR(-20001,
'Il ne doit pas y avoir de chevauchement entre deux périodes surveillance pour un surveillant.');
END IF;
END;
/
何が問題なのか分かりますか?
まず、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
の実行をブロックするシリアル化を強制するロジックを追加して、トリガーをさらに複雑にする必要があります。ロールバック。これにより、複雑さが増し、スケーラビリティが低下し、実装方法によっては、サポートが悪夢になる可能性があります。