Mik*_*sen 5 sql oracle triggers oracle11g
我想防止VERSIONID=1在某个表中删除任何行.我还想在审计表中记录它,以便我们可以看到这种情况何时发生以便进行日志记录.我试图通过触发器来做到这一点:
CREATE TRIGGER TPMDBO.PreventVersionDelete
BEFORE DELETE ON TPM_PROJECTVERSION
FOR EACH ROW
DECLARE
BEGIN
IF( :old.VERSIONID = 1 )
THEN
INSERT INTO TPM_AUDIT VALUES ('Query has attempted to delete root project version!', sysdate);
RAISE_APPLICATION_ERROR( -20001, 'Query has attempted to delete root project version!' );
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
SQL> delete from TPM_PROJECTVERSION where PROJECTID=70 and VERSIONID=1;
delete from TPM_PROJECTVERSION where PROJECTID=70 and VERSIONID=1
*
ERROR at line 1:
ORA-20001: Query has attempted to delete root project version!
ORA-06512: at "TPMDBO.PREVENTVERSIONDELETE", line 6
ORA-04088: error during execution of trigger 'TPMDBO.PREVENTVERSIONDELETE'
Run Code Online (Sandbox Code Playgroud)
但是,该表TPM_AUDIT是空的.难道我做错了什么?
Jus*_*ave 10
如果触发器引发错误,则DELETE语句将失败,并且事务将回滚到在语句运行之前创建的隐式保存点.这意味着触发器所做的任何更改也会回滚.
您可以通过使用自治事务来解决此问题.就像是
CREATE PROCEDURE write_audit
AS
PRAGMA AUTOMOMOUS_TRANSACTION;
BEGIN
INSERT INTO tpm_audit
VALUES( 'Query has attempted to delete root project version!',
sysdate );
commit;
END;
CREATE TRIGGER TPMDBO.PreventVersionDelete
BEFORE DELETE ON TPM_PROJECTVERSION
FOR EACH ROW
DECLARE
BEGIN
IF( :old.VERSIONID = 1 )
THEN
write_audit;
RAISE_APPLICATION_ERROR( -20001, 'Query has attempted to delete root project version!' );
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
这将使INSERT进入TPM_AUDIT到一个单独的事务可以在上下文之外被提交DELETE声明.但是,要非常小心使用自治事务
DELETE语句,多次触发行级触发器,回滚该工作,然后重新执行DELETE.但是,静默回滚不会回滚自治事务所做的更改.因此,完全有可能DELETE单个行中的一个实际上会导致触发器被多次触发,因此会创建多行TPM_AUDIT.| 归档时间: |
|
| 查看次数: |
5710 次 |
| 最近记录: |