Sql 似乎无法为insert-Oracle创建触发器

Sql 似乎无法为insert-Oracle创建触发器,sql,oracle,plsql,triggers,Sql,Oracle,Plsql,Triggers,我正在尝试在表上为插入创建触发器。以下是创建脚本: CREATE OR REPLACE TRIGGER INTEG_QRY_NEW AFTER INSERT ON INTEG_LOG FOR EACH ROW DECLARE VAR2 NUMBER(10); LOG_TEXT1 VARCHAR2(1000); RESULT1 VARCHAR2(1000); QUERY_NUM1 VARCHAR2(1000); QUERY_TIME1 VARCHAR2(1000); LOG_INDE

我正在尝试在表上为插入创建触发器。以下是创建脚本:

CREATE OR REPLACE TRIGGER INTEG_QRY_NEW
AFTER INSERT
   ON INTEG_LOG
   FOR EACH ROW

DECLARE
VAR2 NUMBER(10);
LOG_TEXT1 VARCHAR2(1000);
RESULT1 VARCHAR2(1000);
QUERY_NUM1 VARCHAR2(1000);
QUERY_TIME1 VARCHAR2(1000);
LOG_INDEX1 NUMBER(10);

BEGIN
    SELECT COUNT(*) INTO VAR2 FROM USER_TAB_COLS WHERE (COLUMN_NAME = 'RESULT' OR COLUMN_NAME = 'QUERY_NUM'  OR COLUMN_NAME = 'DATE_TIME' ) AND TABLE_NAME = 'INTEG_LOG';
    IF VAR2=0 THEN
        EXECUTE IMMEDIATE 'ALTER TABLE INTEG_LOG ADD RESULT VARCHAR2(50); ALTER TABLE INTEG_LOG ADD DATE_TIME DATE; ALTER TABLE INTEG_LOG ADD QUERY_NUM VARCHAR2(50);';
    END IF;

    LOG_TEXT1 := :NEW.LOG_TEXT;
    QUERY_TIME1 := :NEW.QUERY_TIME;
    LOG_INDEX1 := :NEW.LOG_INDEX;

    IF QUERY_TIME1 = '' THEN
        RESULT1 := '-1';
        QUERY_NUM1 := '';

        UPDATE INTEG_LOG
        SET RESULT = RESULT1,
               DATE_TIME = CURRENT_DATE,
               QUERY_NUM = QUERY_NUM1
        WHERE LOG_INDEX = LOG_INDEX1;
    ELSE
        RESULT1 := SUBSTR(LOG_TEXT1,(INSTR(LOG_TEXT1,'Result = ')+9),9);
        QUERY_NUM1 := SUBSTR(SUBSTR(LOG_TEXT1,INSTR(LOG_TEXT1,'Q# ')+3,20),1,INSTR(SUBSTR(LOG_TEXT1,INSTR(LOG_TEXT1,'Q# ')+3,20),' '));

        UPDATE INTEG_LOG
        SET RESULT = RESULT1,
               DATE_TIME = CURRENT_DATE,
               QUERY_NUM = QUERY_NUM1
        WHERE LOG_INDEX = LOG_INDEX1;
    END IF;
END;
/
触发器负责对来自应用程序的以下列进行常规插入:

日志日期编号10

日志时间编号10

日志类型编号10

LOG_TEXT VARCHAR22000字节

日志索引编号10

查询时间VARCHAR28字节

触发器检查以下列是否存在,如果不存在,则添加它们: 结果VARCHAR250字节, 日期/时间日期, 查询\u NUM VARCHAR250字节

现在,它获取字符串LOG_TEXT列,并提取“Q”后面的结果值和查询编号。 接下来,它应该更新相同的insert操作,并将这些值添加到新的3列result、date\u time和query\u num中。 触发器确实成功创建,但问题是,当我尝试插入表INTEG_LOG时,出现以下错误:

表string.string正在发生变化,触发器/函数可能看不到它

原因:引用的触发器或用户定义的plsql函数 在此语句中,试图查看或修改已删除的表 在被修改的语句的中间。 操作:重写触发器或函数,使其不读取该值 桌子


这可能是语法错误吗?请帮忙。谢谢。

触发器编译的唯一原因是,INTEG\u LOG已经包含了动态SQL试图添加的列。如果表中没有这些列,触发器将不会添加它们,因为触发器将无效,因为这些UPDATE语句无法编译

应该避免使用动态SQL的原因之一是它将编译错误转化为运行时错误

但是,试图在基于表的触发器中向表中添加列是一个非常糟糕的想法。除此之外,DDL语句还发出隐式提交,我们不能在触发器中提交,因为这会对事务造成严重破坏。是的,有pragma-autonomous\u事务,但使用它通常是一种代码味道

正确的解决方案是:

编写一个一次性DDL脚本来添加这些列 如有必要,在执行ALTER TABLE语句之前,通过检查这些列是否存在,使脚本幂等 运行脚本。 用所有列填充表。
当然,这与那些UPDATE语句导致的突变表错误无关。我们无法在承载触发器的表上执行DML,包括selects。我不确定您试图实现的业务规则是什么,但您需要一种不同的方式来实现它

不能在触发该表的触发器中向该表添加列。您不应该向触发器中的任何表添加列。我想不出任何一个用例会是一个好主意。