1

フィルム、ショー、部屋の 3 つのテーブルがあります。特定の部屋に映画の新しいショーを挿入したいのですが、既存のショーとの時間の衝突がない場合にトリガーを使用してそれを実行できると考えました。

私はこれを書きました:

CREATE OR REPLACE TRIGGER insert_new_show
BEFORE INSERT ON show
FOR EACH ROW
DECLARE
   -- pragma autonomous_transaction;
   collisioni varchar(40);
   runtime INT;
   error1 EXCEPTION;
   error2 EXCEPTION;
BEGIN
   IF  :new.time < CURRENT_TIMESTAMP THEN
      RAISE error1;
   END IF;  

   SELECT runtime INTO runtime 
     FROM film 
    WHERE title = deref(:new.di_film).title;

   SELECT film.title INTO collisioni 
     FROM show JOIN film ON deref(show.di_film).title=film.title
    WHERE DEREF(room).nome = DEREF(:NEW.room).nome 
      AND ( (:new.time < show.time AND :new.time + runtime + 10 > show.time) 
            OR (:new.time > show.time 
                 AND :new.time < show.time + runtime + 10));

   IF NOT SQL%NOTFOUND THEN
      INSERT INTO show
       SELECT to_timestamp(:NEW.orario,'yyyy-mm-dd hh24:mi:ss')
            , :NEW.max_n_spot,:NEW.costo, REF(s), NULL, REF(f)
         FROM film f, room s
        WHERE f.title=deref(:NEW.di_film).title 
          AND s.nome=deref(:NEW.room).nome;     
   ELSE
      RAISE error2; 
   END IF;

EXCEPTION 
   WHEN error1 THEN
      RAISE_APPLICATION_ERROR(-20491,'Error');
   WHEN error2 THEN
      RAISE_APPLICATION_ERROR(-20491,'Error');

END;

「pragmaautonomous_transaction」を使用しないと、table s%s is mutatingエラーが発生します。しかし、もちろんトランザクションでは、トリガーは:new値を見ることができません。CHECK CONSTRAINT でチェックを行うことも考えましたが、機能するかどうかはわかりません。解決策を見つけるのを手伝ってもらえますか?

4

1 に答える 1

0

これは、古典的な「パッケージ/プロシージャを使用する」状況です。

ORA-04091: table name is mutating, trigger/function may not see it現在 DML 操作を実行しているトリガーでテーブルをクエリすると取得されます。Oracle では、データの読み取り一貫性を維持するために、これを許可していません。これを回避するにはさまざまな方法があります。あなたがすでに自律的なトランザクションに気づいたように。

ただし、エラーの根本原因には影響しません。つまり、何か間違ったことをしているということです。このエラーは通常、次の 2 つのいずれかまたは両方を示しています。

  • トリガーにあまりにも多くのロジックを入れています
  • データモデルに欠陥があります。

解決策は、ロジックをパッケージまたはプロシージャに移動することです。これには、難読化のレイヤーを削除し、デバッグを支援するという追加の利点があります。

FILM からランタイムを知る必要があり、2 番目のテーブルをクエリする必要があるため、ここでチェック制約がどのように可能であるかはわかりません。

参考文献:

于 2012-11-02T13:47:50.730 に答える