1

我是 Oracle 触发器的新手。我使用以下语法创建了一个 EVENT 表:

CREATE TABLE Event
(event_id NUMBER (3) NOT NULL,
 event_date DATE NOT NULL,
 venue_id NUMBER (2) NOT NULL,
 concert_id NUMBER (3) NOT NULL
);

我想创建一个触发器以确保音乐会不能在 8 月份运行。我尝试了以下代码来创建触发器。触发器已成功创建,但在插入带有 8 月份的日期后,它已被插入。这不应该是。

CREATE OR REPLACE TRIGGER check_date
  BEFORE INSERT ON event
DECLARE 
  event_date date;
BEGIN
  IF (to_char(event_date, 'mm') = 8) THEN
    raise_application_error(-20000, 'Concerts cannot be run during August');
  END IF;
END;
4

2 回答 2

5

首先,触发器需要是行级触发器而不是语句级触发器。您希望为插入的每一行触发触发器,而不仅仅是为每条语句插入一次。将触发器声明为行级触发器允许您查看正在插入的每一行的数据。

其次,您不想声明局部变量event_date。您想查看正在插入的行是:new.event_date哪个。event_date

如果我把这两个放在一起

CREATE OR REPLACE TRIGGER check_date
  BEFORE INSERT ON event
  FOR EACH ROW
BEGIN
  IF (to_char(:new.event_date, 'mm') = 8) THEN
    raise_application_error(-20000, 'Concerts cannot be run during August');
  END IF;
END;

然后你会得到你想要的行为

SQL> insert into event values( 1, date '2012-08-01', 1, 1 );
insert into event values( 1, date '2012-08-01', 1, 1 )
            *
ERROR at line 1:
ORA-20000: Concerts cannot be run during August
ORA-06512: at "SCOTT.CHECK_DATE", line 3
ORA-04088: error during execution of trigger 'SCOTT.CHECK_DATE'

作为清洁的一般问题,您还希望将字符串与字符串和数字与数字进行比较。所以你会想要

to_number( to_char(:new.event_date, 'mm') ) = 8

或者

to_char(:new.event_date, 'fmmm') = '8'

或者

to_char(:new.event_date, 'mm') = '08'
于 2012-08-18T01:59:43.473 回答
0

改变:

IF (to_char(event_date, 'mm') = 8) THEN

至:

IF (to_char(event_date, 'mm') = '08') THEN

您正在比较字符串和数字。

于 2012-08-18T01:41:47.663 回答