Handle an exception in a trigger in oracle - oracle

I'm a rookie in oracle and I want to display an error when (expAnnee*100 + expMois) < YYMM (YYMM of SYSDATE) to check the validity of a credit card.
expAnnee and expMois are numbers.
I get the following error:
PLS-00201: identifier 'NEW.EXPANNEE' must be declared
But this is a trigger, and in my "InfoCredit" table expAnnee and expMois are indeed there.
CREATE OR REPLACE TRIGGER VALID_CARD
BEFORE INSERT ON INFOCREDIT
FOR EACH ROW
DECLARE
ex_expired EXCEPTION;
testdate NUMBER;
BEGIN
SELECT to_number(to_char(to_date(SYSDATE, 'DD-MM-YYYY'), 'YYMM'))
INTO testdate
FROM Dual;
if ((new.expAnnee*100+new.expMois) < testdate)
Then RAISE ex_expired;
END IF;
EXCEPTION
WHEN ex_expired
THEN DBMS_OUTPUT.PUT_LINE('CARD EXPIRED');
END;
/

Refer to new as :new
E.g.
if ((:new.expAnnee*100+:new.expMois) < testdate)

Related

How to create user defined exception in a procedure?

Using a procedure adds an employee record into the employee table, also validates the input values salary must be always greater than or equal to 500, raise a user-defined exception for any validation error.
You can create something like this. Add parameters for other columns as well
CREATE OR REPLACE PROCEDURE insert_emp (salary NUMBER)
AS
invalid_salary EXCEPTION;
BEGIN
IF salary < 500 THEN
RAISE invalid_salary;
ELSE
INSERT INTO employees(salary) VALUES (salary);
COMMIT;
END IF;
END;
You can also associate an Exception number with the exception
Exception number for user-defined exceptions must be in the range of -20000 to -20999
CREATE OR REPLACE PROCEDURE insert_emp (salary NUMBER)
AS
invalid_salary EXCEPTION;
PRAGMA EXCEPTION_INIT (invalid_salary, -20100);
BEGIN
IF salary < 500 THEN
RAISE invalid_salary;
ELSE
INSERT INTO employees(salary) VALUES (salary);
COMMIT;
END IF;
END;
This sounds like a homework problem so I'll let using a trigger go, except a possible gotta and th show a better way of handling it. You raise the user defined exception "invalid salary" however unless your code handles it Oracle will throw the error "ORA-06510 Unhandled user defined exception", indicating it does not know what with it. So what is a better way: Define the column and include a check constraint on it.
Create table employees (...
, salary number(8,2) not null
constraint salary_less_then_minimum check (salary >= 500)
, ...);

a double-quoted delimited-identifier error SQL

Hi everyone am experiencing this error in oracle
Errors: TRIGGER NOUPDATE
Line/Col: 9/5 PLS-00103: Encountered the symbol "IF" when expecting one of the following:
; <an identifier> <a double-quoted delimited-identifier>
This is the code:
CREATE OR REPLACE TRIGGER NoUpdate
BEFORE UPDATE OF apartmentsize ON rental
FOR EACH ROW
DECLARE
apartmentsize INT(22);
BEGIN
IF (apartmentsize < 60) THEN
BEGIN
RAISE_APPLICATION_ERROR(-20112,
'You cannot update the apartmentsize');
ROLLBACK;
END IF;
END;
/
I think it's firing the trigger but the IF condition is never true. I don't see anywhere that you assign a value to apartmentsize.
If you think it is this statement:
apartmentsize int(22);
Then no, that is simply saying that aparmentsize is declared as a 22-digit integer. If you want to assign a value:
apartmentsize int := 22;
And according to the 18c SQL Language Reference, 'int' is not a valid data type. Supported numeric data types are:
number
float
binary_float
binary_double
What you want is NUMBER(precision,scale). See here.
You have a BEGIN without an END and you probably want to use :NEW.apartmentsize bind variable to reference the updated value rather than declaring a variable in the trigger:
CREATE OR REPLACE TRIGGER NoUpdate
BEFORE UPDATE OF apartmentsize ON rental
FOR EACH ROW
DECLARE
BEGIN
IF (:NEW.apartmentsize < 60) THEN
RAISE_APPLICATION_ERROR(
-20112,
'You cannot update the apartmentsize'
);
END IF;
END;
/
(Note: Including ROLLBACK is pointless as raising the exception will implicitly trigger a rollback and once you have raised the exception the rest of the code in the trigger will not be parsed as an exception has been raised.)
Then if you have the table:
CREATE TABLE rental ( id, apartmentsize ) AS
SELECT 1, 100 FROM DUAL;
Then:
UPDATE rental
SET apartmentsize = 60
WHERE id = 1;
Will work but:
UPDATE rental
SET apartmentsize = 59
WHERE id = 1;
Will raise the exception:
ORA-20112: You cannot update the apartmentsize
ORA-06512: at "FIDDLE_DAVWBSJBRDBITOSDOROT.NOUPDATE", line 4
ORA-04088: error during execution of trigger 'FIDDLE_DAVWBSJBRDBITOSDOROT.NOUPDATE'
db<>fiddle here

Procedure with Exception Handling

Create a PL/SQL Procedure to insert employee details into Employee table. Before inserting, check whether the employee age is eligible or not. Employee age should be 18 or greater. Values are passed as argument to the procedure.
If age valid, insert employee record into table and print the message "Age valid - Record inserted", else print the message "Age invalid - Record not inserted" by raising an exception.
coding:
CREATE OR REPLACE PROCEDURE CHECK_AGE_ELIGIBILITY(
v_id IN EMPLOYEE.EMPID%TYPE,
v_name IN EMPLOYEE.EMPNAME%TYPE,
v_age IN EMPLOYEE.AGE%TYPE)AS
BEGIN
INSERT INTO Employee(EMPID,EMPNAME,AGE)Values(103,'Robert',24);
select age from Employee;
IF AGE >=18
dbms_output.put_line('Age valid -Record inserted');
else
dbms_output.put_line('Age invalid -Record not inserted');
END;
/
EXPECTED OUTPUT:
Age valid -Record inserted
You want to check first, then insert if the check succeds (while your code is doing things the other way around). I also fixed the syntax of your if statement, and changed the insert statement so it uses the procedure arguments instead of hardcoded values. Finally, if you want to raise an error, then use raison_application_error() rather than put_line().
This should do what you want:
create or replace procedure check_age_eligibility(
v_id in employee.empid%type,
v_name in employee.empname%type,
v_age in employee.age%type
)
as
begin
if v_age >=18 then
insert into employee(empid,empname,age)values(v_id, v_name, v_age);
dbms_output.put_line('age valid -record inserted');
else
raise_application_error( -20001, 'age invalid - record not inserted' );
end if;
end;
/
Although this might not be what you were asked to do, please note that you don't need a procedure for this. You can just use a check constraint:
alter table employee add constraint age_above_18 check(age >= 18);
You can then use regular insert statements to feed the table - an error is raised for each row that conflicts with the constraint.
Demo on DB Fiddle
If you want to include the user-defined exception. declare it inside the procedure.
create or replace PROCEDURE CHECK_AGE_ELIGIBILITY(
v_id IN EMPLOYEE.EMPID%TYPE,
v_name IN EMPLOYEE.EMPNAME%TYPE,
v_age IN EMPLOYEE.AGE%TYPE) as
not_of_age exception;
begin
if v_age>=18 then
insert into EMPLOYEE(empid,empname,age) values(v_age,v_name,v_age);
dbms_output.put_line('Age valid - Record inserted');
else
raise not_of_age;
end if;
exception
when not_of_age then
dbms_output.put_line('Age invalid - Record not inserted');
end;
/

PLSQL: BEFORE INSERT TRIGGER (check value in column from other table before allowing insert)

I've made a simple DVD store database. The DVD table has a column "status" which can be either 'FOR_RENT','FOR_SALE','RENTED',or 'SOLD'. I want to write a trigger to block any insertions into my RENTALS table if the status column in the DVD table is not set to 'FOR_RENT'.
Much of the documents I've looked at generally don't show example using values from two different tables so I'm a bit flummaxed.
This is what I believe has been my best attempt so far:
CREATE OR REPLACE TRIGGER RENTAL_UNAVAILABLE
BEFORE INSERT ON RENTAL;
FOR EACH ROW
WHEN (DVD.STATUS != 'FOR_RENT')
DECLARE
dvd_rented EXCEPTION;
PRAGMA EXCEPTION_INIT( dvd_rented, -20001 );
BEGIN
RAISE dvd_rented;
EXCEPTION
WHEN dvd_rented THEN
RAISE_APPLICATION_ERROR(-20001,'DVD has been rented');
END;
/
I'm getting this error:
ORA-00911: invalid character
Try this - I have not complied the code, but should be good. In case you see any compilation issues let me know and post schema on sqlfiddle.com
CREATE OR REPLACE TRIGGER rental_unavailable
BEFORE INSERT
ON rental
FOR EACH ROW
DECLARE
dvd_rented EXCEPTION;
PRAGMA EXCEPTION_INIT (dvd_rented, -20001);
n_count NUMBER (1);
BEGIN
SELECT COUNT (*)
INTO n_count
FROM dvd
WHERE dvd_id = :NEW.dvd_id AND dvd.status = 'FOR_RENT' AND ROWNUM < 2;
IF n_count > 0
THEN
RAISE dvd_rented;
END IF;
EXCEPTION
WHEN dvd_rented
THEN
raise_application_error (-20001, 'DVD has been rented');
END;

oracle handling no data from query

I am writing a trigger to check if an employee is allocated to two flights that overlap.
It would be something like:
select flight_id from flight
where arrival_time > :new.departure_time
and departure_time < :new.arrival_time;
if flight_id is empty
[do nothing]
if flight_id exists
[raise application error]
Can anyone help me out in how I would have to code the conditional logic there? This is my first time working with oracle (university coursework).
SELECT ... INTO is your friend. It will raise an exception, you catch it, do nothing, otherwise and raise your own error.
select flight_id into v
from flight
where arrival_time > :new.departure_time
and departure_time < :new.arrival_time;
raise_application_error(-20000, 'not good');
exception
when NO_DATA_FOUND
then return 1
when others
then raise_application_error(-20011,'really good');
DECLARE
V_some_varible NUMBER;
BEGIN
Seclect 1 into v_some_varible from dual where 1 = 0;
EXCEPTION -- exception handlers begin
WHEN NO_DATA_FOUND THEN
INSERT INTO errors (message) VALUES ('no data found');
WHEN OTHERS THEN -- handles all other errors
ROLLBACK;
END;
Note the 1 = 0 to force the no data found exception. This example should work in any Oracle database with the exception of the insert into an errors table.

Resources