投稿した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の可能性を考慮していません。 ステートメントが失敗する可能性があるため、これらの例外の処理には注意が必要です。また、ユーザーインターフェースの観点からは、例外がトランザクションのかなり早い段階で行われた変更に関連している可能性があるため、問題が何であるかをユーザーに説明するのはやや難しい場合があります。