PL/SQL Trigger activation on specific months - sql

i'm a university student working on a simple database project for our DB exam. I've reached the stage of developing the dynamic constraint for the DB via PL/SQL trigger; the database applies to a oil/gas refinirey enviroment.
Here is table on which the trigger should work:
CREATE TABLE FEED(
NUMBER_STOCK NUMBER(2) CHECK(NUMBER_STOCK>0),
REACT_NAME VARCHAR(20),
PROD_LANE_NUMB NUMBER(2),
DATE_FEED DATE PRIMARY KEY,
QUANTITY NUMBER(5) NOT NULL CHECK (QUANTITY>0),
CONSTRAINT FKA FOREIGN KEY (NUMBER_STOCK) REFERENCES STOCKS(NUMBER_STOCK) ON DELETE CASCADE,
CONSTRAINT FKA2 FOREIGN KEY (REACT_NAME,PROD_LANE_NUMB) REFERENCES PRODUCTION_PLANTS(REACT_NAME,PROD_LANE_NUMB) ON DELETE CASCADE
);
The trigger i am trying to develop has the following purpose:
During the winter and summer months(December-February and June-August) the production plants cannot work at full load due to many weather related factors, such corrosion, pipe dilation/constriction and higher/lower temepratures. During these months the QUANTITY of raw materials sent daily to the plants, must be less than the average of total QUANTITY sent in the months preeciding those periods( November and May).
Now here's how i developed my trigger(Note: there is already another AFTER INSERT OR UPDATE trigger active on the table):
CREATE OR REPLACE TRIGGER METEO
AFTER INSERT OR UPDATE ON FEED
FOR EACH ROW
DECLARE
ACTL_MONTH CHAR(3); --ACTUAL MONTH WITHIN 3 LETTER FORMAT --
MONTH_AVG NUMBER(8) := 0; --PREECIDING MONTHS AVARAGE--
FEED_QUAN NUMBER(8) := 0; --ACTUAL FEED INSERTED/UPDATED--
BEGIN
--GETTING DATE FROM DUAL IN 3 LETTER FORMAT--
SELECT TO_CHAR(TRUNC(SYSDATE,'MONTH'),'MON') INTO ACTL_MONTH FROM DUAL;
--CHECKING DATE--
IF ACTL_MONTH='MAY' THEN
SELECT AVG(QUANTITY) INTO MONTH_AVG FROM FEED WHERE TO_CHAR(TRUNC(DATE_FEED,'MONTH'),'MON')='MAY';
END IF;
IF ACTL_MONTH='NOV' THEN
SELECT AVG(QUANTITY) INTO MONTH_AVG FROM FEED WHERE TO_CHAR(TRUNC(DATE_FEED,'MONTH'),'MON')='NOV';
END IF;
--SELECTING THE QUANTITY FEEDED--
SELECT :NEW.QUANTITY INTO FEED_QUAN FROM FEED;
IF MONTH_AVG<FEED_QUAN THEN
RAISE_APPLICATION_ERROR(-20008,'EXCEEDING FEED QUANTITY DUE TO WEATHER LIMITATIONS.ROLLBACK');
END IF;
END;
/
But every time i insert a value the trigger does not fire, and allows me to insert/update rows with not allowed values.
So:
Did i made mistakes in PL/SQL code?(It compiled with no errors)
May trigger cannot be fired upon dates?
Should i use another type of trigger structure?(statement?before?)
This is my first question on stack overflow so have mercy on me, and yes i have used google and used stack search for similar question but did not find anything like my problem, if something is not clear point it to me and i will adjust/explain; besisde consdier that im a foreign student so expect LOTS of english grammar errors.

There are a couple of different ways to solve this problem. First, create a second table to hold your monthly averages:
CREATE TABLE MONTHLY_AVERAGE_FEED
(MONTH_YEAR DATE -- 01-MM-YYYY
PRIMARY KEY,
TOTAL_QUANTITY NUMBER,
TRANSACTIONS NUMBER,
AVERAGE_QUANTITY NUMBER
GENERATED ALWAYS AS (CASE
WHEN TRANSACTIONS > 0 THEN
TOTAL_QUANTITY / TRANSACTIONS
ELSE 0
END));
and maintained by a trigger:
CREATE TRIGGER FEED_AVERAGE_AIUD
AFTER INSERT OR UPDATE OR DELETE ON FEED
FOR EACH ROW
BEGIN
IF UPDATING OR DELETING THEN
-- Back out the 'old' values
UPDATE MONTHLY_AVERAGE_FEED
SET TOTAL_QUANTITY = GREATEST(TOTAL_QUANTITY - :OLD.QUANTITY, 0),
TRANSACTIONS = GREATEST(TRANSACTIONS - 1, 0)
WHERE MONTH_YEAR = TRUNC(:OLD.DATE_FEED, 'MONTH');
END IF;
IF INSERTING OR UPDATING THEN
MERGE INTO MONTHLY_AVERAGE_FEED maf
USING (SELECT TRUNC(:NEW.DATE_FEED, 'MONTH') AS MONTH_YEAR
FROM DUAL) d
ON (maf.MONTH_YEAR = d.MONTH_YEAR)
WHEN MATCHED THEN
UPDATE
SET TOTAL_QUANTITY := TOTAL_QUANTITY +
(:NEW.QUANTITY *
CASE
WHEN INSERTING OR UPDATING THEN 1
ELSE -1
END),
TRANSACTIONS = TRANSACTIONS + 1
WHEN NOT MATCHED THEN
INSERT (MONTH_YEAR, TRANSACTIONS, TOTAL_QUANTITY)
VALUES (TRUNC(:NEW.DATE_FEED, 'MONTH'), 1, :NEW.QUANTITY);
END IF;
END FEED_AVERAGE_AIUD;
Then in your trigger you can simply query the MONTHLY_AVERAGE_FEED table to get the average feed for whatever month you want.
The second option would be to rewrite #MT0's trigger as a compound trigger. The "BEFORE STATEMENT" section of the trigger would handle computing the average feed for whatever month(s) you want, while the "BEFORE EACH ROW" section would contain the rest of the work.

Thanks to the answers and the help given by Bob Jarvis and MT0 i have finally solved my problem.
So i added a support table for the averages like Bob Jarvis suggested, and then added a specific trigger to populate it when any row is inserted into FEED table of my first post; here's the trigger modified which compile properly:
CREATE OR REPLACE TRIGGER FEED_AVERAGE_AIUD
AFTER INSERT OR UPDATE OR DELETE ON FEED
FOR EACH ROW
BEGIN
IF UPDATING OR DELETING THEN
-- Back out the 'old' values
UPDATE MONTHLY_AVERAGE_FEED
SET TOTAL_QUANTITY = GREATEST(TOTAL_QUANTITY - :OLD.QUANTITY, 0),
TRANSACTIONS = GREATEST(TRANSACTIONS - 1, 0)
WHERE MONTH_YEAR = TRUNC(:OLD.DATE_FEED, 'MONTH');
END IF;
IF INSERTING OR UPDATING THEN
MERGE INTO MONTHLY_AVERAGE_FEED maf
USING (SELECT TRUNC(:NEW.DATE_FEED, 'MONTH') AS MONTH_YEAR
FROM DUAL) d
ON (maf.MONTH_YEAR = d.MONTH_YEAR)
WHEN MATCHED THEN
UPDATE
SET TOTAL_QUANTITY = TOTAL_QUANTITY +:NEW.QUANTITY,
TRANSACTIONS = TRANSACTIONS + 1
WHEN NOT MATCHED THEN
INSERT (MONTH_YEAR, TRANSACTIONS, TOTAL_QUANTITY)
VALUES (TRUNC(:NEW.DATE_FEED, 'MONTH'), 1, :NEW.QUANTITY);
END IF;
END FEED_AVERAGE_AIUD;
/
So with the average table in place and running i created the following trigger to check the consitency beetwen the new inserted/updated values and the averages in specified months:
CREATE OR REPLACE TRIGGER METEO
AFTER INSERT OR UPDATE ON FEED
FOR EACH ROW
DECLARE
ACT_QUANT NUMBER; --ACTUAL INSERTED/UPDATED QUANTITY---
ACT_MONTH NUMBER; --MONTH AT WHICH THE QUANTITY WAS INSERTED/UPDATED--
REF_AVERG NUMBER; --THE AVERAGE IN THE AVERAGES TABLE REFEERING TO THE ISNERTED/UPDATED MONTH--
BEGIN
ACT_MONTH:= EXTRACT(MONTH FROM :NEW.DATE_FEED);
ACT_QUANT:= :NEW.QUANTITY;
-- SO IF I AM INSERTING/UPDATING VALUES IN JUNE/JULY/AUGUST
-- I SIMPLY SEARCH THE AVERAGE TABLE WITH A QUERY WITH MONTH AND YEAR TAKEN
-- BY THE DATE_FEED
IF ACT_MONTH IN(6,7,8) THEN
SELECT AVERAGE_QUANTITY
INTO REF_AVERG
FROM MONTHLY_AVERAGE_FEED
WHERE EXTRACT(MONTH FROM MONTH_YEAR)=5 AND
EXTRACT(YEAR FROM MONTH_YEAR)=EXTRACT(YEAR FROM :NEW.DATE_FEED);
ELSIF ACT_MONTH=12 THEN --FOR DECEMBER I TAKE THE SAME YEAR NOVEMBER AVG--
SELECT AVERAGE_QUANTITY
INTO REF_AVERG
FROM MONTHLY_AVERAGE_FEED
WHERE EXTRACT(MONTH FROM MONTH_YEAR)=11 AND
EXTRACT(YEAR FROM MONTH_YEAR)=EXTRACT(YEAR FROM :NEW.DATE_FEED);
ELSIF ACT_MONTH IN (1,2) THEN --FOR JANUARY AND FEBRUARY I TAKE THE AVG OF THE PREVIOUS YEAR --
SELECT AVERAGE_QUANTITY
INTO REF_AVERG
FROM MONTHLY_AVERAGE_FEED
WHERE EXTRACT(MONTH FROM MONTH_YEAR)=11 AND
EXTRACT(YEAR FROM MONTH_YEAR)=EXTRACT(YEAR FROM :NEW.DATE_ALIM)-1;
END IF;
IF ACT_QUANT>REF_AVERG THEN
RAISE_APPLICATION_ERROR(
-20008,
'EXCEEDING FEED QUANTITY DUE TO WEATHER LIMITATIONS.ROLLBACK'
);
END IF;
END;
/
The trigger compiled and worked as it was intended, it's not elegant for sure, but it does his job. As ever I had to translate every table/attributes names from my original language to english so it's possibile that i forgot something or mispelled word,verbs etc.
Anyway thanks to everyone who replied and helped,hoping this will help somebody else someday, thank you guys.

Change the trigger from AFTER to BEFORE.
You don't need to use SELECT ... INTO to assign variables.
You aren't answering the question. You need to check if the month is Dec-Feb or Jun-Aug and then find the daily average for Nov or May (respectively).
Rather than getting the average for all Mays (or Novembers), you need to get the average for only the preceding May (or November).
Like this:
SET DEFINE OFF;
CREATE OR REPLACE TRIGGER METEO
BEFORE INSERT OR UPDATE ON FEED
FOR EACH ROW
DECLARE
MONTH_START DATE;
MONTH_AVG NUMBER(8);
BEGIN
MONTH_START := CASE EXTRACT( MONTH FROM :NEW.DATE_FEED )
WHEN 12 THEN ADD_MONTHS( TRUNC( :NEW.DATE_FEED, 'MM' ), -1 )
WHEN 1 THEN ADD_MONTHS( TRUNC( :NEW.DATE_FEED, 'MM' ), -2 )
WHEN 2 THEN ADD_MONTHS( TRUNC( :NEW.DATE_FEED, 'MM' ), -3 )
WHEN 6 THEN ADD_MONTHS( TRUNC( :NEW.DATE_FEED, 'MM' ), -1 )
WHEN 7 THEN ADD_MONTHS( TRUNC( :NEW.DATE_FEED, 'MM' ), -2 )
WHEN 8 THEN ADD_MONTHS( TRUNC( :NEW.DATE_FEED, 'MM' ), -3 )
ELSE NULL
END;
IF MONTH_START IS NULL THEN
RETURN;
END IF;
SELECT AVG( QUANTITY )
INTO MONTH_AVG
FROM FEED
WHERE DATE_FEED >= MONTH_START
AND DATE_FEED < ADD_MONTHS( MONTH_START, 1 );
IF MONTH_AVG <= :NEW.QUANTITY THEN
RAISE_APPLICATION_ERROR(-20008,'EXCEEDING FEED QUANTITY DUE TO WEATHER LIMITATIONS.ROLLBACK');
END IF;
END;
/

Related

Getting unexpected values for number of days between two dates in oracle

I am writing a SQL code which fetches two dates from the database and calculates the number of days between them. Here is the code:
create table borrower(
roll_no number,
date_of_issue date,
name_of_book varchar(20),
status varchar(10)
);
insert into borrower values(1,to_date('02-JAN-2022'),'dbms','issued');
insert into borrower values(2,to_date('10-JAN-2022'),'cns','issued');
insert into borrower values(3,to_date('17-JAN-2022'),'spos','issued');
insert into borrower values(4,to_date('26-JAN-2022'),'toc','issued');
create table fine(
roll_no number,
current_date date,
amount number
);
insert into fine values(1,to_date('14-FEB-2022'),null);
insert into fine values(2,to_date('14-FEB-2022'),null);
insert into fine values(3,to_date('14-FEB-2022'),null);
insert into fine values(4,to_date('14-FEB-2022'),null);
DECLARE
roll_counter number:=1;
initial_date date;
final_date date;
date_calc number;
BEGIN
loop
select date_of_issue into initial_date from borrower where roll_no=roll_counter;
select current_date into final_date from fine where roll_no=roll_counter;
date_calc:=final_date-initial_date;
dbms_output.put_line(date_calc);
roll_counter:=roll_counter+1;
exit when roll_counter>4;
end loop;
END;
/
drop table borrower;
drop table fine;
I am not getting any error, but instead getting unexpected values for the number of days. Here is the output:
Statement processed.
246.4165625
238.4165625
231.4165625
222.4165625
I was expecting the number of days between the two dates(check the table). Can someone help me sort this out.
CURRENT_DATE is an Oracle keyword that returns the current date. Name your column something that is not an Oracle keyword.
https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CURRENT_DATE.html
As #Matthew McPeak pointed out, CURRENT_DATE is a built-in function and that function is being called rather than returning your column value.
If you want the column value then you need to prefix the column name with the table name/alias and use fine.current_date:
DECLARE
roll_counter number:=1;
initial_date date;
final_date date;
date_calc number;
BEGIN
FOR roll_counter IN 1 .. 4 LOOP
select date_of_issue
into initial_date
from borrower
where roll_no=roll_counter;
select fine.current_date
into final_date
from fine
where roll_no=roll_counter;
date_calc:=final_date-initial_date;
dbms_output.put_line(date_calc);
END LOOP;
END;
/
Which, for your sample data, outputs:
43
35
28
19
Or you can use a single query (rather than multiple queries that are called in each loop iteration):
BEGIN
FOR r IN (
SELECT f.current_date - b.date_of_issue AS diff
FROM borrower b
FULL OUTER JOIN fine f
ON (b.roll_no = f.roll_no)
WHERE COALESCE(b.roll_no, f.roll_no) BETWEEN 1 AND 4
ORDER BY COALESCE(b.roll_no, f.roll_no)
) LOOP
dbms_output.put_line(r.diff);
END LOOP;
END;
/
db<>fiddle here

Creating a Trigger that runs on two tables

I have two tables, COPY and BORROW. Their columns are:
COPY (
Copy_id,
Bk_id,
Loc_id,
Opinion
)
and
BORROW (
Cus_evo,
B_Date,
R_Date,
Fee,
Copy_id,
Cus_id
)
I want to configure a trigger that ensures Copies that stored in a Exact location (London) (from Loc-id column of COPY table) cannot be Borrowed in December (from B_Date column of BORROW table).
I have created the following trigger:
CREATE OR REPLACE TRIGGER BORROW_TRIGGER
BEFORE INSERT ON BORROW FOR EACH ROW BEGIN
IF(TO_CHAR(TO_DATE(:NEW.B_Date, 'DD-MMM-YYYY'),'MMM'= 'DEC')
AND :NEW.Loc_id='LC0001')
THEN RAISE_APPLICATION_ERROR(-20669,'CANNOT BORROW BOOKS FROM LONDON STORE DURING MONTH DECEMBER');
END IF;
END;
/
The trigger is not created and have errors please cloud give me correct trigger for this??
Error i have experiencing
Errors: TRIGGER BORROW_TRIGGER
Line/Col: 3/5 PLS-00049: bad bind variable 'NEW.LOC_ID'
Since you only need to perform the check when b_date is in December, it's more efficient to add this as a when condition at the top of the trigger. This also simplifies the trigger logic.
create or replace trigger borrow_check_trg
before insert on borrow
for each row
when (to_char(new.b_date,'MM') = '12')
declare
l_loc_id copy.loc_id%type;
begin
select c.loc_id into l_loc_id
from copy c
where c.copy_id = :new.copy_id;
if l_loc_id = 'LC0001' then
raise_application_error(-20669, 'Books cannot be borrowed from the London store during December');
end if;
end;
You need to query the COPY table to get the field you need:
CREATE OR REPLACE TRIGGER BORROW_BI
BEFORE INSERT ON BORROW
FOR EACH ROW
DECLARE
strLoc_id COPY.LOC_ID%TYPE;
BEGIN
SELECT LOC_ID
INTO strLoc_id
FROM DUAL
LEFT OUTER JOIN COPY c
ON c.COPY_ID = :NEW.COPY_ID;
IF TO_CHAR(TO_DATE(:NEW.B_Date, 'DD-MMM-YYYY'), 'MMM') = 'DEC' AND
strLoc_id = 'LC0001'
THEN
RAISE_APPLICATION_ERROR(-20669,'CANNOT BORROW BOOKS FROM LONDON STORE DURING MONTH DECEMBER');
END IF;
END BORROW_BI;
You can check out the existence by using a Select statement with COUNT aggregation from the other table(copy) through use of common column (copy_id) among tables such as
CREATE OR REPLACE TRIGGER Trg_Borrow_Trigger_BI
BEFORE INSERT ON borrow
FOR EACH ROW
DECLARE
v_exists INT;
BEGIN
SELECT COUNT(*)
INTO v_exists
FROM copy
WHERE copy_id = :NEW.copy_id
AND loc_id = 'LC0001'
AND TO_CHAR( :NEW.b_Date, 'MM' ) = '12';
IF v_exists > 0 THEN
RAISE_APPLICATION_ERROR(-20669,
'CANNOT BORROW BOOKS FROM LONDON STORE DURING MONTH DECEMBER');
END IF;
END;
/
where
TO_DATE() conversion is superfluous
to prepend loc_id with :NEW is not possible, since the trigger is created for
the table borrow has not this column, while copy table has.

PLSQL condition statement in trigger involving 2 tables

I've two tables purchases and customers, I need to update visits_made (number) in customers if time of purchase ptime (date) in purchases table is different from the already existing last_visit (date) in customers table.
Here is the trigger that I'm trying and I'm doing something terribly and shamefully wrong.
create or replace trigger update_visits_made
after insert on purchases
for each row
declare new_date purchases.ptime%type;
begin
select ptime into new_date
from purchases
where purchases.ptime = :new.ptime;
if new_date = customers.last_visit then
new.last_visit=old.last_visit;
else
update customers
set visits_made=visits_made+1
where purchases.ptime=:new.ptime;
end if;
end;
/
show errors
Can anybody please tell me where I'm going wrong?
I get following errors
LINE/COL ERROR
10/15 PLS-00103: Encountered the symbol "=" when expecting one of the
following:
:= . ( # % ;
11/1 PLS-00103: Encountered the symbol "ELSE"
16/1 PLS-00103: Encountered the symbol "END"
This is a scalar assignment in PL/SQL:
new.last_visit = old.last_visit;
Not only should this be done with := but new and old should have colons before their names:
:new.last_visit := :old.last_visit;
Once you have fixed that problem, then the update will pose an issue:
update customers
set visits_made=visits_made+1
where purchases.ptime = :new.ptime;
It is unclear to me what this is supposed to be doing, so I can't suggest anything, other than pointing out that purchases is not defined.
I think somehow i get your requirement. Basically its a ticker which count the vists of user based on Login dates. I have written a snippet below which replicates the same scenario as mentioned Above. Let me know if this helps.
-- Table creation and insertion script
CREATE TABLE PURCHASES
(
P_ID NUMBER,
P_TIME DATE
);
INSERT INTO PURCHASES
SELECT LEVEL,SYSDATE+LEVEL FROM DUAL
CONNECT BY LEVEL < 10;
CREATE TABLE CUSTOMERS
(
P_ID NUMBER,
P_VISITS NUMBER
);
INSERT INTO CUSTOMERS
SELECT LEVEL,NULL FROM DUAL
CONNECT BY LEVEL < 10;
-- Table creation and insertion script
--Trigger Script
CREATE OR REPLACE TRIGGER update_purchase BEFORE
INSERT ON purchases FOR EACH row
DECLARE
new_date purchases.p_time%type;
BEGIN
BEGIN
SELECT A.P_TIME
INTO new_date
FROM
(SELECT p_time,
ROW_NUMBER() OVER(PARTITION BY P_ID ORDER BY P_TIME DESC) RNK
-- INTO new_date
FROM purchases
WHERE purchases.p_id = :new.p_id
)a
WHERE A.RNK =1;
EXCEPTION WHEN OTHERS THEN
RETURN;
END;
IF :NEW.P_TIME <> new_date THEN
UPDATE customers
SET P_VISITS =NVL(P_VISITS,0)+1
WHERE p_id=:new.p_id;
END IF;
END;
--Trigger Script
--Testing Script
INSERT INTO PURCHASES VALUES
(9,TO_DATE('12/11/2015','MM/DD/YYYY'));
--Testing Script

Automatically update a column in a table with a trigger

I'm having a problem with a trigger code (table mutation and more!) and I can't find
what is the problem.
Basically, I have a table SEMESTER(id_semester, semester_name, begin_date, end_date).
On the insertion of a row, I want the semester_name to be updated with a value according
to what's in begin_date. For example, if the begin_date is '2000-01-01', I want the value of
semester_name to be W00 (for winter 2000).
My first try was to write an 'after insert' trigger, which didn't work because of a table mutation error. Here it is:
CREATE TRIGGER Test
BEFORE INSERT ON Semester
FOR EACH ROW
DECLARE
sem CHAR(1);
year CHAR(2);
BEGIN
-- begin_date is either 1, 5 or 9.
IF (EXTRACT(MONTH FROM :new.begin_date) = '1') THEN
saison := 'W';
ELSIF (EXTRACT(MONTH FROM :new.begin_date) = '5') THEN
saison := 'S';
ELSE
saison := 'F';
END IF;
year := TO_CHAR(:new.date_debut, 'MM');
UPDATE Semester
SET semester_name = CONCAT(sem, year)
WHERE id_semester = :new.id_semester;
END;
/
After, I tried to make a 'before insert' trigger, thinking it would work better but it does not.
Anyone could point me in the right direction?
Thanks!
Assuming id_semester is the primary key, instead of an UPDATE statement, you would just want to assign the :new.semester_name
:new.semester_name := concat( sem, year );
The mutanting table error occurs only with "each row" kind of triggers, try to change your after insert trigger for a "statement" type

INSERT TRIGGER IN ORACLE

I am new to triggers in Oracle. I created an EVENT table with this syntax:
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
);
I want to create a trigger to ensure that concerts cannot run during the month of August. I tried the following code to create the trigger. The trigger was created successfully but after inserting a date with the month of August, it was inserted. This is not suppose to be.
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;
First, the trigger needs to be a row-level trigger not a statement-level trigger. You want the trigger to be fired for every row that is inserted not just once for every statement. Declaring the trigger a row-level trigger allows you to see the data for each row that is being inserted.
Second, you don't want to declare a local variable event_date. You want to look at :new.event_date which is the event_date for the row that is being inserted.
If I put those two together
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;
then you'll get the behavior you want
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'
As a general matter of cleanliness, you also want to compare strings with strings and numbers with numbers. So you would want either
to_number( to_char(:new.event_date, 'mm') ) = 8
or
to_char(:new.event_date, 'fmmm') = '8'
or
to_char(:new.event_date, 'mm') = '08'
change:
IF (to_char(event_date, 'mm') = 8) THEN
to:
IF (to_char(event_date, 'mm') = '08') THEN
You're comparing between string and number.