投稿したDDLに関するコメントがいくつかあります。
-
AUTOINCREMENT
はありません Oracleのキーワード。シーケンス(通常はテーブルごとに1つのシーケンス)を作成し、NEXTVAL
を使用する必要がありますINSERT
のいずれかのシーケンスから ステートメント自体、または合成主キーを設定するトリガー内。 -
VENUE_NO
を作成しているものは何もありませんEVENT_DETAILS
の列 。実際のDDLがその列を定義していると思います。
単純なCHECK
ではこれを強制できません 制約。トリガーを作成できます
CREATE OR REPLACE TRIGGER validate_capacity
BEFORE INSERT OR UPDATE ON event_details
FOR EACH ROW
DECLARE
l_venue_capacity venue.capacity%type;
BEGIN
SELECT capacity
INTO l_venue_capacity
FROM venue
WHERE venue_no = :new.venue_no;
IF( l_venue_capacity < :new.no_players )
THEN
RAISE_APPLICATION_ERROR( -20001, 'Sorry, the venue has insufficient capacity' );
END IF;
END;
ただし、注意してください
-
VENUE
にもトリガーが必要です 会場の収容人数の変更により特定のイベントが無効になるかどうかを確認するテーブル。一般に、イベントの詳細テーブルに何らかの日付が含まれている必要があります。おそらく、会場の容量は時間の経過とともに変化する可能性があり、検証ではその会場での将来のイベントのみをチェックする必要があるためです。 - トリガーベースのソリューションは、マルチユーザー環境で常に機能するとは限りません。会場1の容量が30であると想像してください。ここで、セッションAはその容量を15に更新します。ただし、セッションAがコミットする前に、セッションBは
NO_PLAYERS
を使用してイベントを挿入します。 どちらのセッションのトリガーにも問題は見られないため、両方の変更が許可されます。ただし、両方のセッションがコミットされると、15人のプレーヤーのみをサポートする会場で20人のプレーヤーで予約されたイベントがあります。EVENT_DETAILS
のトリガーVENUE
の行をロックする可能性があります この競合状態を回避するためのテーブルですが、EVENT_DETAILS
で挿入と更新をシリアル化しています 特にアプリケーションがトランザクションをコミットする前に人間の入力を待つ場合、パフォーマンスの問題になる可能性のあるテーブル。
トリガーの代わりに、ON COMMIT
を作成できます。 2つのテーブルを結合し、CHECK
を配置するマテリアライズドビュー プレーヤーの数が会場の定員を超えてはならないという要件を強制する、そのマテリアライズドビューに対する制約。これはマルチユーザー環境で機能しますが、両方のベーステーブルにマテリアライズドビューログが必要であり、セッションがコミットするポイントにチェックを移動します。これは少し注意が必要です。ほとんどのアプリケーションは、COMMIT
の可能性を考慮していません。 ステートメントが失敗する可能性があるため、これらの例外の処理には注意が必要です。また、ユーザーインターフェースの観点からは、例外がトランザクションのかなり早い段階で行われた変更に関連している可能性があるため、問題が何であるかをユーザーに説明するのはやや難しい場合があります。