0

私は大学の科目用に小規模なプロジェクトを作成していますが、Oracle SQL Developer で小規模なデータベース用のトリガーを設計する際に問題があります。

次のテーブルがあります。

create table ASSIGNED_TO(
  ASSIGNMENT_ID int not null primary key,
  ROOM_ID int not null,
  foreign key (ROOM_ID) references ROOM(ROOM_ID),
  NURSE_ID int not null,
  foreign key (NURSE_ID) references NURSE(PERSON_ID)
);

create table MESSAGE_LOG(
  ID int not null,
  MESSAGE varchar2(100) null
);

または操作ASSIGNED_TOによってテーブルの行が変更され、同じ行が2つあるたびに、トリガーで単純なメッセージをテーブルに書き込む必要があります。INSERTUPDATEROOM_IDMESSAGE_LOG

問題の原因は、 table の「変異」ですASSIGNED_TO。私の現在の解決策は次のとおりです。

create or replace TRIGGER TRIG3
  AFTER INSERT OR UPDATE
  ON ASSIGNED_TO
  FOR EACH ROW
DECLARE
  nr_nurses INTEGER;  
BEGIN
      SELECT COUNT(*) INTO nr_nurses
        FROM ASSIGNED_TO
      WHERE ROOM_ID = :NEW.ROOM_ID;

      IF nr_nurses >= 2 THEN
        INSERT INTO MESSAGE_LOG values (3, '2 or more nurses per room detected');
        DBMS_OUTPUT.PUT_LINE('3| 2 or more nurses per room detected');
      END IF;
END;

このトリガーにより、「Mutating Table」エラーが発生し、これまでのところ修正できませんでした。:OLD.ROOM_ID代わりに使用すると、操作の際に存在しないためROOM_ID失敗します。この作品を作る上でのアドバイスは大歓迎です。:OLD.ROOM_IDUPDATE

4

2 に答える 2

3

@MichaelBroughton が指摘したように、恐ろしい「変更テーブル」例外が発生するため、ここで行トリガーを使用することはできません。この問題を回避するにはさまざまな方法があります。おそらく最も簡単な方法は、ステートメント トリガーを使用して同じ目的を達成することです。トリガーを次のように作り直します。

CREATE OR REPLACE TRIGGER TRIG3
  AFTER INSERT OR UPDATE
  ON ASSIGNED_TO
BEGIN
  -- The following cursor will only find rows for
  -- which multiple nurses have been assigned.

  FOR aRow IN (SELECT ROOM_ID, COUNT(*) AS NURSE_COUNT
                 FROM ASSIGNED_TO
                 GROUP BY ROOM_ID
                 HAVING COUNT(*) >= 2)
  LOOP
    INSERT INTO MESSAGE_LOG
      (ID, MESSAGE)
    VALUES
      (3, aRow.NURSE_COUNT || 'ASSIGNED TO ROOM ' || aRow.ROOM_ID);

    DBMS_OUTPUT.PUT_LINE('3| ' || aRow.NURSE_COUNT || 'ASSIGNED TO ROOM ' ||
                         aRow.ROOM_ID);
  END LOOP;
END TRIG3;

注: 行が含まれていないため、これはステートメント トリガーですFOR EACH ROW

このトリガーは、変更された行ごとに 1 回ではなく、ASSIGNED_TO テーブルに影響を与える INSERT または UPDATE ステートメントごとに 1 回呼び出されますが、このようにすると、トリガーは元の行トリガーと同じ機能を提供し、「変更テーブル" 問題。

共有してお楽しみください。

于 2015-01-28T18:09:29.980 に答える
1

挿入先のテーブルを参照すると、この問題が発生します。これは、変更がコミットされる前にテーブルの内容を確認しているためです。

答えは、トリガーを介してこのチェックを行わないことです。私は、UI からの純粋なテーブル操作よりも、pl/sql ビジネスレベル インターフェイスにアクセスすることを好みます。たとえば、insert_room_assigment(nurse_id, room_id) プロシージャをコーディングして、挿入、チェック、および必要に応じて問題のログを記録するか、最初にチェックして最初から挿入を許可しないようにすることができます。

しかし、どのように解決しても、トリガーは機能しません。

于 2015-01-28T18:00:24.687 に答える