要求是,
如果INSERTING,必填字段为ID,LOGIN_USER
•在插入表格之前,请确认没有具有相同LOGIN_USER的现有记录且记录状态为True。
•如果此验证失败,请返回错误代码和指示失败的消息。
•将记录插入表格后,事件后触发器将触发更新以下字段:带序列的ID,创建的当前日期/时间和操作“记录创建”
如果更新,必填字段为ID,LOGIN_USER
•在表格中更新记录时,会触发事件后触发器执行以下操作:
o将记录插入到受影响的表中,复制字段的当前值。
o使用以下值填充或覆盖以下字段: 活跃的错误 事件“审计数据维护”
•事件前触发器将触发并阻止更新非活动记录。
•状态为Active = False的记录可能无法更新。如果是,则必须创建新记录。
我编写了代码,它执行DELETE AND INSERT没有任何问题。
问题在于UPDATE,当它遇到UPDATING块,其他块内的INSERTS;这里INSERT查询由递归的INSERTING块触发。当我只想运行UPDATING块时,不应执行哪个。
请建议,还有其他方法可以效仿。这是我第一次使用触发器代码。
CREATE OR REPLACE TRIGGER BEFORE_DML
BEFORE DELETE OR INSERT OR UPDATE OF ID,LOGIN_USER ON USER_INFO
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
V_USER VARCHAR2 (30);
V_NODE VARCHAR2 (50);
V_CNT NUMBER := 0;
V_ACTIVE VARCHAR2 (10);
BEGIN
SELECT SYS_CONTEXT ('USERENV', 'IP_ADDRESS')
INTO V_NODE
FROM DUAL;
IF DELETING THEN
INSERT
INTO AUDIT (IDS,
ACTION,
IP_ADDRESS,
LOGIN,
CREATED
)
VALUES(AUDIT_SEQ.NEXTVAL,
'Deletion',
V_NODE,
SYS.LOGIN_USER,
SYSDATE
);
COMMIT;
RAISE_APPLICATION_ERROR (-20002, 'USER_INFO table data can not be deleted');
END IF; --Close IF for DELETING
IF INSERTING THEN
SELECT COUNT (1)
INTO V_CNT
FROM USER_INFO
WHERE LOGIN_USER = :NEW.LOGIN_USER
AND STATUS='TRUE';
IF ( V_CNT >=1 ) THEN
RAISE_APPLICATION_ERROR (-20002, 'DATABASE LOGIN USER ALREADY EXISTS', TRUE);
END IF;
:NEW.ID := DBLOGIN_SEQ.NEXTVAL;
:NEW.CREATED := SYSDATE;
:NEW.ACTION := 'Record Creation' ;
END IF; --CLOSE IF FOR INSERTING
IF UPDATING THEN
IF :OLD.STATUS = 'INACTIVE'
THEN
RAISE_APPLICATION_ERROR (-20002, 'INACTIVE RECORDS CAN NOT BE UPDATED');
ELSE IF :OLD.STATUS = 'FALSE' THEN
INSERT INTO USER_INFO(ID,
STATUS,
LOGIN_USER,
CREATED,
ACTION
)
VALUES(DBLOGIN_SEQ.NEXTVAL,
'INVALID',
:OLD.LOGIN_USER,
SYSDATE,
'FALSE RECORD UPDATED '
);
COMMIT;
ELSE
INSERT INTO USER_INFO(ID,
STATUS,
LOGIN_USER,
CREATED,
ACTION
)
VALUES(DBLOGIN_SEQ.NEXTVAL,
'FALSE',
:OLD.LOGIN_USER, --NEW.LOGIN_USER
SYSDATE,
'Audit for data maintenance'
);
COMMIT;
END IF;
END IF;
END IF; --CLOSE IF FOR UPDATING
END BEFORE_DML;
/
答案 0 :(得分:0)
一种方法是在插入之前禁用触发器,然后再次启用它。 例如:
execute immediate 'alter trigger [trigger_name] disable'