2017-06-07 2 views
-1

Schreiben eines Triggers auf Tabelle, die eine andere Tabelle auf Orakel aktualisiert Trigger löst Muting-Tabellenfehler aus. Ich weiß, dass der Fehler kommt, weil ich die Tabelle aktualisiere, die in meinem Block der Reihenebene ist, aber ich kann eine Arbeit umPL/SQL-Trigger Muting-Tabelle auf Compound-Trigger

nicht herausfinden

EDIT: Dieser Code löst ein PL/SQL: numerischer oder Wertfehler: Nullindex Tabellenschlüssel Wert, aber ich habe den mutierenden Tisch umgangen.

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; 

Der ursprüngliche Auslöser schrieb ich, dass dies funktioniert, aber ich möchte es als eine Verbindung Trigger stattdessen geschrieben werden, wenn ein plate_type zu ‚Assayplatte‘ die Abfrage alle well_values ​​dieser plate_id auf Tabelle schaut nach oben gesetzt DSPLATE_WELL, die well_values ​​entsprechen vielen verschiedenen plate_ids in der Tabelle DSPLATE mit plat_type 'cherry pick' und bestimmten WELL_IDs, von denen die WELL_VALUES ursprünglich stammen, müssen ihre Volumenmenge aktualisiert haben.

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

Ich kann nicht sofort sehen, was der Code aus dem Blick auf den (unformatierten) Code tun soll. Warum müssen Sie die Tabelle während der Aktualisierung abfragen? –

+0

Ich erkläre, wie der Code in meiner Bearbeitung funktioniert –

Antwort

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

Ihr Auslöser wie diese aussehen sollte:

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; 

Hinweis, dieser Code nicht getestet ist und höchstwahrscheinlich nicht optimal in Bezug auf Leistung (ich nehme an die zweite Schleife ist nicht erforderlich und kann sein in eine einzige UPDATE-Anweisung einfügen). Sie sollten sich jedoch eine Vorstellung davon machen, wie zusammengesetzte Trigger funktionieren.

+0

Ich sehe die Richtung, in die Sie gehen, aber das enthält immer noch eine: NEW bind auf der Anweisungsebene, dies löst einen Bind-Fehler beim Versuch zu kompilieren –

0

Ich hatte ähnliche zusammengesetzte Trigger geschrieben und ich habe "vor Anweisung" verwendet, um die Werte abzufangen (ich hatte eine SELECT verwendet, um eine Struktur mit Bulk Collect zu füllen) und "nach jeder Zeile" zu aktualisieren.

Verwandte Themen