'坏绑定变量'在触发器中

时间:2015-01-22 17:56:54

标签: oracle plsql triggers

我的SQL Developer编写的代码与以下触发器有关:

CREATE OR REPLACE TRIGGER AGGIORNA_QTA 
AFTER INSERT ON ACQUISTI 
FOR EACH ROW 
BEGIN
  update prodotti set qta=:old.qta-(select qtaacq from acquisti
    where utente=:new.utente and prodotto=:new.prodotto and data=:new.data);
END;

这是数据库表定义:

CREATE TABLE PRODOTTI(  
 CODICE NUMBER, 
 NOME VARCHAR2(10), 
 QTA NUMBER, 
 PREZZO NUMBER, 
 PRIMARY KEY ("CODICE"))

CREATE TABLE UTENTI(
 USERNAME VARCHAR2(10), 
 NOME VARCHAR2(10), 
 COGNOME VARCHAR2(10), 
 PRIMARY KEY ("USERNAME"))

CREATE TABLE ACQUISTI(
 UTENTE VARCHAR2(10), 
 PRODOTTO NUMBER, 
 DATA DATE, 
 QTAACQ NUMBER, 
 PRIMARY KEY (UTENTE,PRODOTTO,DATA),
 FOREIGN KEY (UTENTE) REFERENCES UTENTI (USERNAME),
 FOREIGN KEY (PRODOTTO) REFERENCES PRODOTTI (CODICE)) 

问题是我一直收到以下错误:

Error(2,29): PLS-00049: bad bind variable 'OLD.QTA'

我做错了什么?

2 个答案:

答案 0 :(得分:2)

问题是你试图在错误的表中设置变量,ACQUISTI没有名为qta的列,但PRODOTTI表有一个名为qta的列

答案 1 :(得分:0)

oldnew伪月仅存在于触发器所针对的表中。对于您正在更新的表格,您可以直接参考qta,并使用当前值进行计算:

update prodotti set qta = qta - ...

您没有指定该表中的哪一行进行更新,因此您需要添加以下内容:

where codice = :new.prodotto

但是,您尝试从同一个表中选择要插入的内容,这样您就会收到ORA-04091变异表错误。当您根据主键查询时,您不能期待多行,因此您根本不需要查询,只需使用新行即可qtaacq

CREATE OR REPLACE TRIGGER AGGIORNA_QTA 
AFTER INSERT ON ACQUISTI 
FOR EACH ROW 
BEGIN
  update prodotti set qta = qta - :new.qtaacq
  where codice = :new.prodotto;
END;
/

SQL Fiddle demo

您可能会发现,这并不能像在多用户环境中那样可靠地保持主表中的数量。同时插入可能会看到相同的旧qta值并导致更新丢失。