2017-06-07 11 views
-1

トリガーがテーブルのエラーを変異スローOracleで別のテーブルを更新し、テーブル上のトリガを書きます。 私は行レベルブロック内の参照であるテーブルを更新しているため、回避策を見つけることができないため、エラーが発生していることがわかりますPL/SQLトリガー変異表

EDIT:このコードはPL/SQL:数値または値のエラーをスローします。テーブルのキー値が、私は変異テーブルの周りを得たようです。

create or replace TRIGGER DSPLATE_WELL_VOLUME_V3 
FOR UPDATE ON DSPLATE 
COMPOUND TRIGGER 


TYPE t_PLATE_ID IS TABLE OF DSPLATE.PLATE_ID%TYPE; 
v_PLATE_ID t_PLATE_ID; 
TYPE t_NEW_AMOUNT IS TABLE OF DSPLATE.AMOUNT%TYPE; 
v_NEW_AMOUNT t_NEW_AMOUNT; 


BEFORE STATEMENT IS 
BEGIN 
    v_PLATE_ID := t_PLATE_ID(); 
    v_NEW_AMOUNT := t_NEW_AMOUNT(); 
END BEFORE STATEMENT; 


BEFORE EACH ROW IS 
BEGIN 
    IF :NEW.PLATE_TYPE != :OLD.PLATE_TYPE AND :NEW.PLATE_TYPE = 'Assay Plate' 
     AND :NEW.AMOUNT_INITIAL IS NOT NULL AND :OLD.AMOUNT_INITIAL IS NULL THEN 
      v_PLATE_ID(v_PLATE_ID.LAST) := :OLD.PLATE_ID; 
      v_NEW_AMOUNT(v_NEW_AMOUNT.LAST) := :NEW.AMOUNT_INITIAL; 
    END IF; 
END BEFORE EACH ROW; 

AFTER STATEMENT IS 
BEGIN 
    FOR p IN 1..v_PLATE_ID.LAST LOOP 
        UPDATE DSPLATE_WELL 
      SET AMOUNT = AMOUNT - v_NEW_AMOUNT(p) 
       WHERE WELL_ID IN (SELECT DSPLATE_WELL.WELL_ID 
       FROM DSPLATE INNER JOIN DSPLATE_WELL ON DSPLATE_WELL.PLATE_ID = DSPLATE.PLATE_ID 
       WHERE DSPLATE_WELL.WELL_VALUE IN (SELECT DSPLATE_WELL.WELL_VALUE 
       FROM DSPLATE_WELL INNER JOIN DSPLATE ON DSPLATE.PLATE_ID = DSPLATE_WELL.PLATE_ID WHERE DSPLATE.PLATE_ID = v_PLATE_ID(p)) 
       AND DSPLATE.PLATE_TYPE = 'Cherry Pick Plate' AND DSPLATE.LOCATION_ID = 1420); 
     END LOOP; 
END AFTER STATEMENT; 


END; 

私が働いていたことを書いたオリジナルのトリガは、このですが、plate_typeが「アッセイプレート」に設定されている場合、私はそれではなく、複合トリガーとして書くことにしたい、クエリがテーブルの上にそのplate_idのすべてwell_valuesを検索しますDSPLATE_WELL、well_valuesは、plate_type 'cherry pick'とWELL_VALUESが元々由来した特定のWELL_IDを持つ表DSPLATEの多くの異なるplate_idsに対応し、ボリューム量が更新されている必要があります。

create or replace TRIGGER INSERT_DSPLATE_WELL_VOLUME 
AFTER UPDATE ON DSPLATE 
FOR EACH ROW 
DECLARE 
pragma autonomous_transaction; 


BEGIN 
    IF :NEW.PLATE_TYPE != :OLD.PLATE_TYPE AND :NEW.PLATE_TYPE = 'Assay Plate' 
AND :NEW.AMOUNT_INITIAL IS NOT NULL AND :OLD.AMOUNT_INITIAL IS NULL 
    THEN 
     UPDATE DSPLATE_WELL 
     SET AMOUNT = AMOUNT - :NEW.AMOUNT_INITIAL 
      WHERE WELL_ID IN (SELECT DSPLATE_WELL.WELL_ID 
      FROM DSPLATE INNER JOIN DSPLATE_WELL ON DSPLATE_WELL.PLATE_ID = DSPLATE.PLATE_ID 
      WHERE DSPLATE_WELL.WELL_VALUE IN (SELECT DSPLATE_WELL.WELL_VALUE 
      FROM DSPLATE_WELL INNER JOIN DSPLATE ON DSPLATE.PLATE_ID = DSPLATE_WELL.PLATE_ID WHERE DSPLATE.PLATE_ID = :OLD.PLATE_ID) 
      AND DSPLATE.PLATE_TYPE = 'Cherry Pick Plate' AND DSPLATE.LOCATION_ID = 1420); 
      COMMIT; 
    END IF; 
END; 
+0

(フォーマットされていない)コードを見て、コードが何を意味するのかすぐにはわかりません。なぜあなたはそれが更新されている間にテーブルを照会する必要がありますか? –

+0

私は私はあなたが行っている方向を見たが、これはまだ含まれているコードは私の編集 –

答えて

0
create or replace TRIGGER DSPLATE_WELL_VOLUME_V3 
FOR UPDATE ON DSPLATE 
COMPOUND TRIGGER 



TYPE t_PLATE_ID IS TABLE OF DSPLATE.PLATE_ID%TYPE INDEX BY PLS_INTEGER; 
v_PLATE_ID t_PLATE_ID; 
v_NEW_AMOUNT t_PLATE_ID; 

counter number := 1; 


BEFORE EACH ROW IS 
BEGIN 
    IF :NEW.PLATE_TYPE != :OLD.PLATE_TYPE AND :NEW.PLATE_TYPE = 'Assay Plate' 
     AND :NEW.AMOUNT_INITIAL IS NOT NULL AND :OLD.AMOUNT_INITIAL IS NULL THEN 
      v_PLATE_ID(counter) := :OLD.PLATE_ID; 
      v_NEW_AMOUNT(counter) := :NEW.AMOUNT_INITIAL; 
      counter := counter + 1; 
    END IF; 
END BEFORE EACH ROW; 

AFTER STATEMENT IS 
BEGIN 
    FOR p IN 1..v_PLATE_ID.COUNT LOOP 
        UPDATE DSPLATE_WELL 
      SET AMOUNT = AMOUNT - v_NEW_AMOUNT(p) 
       WHERE WELL_ID IN (SELECT DSPLATE_WELL.WELL_ID 
       FROM DSPLATE INNER JOIN DSPLATE_WELL ON DSPLATE_WELL.PLATE_ID = DSPLATE.PLATE_ID 
       WHERE DSPLATE_WELL.WELL_VALUE IN (SELECT DSPLATE_WELL.WELL_VALUE 
       FROM DSPLATE_WELL INNER JOIN DSPLATE ON DSPLATE.PLATE_ID = DSPLATE_WELL.PLATE_ID WHERE DSPLATE.PLATE_ID = v_PLATE_ID(p)) 
       AND DSPLATE.PLATE_TYPE = 'Cherry Pick Plate' AND DSPLATE.LOCATION_ID = 1420 AND DSPLATE_WELL.AMOUNT IS NOT NULL); 
     END LOOP; 
END AFTER STATEMENT; 


END; 
1

トリガーはこの1つのようになります:

create or replace TRIGGER DSPLATE_WELL_VOLUME_V2 
FOR UPDATE ON DSPLATE 
COMPOUND TRIGGER 

TYPE t_WELL_ID IS TABLE OF DSPLATE_WELL.WELL_ID%TYPE; 
v_WELL_ID t_WELL_ID := t_WELL_ID(); 
TYPE t_AMOUNT IS TABLE OF INT; 
v_NEW_AMOUNT t_AMOUNT := t_AMOUNT(); 



TYPE t_PLATE_ID IS TABLE OF DSPLATE.PLATE_ID%TYPE; 
v_PLATE_ID t_PLATE_ID; 


BEFORE STATEMENT IS 
BEGIN 
    v_PLATE_ID := t_PLATE_ID(); 
END BEFORE STATEMENT; 


BEFORE EACH ROW IS 
BEGIN 
    IF :NEW.PLATE_TYPE != :OLD.PLATE_TYPE AND :NEW.PLATE_TYPE = 'Assay Plate' 
     AND :NEW.AMOUNT_INITIAL IS NOT NULL AND :OLD.AMOUNT_INITIAL IS NULL THEN 
      v_PLATE_ID.EXTEND; 
      v_PLATE_ID(v_PLATE_ID.LAST) := :OLD.PLATE_ID; 
    END IF; 
END BEFORE EACH ROW; 

AFTER STATEMENT IS 
BEGIN 

FOR p IN 1..v_PLATE_ID.LAST LOOP 

    SELECT DSPLATE_WELL.WELL_ID, :NEW.AMOUNT 
    BULK COLLECT INTO v_WELL_ID, v_NEW_AMOUNT 
    FROM DSPLATE INNER JOIN DSPLATE_WELL ON DSPLATE_WELL.PLATE_ID = DSPLATE.PLATE_ID 
    WHERE DSPLATE_WELL.WELL_VALUE IN 
      (SELECT DSPLATE_WELL.WELL_VALUE 
      FROM DSPLATE_WELL INNER JOIN DSPLATE ON DSPLATE.PLATE_ID = DSPLATE_WELL.PLATE_ID 
      WHERE DSPLATE.PLATE_ID = v_PLATE_ID(p)) 
     AND DSPLATE.PLATE_TYPE = 'Cherry Pick Plate' 
     AND DSPLATE.LOCATION_ID = 1420; 

    FOR i in 1..v_WELL_ID.count() LOOP 
     UPDATE DSPLATE_WELL SET AMOUNT = (AMOUNT - v_NEW_AMOUNT(i)) 
     WHERE WELL_ID = v_WELL_ID(i); 
    END LOOP; 

END LOOP; 


END AFTER STATEMENT; 

END; 

注、このコードはテストされ、最も可能性が高いではない、最適なパフォーマンスの面でされていません(私は2番目のループが必要とされていないと仮定してすることができ単一のUPDATEステートメントに入れる)。しかし、化合物トリガーがどのように作用しているかを知る必要があります。

+0

にどのように動作するかを説明します。文レベルでの新しいバインドをコンパイルしようとしたとき、これはバインド・エラーがスローされます –

0

Iは、類似化合物のトリガーを書いたと私は更新する値(I収集バルクで構造を充填するためにSELECTを使用していた)および「各行の後に」捕捉する「ステートメントの前に」使用。

関連する問題