用于更新和插入的错误绑定变量触发器

时间:2014-09-09 03:18:20

标签: sql database plsql triggers

我一直收到错误的绑定变量错误。我已经尝试过调试它,但这仍然挥之不去,不太清楚为什么它在这里这么说。

我尝试做的事情就好像有人在1993年之前插入了enrols数据库那样他们就可以获得10%的折扣。此外,如果更新细节并在1993年开始之前注册,那么给他们10%的折扣。

errors:
6/31     PLS-00049: bad bind variable 'OLD.PAPER_COST'
6/50     PLS-00049: bad bind variable 'OLD.PAPER_COST'
14/31    PLS-00049: bad bind variable 'NEW.PAPER_COST'
14/50    PLS-00049: bad bind variable 'NEW.PAPER_COST'

不应该没关系,我没有在我的enrols关系中引用paper_cost,而是在我的论文关系中,因为我正在呼叫"更新论文"在paper_cost之前?

CREATE OR REPLACE TRIGGER discount_160
BEFORE INSERT OR UPDATE ON enrols
FOR EACH ROW
BEGIN
    IF UPDATING THEN
      IF (date_enrolled < TO_DATE('01-Jan-1993', 'dd-mon-yyyy')) THEN
         IF (paper_code = 160) THEN
            UPDATE papers
            SET paper_cost = (:OLD.paper_cost - (:OLD.paper_cost * 0.1))
            WHERE papers.paper_code = enrols.paper_code;
       END IF;
    END IF;
    ELSE --inserting
      IF (date_enrolled < TO_DATE('01-Jan-1993', 'dd-mon-yyyy')) THEN
         IF (paper_code = 160) THEN
            UPDATE papers
            SET paper_cost = (:NEW.paper_cost - (:NEW.paper_cost * 0.1))
            WHERE papers.paper_code = enrols.paper_code;
         END IF;
      END IF;
   END IF;
END;
/

我的enrols关系:

CREATE TABLE enrols
       (paper_code         INT     ,
       student_id         INT      REFERENCES student(student_id),
       date_enrolled      DATE,
       dept_id            INT,
       PRIMARY KEY(paper_code, student_id, dept_id),
       FOREIGN KEY (paper_code, dept_id) REFERENCES papers(paper_code, dept_id));

INSERT INTO enrols VALUES
   (160, 172384, TO_DATE('22-Mar-1994', 'dd-mon-yyyy'), 01);
INSERT INTO enrols VALUES
   (444, 849294, TO_DATE('14-Jul-1992', 'dd-mon-yyyy'), 04);
INSERT INTO enrols VALUES
   (160, 384583, TO_DATE('07-Aug-1995', 'dd-mon-yyyy'), 01);
INSERT INTO enrols VALUES
   (160, 999999, TO_DATE('18-Aug-1991', 'dd-mon-yyyy'), 01);

我的论文关系:

CREATE TABLE papers
   (paper_code      INT,
   EFTS             INT     NOT NULL,
   dept_id          INT     REFERENCES departments(dept_id),
   paper_cost       INT,  
   PRIMARY KEY(paper_code, dept_id));


INSERT INTO papers VALUES
   (160, 0.18, 01, 800);

任何帮助我指明正确方向的帮助都会很棒。

2 个答案:

答案 0 :(得分:1)

触发器中有很多错误。

BEGIN
    IF UPDATING THEN
(1)   IF ([:new.|:old.]date_enrolled < TO_DATE('01-Jan-1993', 'dd-mon-yyyy')) THEN
(1)      IF ([:new.|:old.]paper_code = 160) THEN
            UPDATE papers
            SET paper_cost = (:OLD.paper_cost - (:OLD.paper_cost * 0.1))
(2)         WHERE papers.paper_code = <strike>enrols</strike>[:new].paper_code;
       END IF;
    END IF;
    ELSE --inserting
(3)   IF ([:new.]date_enrolled < TO_DATE('01-Jan-1993', 'dd-mon-yyyy')) THEN
(3)      IF ([:new.]paper_code = 160) THEN
            UPDATE papers
            SET paper_cost = (:NEW.paper_cost - (:NEW.paper_cost * 0.1))
(2)         WHERE papers.paper_code = <strike>enrols</strike>[:new].paper_code;

(1):触发器有两个可用的伪行:NEW和OLD。更新时,OLD行包含表中当前存在的数据。 NEW行包含更新完成后的行。所以你不能只召唤date_enrolled。您的意思是:new.date_enrolled还是:old.date_enrolledpaper_code在两个地方也是如此。

(2):您正在为表papers发布Update语句,但您指的是enrols。那个是从哪里来的?你还没有定义它。你和我知道你的意思是表enrols,但编译器并不知道。此外,您不需要该表,您已经在该表的触发器中,并且您在其中一个伪行中拥有您需要的数据。我想你想要:NEW中的那个,但这是你的决定。此外,由于paper_cost似乎在两个表格中(不是最佳数据建模理念),您也应该更改:NEW.paper_cost

(3):在触发器的“插入”部分中,:OLD伪行只有NULL,所以你想在这里使用:NEW是非常安全的。

不是错误,只是一些技巧:声明一个名为oh,CutoffDate的本地日期变量来放置TO_DATE调用的结果。然后只需引用该变量,而不是在两个地方调用该函数。此外,将值减少10%的更直接方法是SET paper_cost = :OLD.paper_cost * 0.9

另外,由于在插入和更新部分都执行相同的代码,为什么不将它们组合起来呢?

所以新的触发器看起来像这样:

CREATE OR REPLACE TRIGGER discount_160
BEFORE INSERT OR UPDATE ON enrols
FOR EACH ROW
DECLARE
    CUTOFF  DATE := TO_DATE( '01-Jan-1993', 'dd-mon-yyyy' );
BEGIN
    IF :new.date_enrolled < CUTOFF AND
       :new.paper_code = 160 THEN
        :new.paper_cost := :old.paper_cost * 0.9;
        UPDATE papers
          SET paper_cost = :new.paper_cost
        WHERE paper_code = :new.paper_code;
    END IF;
END;

我还没有尝试过编译它,如果我在某个地方搞砸了或者你有疑问,请告诉我。

答案 1 :(得分:0)

您可以尝试在您的对帐单中将字段paper_cost引用为papers.paper_cost,而不是使用:NEW或:OLD