Использование триггера строки для сравнения старых дат с новыми датами - PullRequest
1 голос
/ 04 апреля 2019

Эй, ребята, у меня есть проблема, которую я просто не могу решить.

Мне нужно создать триггер строки, чтобы при вставке нового приложения заявитель не мог подать заявку на ту же позицию в течение 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') );

Заранее большое спасибо, высоко ценится.

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Понятия не имею, какая у вас ошибка связана с остальной частью вашего сообщения.

В любом случае: AFTER триггер вызывает ошибку таблицы мутаций . Если вы переключитесь на 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>
0 голосов
/ 04 апреля 2019

Как упоминалось в комментариях, я бы порекомендовал вам избегать триггера для этого требования и посоветовал бы вам преобразовать 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

...