Oracle中触发器内的select语句出现错误的绑定变量错误

Posted

技术标签:

【中文标题】Oracle中触发器内的select语句出现错误的绑定变量错误【英文标题】:Bad bind variable error with select statement inside a trigger in Oracle 【发布时间】:2015-05-13 03:52:51 【问题描述】:

我正在尝试使用触发器将一条记录插入到与另一个表中更改的记录相同的表中。

我还需要插入操作是插入、更新还是删除

CREATE OR REPLACE TRIGGER triggername
AFTER INSERT OR UPDATE OR DELETE
ON tablename

DECLARE
operation_type VARCHAR2;
changed_id VARCHAR2;
BEGIN

IF UPDATING
THEN operation_type := 'Update';

ELSE IF INSERTING
THEN operation_type := 'Insert';

ELSE IF DELETING
THEN operation_type := 'Delete';

END IF;


SELECT id
FROM tablename
WHERE :OLD.record1 != :NEW.record1
OR :OLD.record2 != :NEW.record2
OR :OLD.record3 != :NEW.record3
OR :OLD.record4 != :NEW.record4
OR :OLD.record5 != :NEW.record5
OR :OLD.record6 != :NEW.record6;

INTO changed_id;

  INSERT INTO trigger_table.id VALUES(changed_id);
  INSERT INTO trigger_table.type VALUES(operation_type);
END;
/

我遇到了一个错误

对于每个 :NEW 或 :老

如上所示

【问题讨论】:

您只能在 ROW LEVEL TRIGGER 中引用 :OLD:NEW 值。您必须使用FOR EACH ROW 触发器不支持测试整条记录的语法,需要逐列测试。 查看this similar SO question关于审计触发器的答案。 【参考方案1】:

您的触发代码存在多个问题:

    operation_type VARCHAR2;

您必须声明变量大小。否则你会得到一个错误

PLS-00215:字符串长度限制必须在范围内 (1 .. 32767)

例如,修改为:

operation_type VARCHAR2(20);
changed_id VARCHAR2(20);
    SELECT .. INTO 语句
SELECT id
FROM tablename
WHERE :OLD.record1 != :NEW.record1
OR :OLD.record2 != :NEW.record2
OR :OLD.record3 != :NEW.record3
OR :OLD.record4 != :NEW.record4
OR :OLD.record5 != :NEW.record5
OR :OLD.record6 != :NEW.record6;

INTO changed_id;

语法不正确。 INTO 子句应在 SELECTFROM 子句之间:

SELECT id 
  INTO changed_id 
FROM tablename 
 WHERE ...
    WHERE :OLD.record1 != :NEW.record1

这是您关于绑定变量错误的原始问题。

要引用:OLD:NEW 值,您需要创建ROW LEVEL 触发器,其中必须包含以下条件:

FOR EACH ROW
    INSERT 语句
INSERT INTO trigger_table.id VALUES(changed_id);
INSERT INTO trigger_table.type VALUES(operation_type);

您必须使用两个插入语句插入单行而不是两行。此外,trigger_table.id 的语法不正确。您需要在括号内提及列名。

例如,

INSERT INTO trigger_table(column1, column2) VALUES
          (changed_id, operation_type);

【讨论】:

【参考方案2】:

当您尝试将 :NEW 用于删除和 :OLD 用于在触发器中创建时,您会看到这些错误。

最好把select&insert语句移到里面

IF INSERTING THEN ... END IF;
IF UPDATING THEN ... END IF;
IF DELETING THEN ... END IF;

使用 :NEW 和 :OLD 变量

【讨论】:

我不确定我是否遵循。 :NEW 和 :OLD 语句用于识别表中的哪条记录被更改。有没有更简单的方法来确定哪条记录被更改了? 你是对的。但是,由于您的触发器将所有创建、更新和删除事务视为相同,并尝试运行 select 和 insert 语句,因此您会看到错误。而不是在“如果创建”和“如果删除”结构之外进行选择和插入,而是将它们移到内部。创建记录时 :OLD 中没有值,删除记录时 :NEW 中没有值 不,这不是错误绑定变量错误的原因。原因是要引用:OLD:NEW 值,它应该是一个ROW LEVEL 触发器,它需要FOR EACH ROW 条件。

以上是关于Oracle中触发器内的select语句出现错误的绑定变量错误的主要内容,如果未能解决你的问题,请参考以下文章

在 SELECT 语句中按错误分组,导致 Oracle 中出现 ORA-00979 错误代码

Oracle SQL If语句使用select进行比较[重复]

Oracle的PL_SQL的异常处理

如何从 oracle pl sql 中的包主体内的 select 语句中捕获特定列

oracle数据库里面,在下面的select语句中,我需要增加一个条件为只查询3天内的记录。该如何编写,求教育

执行 `EXECUTE IMMEDIATE` Oracle 语句出现错误