使用行触发器比较旧日期和新日期

Using a row trigger to compare old dates to new dates

嘿伙计们,我有一个我似乎无法解决的问题。

我必须创建一个行触发器,这样当我插入一个新的申请时,申请人不能在上次申请该职位后的 30 天内申请过该职位。

到目前为止,这是我的代码:我认为我在正确的轨道上,但我似乎无法将它们串在一起。插入的日期应该会触发触发器。

CREATE OR REPLACE TRIGGER applicant_date
AFTER INSERT ON APPLIES
FOR EACH ROW
DECLARE applydate applies.appdate%TYPE;

BEGIN
SELECT appdate INTO applydate
FROM applies
where anumber=:New.anumber
and pnumber=:New.pnumber;

IF :New.appdate - applydate < 30 THEN
  RAISE_APPLICATION_ERROR(-20001,
                        'Applicantion within 30 days of last 
application.');
                        END IF;
END;
/

INSERT INTO APPLIES(anumber, pnumber, appdate)
VALUES(000004, 00000007, '13-JAN-2000');

它还要求我输入绑定,我只是没有足够的经验来完成它。无论我输入什么,我都会得到: PLS-00487: 对变量 'SQLDEVBIND1Z_2'

的引用无效

以下是对您有帮助的表格:

CREATE TABLE APPLIES(
anumber     NUMBER(6)   NOT NULL, /* Applicant number       */
pnumber     NUMBER(8)   NOT NULL, /* Position number        */
appdate     DATE        NOT NULL, /* Application date       */
CONSTRAINT APPLIES_pkey PRIMARY KEY ( anumber, pnumber, appdate ), 
CONSTRAINT APPLIES_fkey1 FOREIGN KEY ( anumber )
            REFERENCES APPLICANT ( anumber )
            ON DELETE CASCADE,
CONSTRAINT APPLIES_fkey2 FOREIGN KEY ( pnumber )
            REFERENCES POSITION ( pnumber ) 
            ON DELETE CASCADE);

 INSERT INTO APPLIES VALUES( 000001, 00000001, TO_DATE('13-DEC-1999','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000002, 00000001, TO_DATE('13-DEC-1999','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000003, 00000002, TO_DATE('14-NOV-1999','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000004, 00000002, TO_DATE('20-JAN-2000','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000005, 00000002, TO_DATE('22-JAN-2000','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000005, 00000003, TO_DATE('09-MAY-1999','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000006, 00000003, TO_DATE('17-JUN-1999','DD- 
 MON-YYYY') ); 
 INSERT INTO APPLIES VALUES( 000007, 00000003, TO_DATE('18-JUN-1999','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000007, 00000004, TO_DATE('13-APR-2000','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000008, 00000004, TO_DATE('13-APR-2000','DD- 
 MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000009, 00000004, TO_DATE('14-APR-2000','DD- 
MON-YYYY') );
 INSERT INTO APPLIES VALUES( 000010, 00000005, TO_DATE('23-SEP-1999','DD- 
MON-YYYY') );
INSERT INTO APPLIES VALUES( 000001, 00000006, TO_DATE('26-OCT-1999','DD- 
MON-YYYY') );
INSERT INTO APPLIES VALUES( 000002, 00000006, TO_DATE('27-OCT-1999','DD- 
MON-YYYY') );
INSERT INTO APPLIES VALUES( 000003, 00000006, TO_DATE('28-OCT-1999','DD- 
MON-YYYY') );
INSERT INTO APPLIES VALUES( 000004, 00000007, TO_DATE('01-JAN-2000','DD- 
MON-YYYY') ); /*row i am trying to trigger*/
INSERT INTO APPLIES VALUES( 000005, 00000007, TO_DATE('03-JAN-2000','DD- 
MON-YYYY') );
INSERT INTO APPLIES VALUES( 000006, 00000007, TO_DATE('04-JAN-2000','DD- 
MON-YYYY') );
INSERT INTO APPLIES VALUES( 000007, 00000007, TO_DATE('07-JAN-2000','DD- 
MON-YYYY') );

非常感谢您,非常感谢。

我不知道你收到的错误与你的消息的其余部分有什么关系。

无论如何:AFTER 触发器引发 变异 table 错误。如果你切换到 BEFORE 一个,那么它看起来像这样:

SQL> CREATE OR REPLACE TRIGGER applicant_date
  2     before INSERT
  3     ON APPLIES
  4     FOR EACH ROW
  5  DECLARE
  6     applydate  applies.appdate%TYPE;
  7  BEGIN
  8     SELECT appdate
  9       INTO applydate
 10       FROM applies
 11      WHERE     anumber = :New.anumber
 12            AND pnumber = :New.pnumber;
 13
 14     IF :New.appdate - applydate < 30
 15     THEN
 16        RAISE_APPLICATION_ERROR (-20001,
 17                                 'Applicantion within 30 days of last application.');
 18     END IF;
 19  END;
 20  /

Trigger created.

测试:

SQL> INSERT INTO APPLIES(anumber, pnumber, appdate) VALUES(000004, 00000007, date '2000-01-13');
INSERT INTO APPLIES(anumber, pnumber, appdate) VALUES(000004, 00000007, date '2000-01-13')
            *
ERROR at line 1:
ORA-20001: Applicantion within 30 days of last application.
ORA-06512: at "SCOTT.APPLICANT_DATE", line 12
ORA-04088: error during execution of trigger 'SCOTT.APPLICANT_DATE'


SQL> INSERT INTO APPLIES(anumber, pnumber, appdate) VALUES(000004, 00000007, date '2000-04-13');

1 row created.

SQL>

如评论中所述,我建议您避免使用 Trigger 满足此要求,并建议您将 INSERT 作为过程的一部分或 PL/SQL 块进行转换,从而引发基于插入的异常。

DECLARE
  anumber  applies.anumber%type := 4;
  pnumber  applies.pnumber%type := 7;
  appdate  applies.appdate%type :=  to_date('13-JAN-2000','dd-mon-yyyy');
BEGIN
INSERT INTO APPLIES(anumber, pnumber, appdate)

with input(anumber, pnumber, appdate) as
  (
       select anumber, pnumber, appdate from dual  
  ) select * from input i 
        where not exists ( select 1 from applies ap where 
                                i.anumber = ap.anumber
                            and i.pnumber = ap.pnumber
                            and i.appdate - ap.appdate  < 30  ) ;
   IF SQL%ROWCOUNT = 0 THEN
    RAISE_APPLICATION_ERROR(-20001,
    'Application within 30 days of last application.');
   ELSE
     COMMIT;
   END IF;

END;
/

DEMO