0

我正在尝试创建一个复合触发器来避免突变问题。我有一个表和一个执行事务插入的 python 程序。该表有 n 个字段。我想要做的是当这些字段之一的值为负时,然后不执行操作,并从表的字段(插入之前)的上一条记录中插入值。另一个问题是其中一个字段是和 id,以区分站点。

不,这是我的代码,只考虑一个字段(KWHGEN):

CREATE OR REPLACE TRIGGER "CIRCU3".D_measures_TP_test
--FOR INSERT OR UPDATE ON T_MEASURES_TP_NEW
FOR INSERT ON T_MEASURES_TP_NEW
COMPOUND TRIGGER

VAL_KWHGEN NUMBER(21,2);
VAL_autoin NUMBER (19,0);

AFTER EACH ROW IS
BEGIN
SELECT autoin, KWHGEN INTO VAL_ID_MED, VAL_KWHGEN FROM
    (SELECT * 
        FROM T_measures_TP_NEW WHERE ID_site = :NEW.ID_site
       ORDER BY TIMESTAMP DESC)
    WHERE ROWNUM = 1;

IF :NEW.KWHGEN <0
  THEN UPDATE T_MEASURES_TP_NEW SET KWHGEN = VAL_KWHGEN WHERE autoin = VAL_autoin;

END IF;
END AFTER EACH ROW;

END D_MEASURES_TP_test;

但是突变错误正在跟随我;-)

4

3 回答 3

0

您已经在 T_MEASURES_TP_NEW 上创建了触发器,然后在触发器中更新了同一个表 T_MEASURES_TP_NEW。这将再次调用您的触发器。如果触发器中的第一个选择再次在 VAL_KWHGEN 中返回负值,那么变异错误将随之而来。

于 2015-07-01T11:37:26.577 回答
0

你只定义了一个AFTER EACH块,没有别的。这与创建行级触发器相同(即使用FOR EACH ROW

它必须是这样的(未测试):

CREATE OR REPLACE TRIGGER "CIRCU3".D_measures_TP_test
FOR INSERT ON T_MEASURES_TP_NEW
COMPOUND TRIGGER

VAL_KWHGEN NUMBER(21,2);
VAL_autoin NUMBER (19,0);

TYPE RowIdTableType IS TABLE OF ROWID;
TYPE KWHGENTableType IS TABLE OF T_MEASURES_TP_NEW.KWHGEN%TYPE;

RowIdTable RowIdTableType;
KWHGENTable KWHGENTableType;

BEFORE STATEMENT IS   
    BEGIN       
        RowIdTable := RowIdTable();
        KWHGENTable := KWHGENTableType();
    END BEFORE STATEMENT;

BEFORE EACH ROW IS   
    BEGIN       
        RowIdTable.EXTEND;
        RowIdTable(RowIdTable.LAST) := :NEW.ROWID;
        KWHGENTable.EXTEND;
        KWHGENTable(RowIdTable.LAST) := :NEW.KWHGEN;
    END BEFORE EACH ROW;

AFTER STATEMENT IS 
    BEGIN
       FOR i IN RowIdTable.FIRST..RowIdTable.LAST LOOP
           SELECT 
                DISTINCT MIN(autoin) OVER (ORDER BY TIMESTAMP DESC), 
                DISTINCT MIN(KWHGEN) OVER (ORDER BY TIMESTAMP DESC)
           INTO VAL_ID_MED, VAL_KWHGEN 
           FROM T_measures_TP_NEW 
           WHERE ROWID = RowIdTable(i);

           IF KWHGENTable(i) < 0
              THEN UPDATE T_MEASURES_TP_NEW 
              SET KWHGEN = VAL_KWHGEN 
              WHERE  autoin = VAL_autoin;
           END IF;
       END LOOP;
    END AFTER STATEMENT;    

END;
/
于 2015-07-01T12:23:46.650 回答
0

好的,我确实有一个解决方案:

1.- 创建一个记录新插入数据的包(之前)

create or replace PACKAGE PCK_MEDIDAS_TP AS 
TYPE DATOS_MEDIDAS_TP IS RECORD(
v_id_sede NUMBER (10,0),
v_id_med NUMBER (10,0),
v_kwhGEN NUMBER (21,2),
v_timestamp TIMESTAMP
);

type T_MEDTP is table of DATOS_MEDIDAS_TP index by binary_integer;

tabla_medidas_tp T_MEDTP;

END PCK_MEDIDAS_TP;

2.- 每行(BEFORE)创建一个过程来读取新的插入数据,然后将它们记录到de包的表中。

create or replace TRIGGER "CIRCU3".D_MEDIDAS_TP_test
BEFORE INSERT ON T_MEDIDAS_TP_NEW
FOR EACH ROW
DECLARE
Indice binary_integer; 
BEGIN
--AUTOINCREMENTAL DEL CAMPO ID_MEDIDAS
SELECT T_MEDIDAS_TP_NEW_SEQ.NEXTVAL INTO :NEW.id_MEDIDAS_OLD FROM DUAL;

Indice:= PCK_MEDIDAS_TP.tabla_medidas_tp.COUNT+1;
PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_id_sede := :NEW.ID_SEDE;
PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_id_med := :NEW.ID_MEDIDAS;
PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_kwhGEN := :NEW.KWHGEN;
PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_timestamp := :NEW.TIMESTAMP;
IF :NEW.KWHGEN <0 THEN
DBMS_OUTPUT.put_line('first trigger:'     ||:NEW.ID_MEDIDAS||','||:NEW.ID_SEDE||','||:NEW.TIMESTAMP);
-- INSERT INTO TEST_TRIGGER VALUES ('100', :NEW.KWHGEN, SYSDATE);
--ELSE DBMS_OUTPUT.PUT_LINE('¿?');
END IF;
END;

3.- 创建一个语句程序(之后),您可以在其中检查您的状况,在我的情况下,如果 kwhgen <0。如果为真,我将读取原始 tbale 中的前一条记录,并使用 taht 值更新插入记录。

create or replace TRIGGER D_MEDIDAS_TP_TEST_STATEMENT 
AFTER INSERT ON T_MEDIDAS_TP_NEW 
DECLARE
Indice binary_integer;
s_id_sede NUMBER (10,0);
s_id_med NUMBER (10,0);
s_kwhGEN NUMBER (21,2);
s_timestamp TIMESTAMP;
BEGIN
FOR Indice in 1..PCK_MEDIDAS_TP.tabla_medidas_tp.count LOOP
DBMS_OUTPUT.put_line('second trigger: kwhgen:     '||PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_kwhGEN||', id_sede:     '||PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_id_sede);
IF PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_kwhGEN <0 THEN
DBMS_OUTPUT.put_line('second trigger: v_kwhGEN is negative');
SELECT prev_KWHGEN INTO s_kwhgen
from(
SELECT LEAD (KWHGEN,1) over (ORDER BY id_medidas desc) as prev_KWHGEN
FROM T_MEDIDAS_TP_NEW WHERE ID_SEDE =     PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_id_sede
ORDER BY id_medidas DESC) where rownum =1;
INSERT INTO TEST_TRIGGER VALUES ('100', '5555', SYSDATE);
DBMS_OUTPUT.put_line('second trigger. KWHGEN: '||s_kwhGEN);
DBMS_OUTPUT.put_line('UPDATE');
UPDATE T_MEDIDAS_TP_NEW SET KWHGEN = S_KWHGEN WHERE ID_MEDIDAS =     PCK_MEDIDAS_TP.tabla_medidas_tp(Indice).v_id_med;
else DBMS_OUTPUT.put_line('¿?');
END IF;
END LOOP;
PCK_MEDIDAS_TP.tabla_medidas_tp.delete; -- vaciamos la tabla
END;
于 2015-07-02T12:37:12.757 回答