I'm trying to create a code in which i delete a student from my table by specifying his nr_matr, but if i don't have that nr_matr in my table then i want to trow an exception.
this is my code:
CREATE OR REPLACE PACKAGE manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type);
END manager_faculty;
/
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type) IS
BEGIN
DELETE from student
WHERE nr_matricol=nr_matr;
EXCEPTION
WHEN no_data_found THEN
SELECT COUNT(*) INTO counter FROM student WHERE nr_matricol=nr_matr;
IF counter = 0 THEN
raise_application_error (-20001, 'There is no student with the number' || nr_matr);
END IF;
END delete_stud;
END manager_faculty;
/
set serveroutput on;
BEGIN
manager_faculty.delete_stud(125);
END;
/
When i'm trying to compile my code it says that the package body was created whit compilation errors. What am i doing wrong?
The error is PLS-00201: identifier 'COUNTER' must be declared and you can find this out by running SHOW ERRORS; after trying to compile your package body.
You can fix it like this:
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type)
IS
counter INT;
BEGIN
DELETE FROM student
WHERE nr_matricol=nr_matr;
EXCEPTION
WHEN no_data_found THEN
SELECT COUNT(*)
INTO counter
FROM student
WHERE nr_matricol=nr_matr;
IF counter = 0 THEN
raise_application_error (
-20001,
'There is no student with the number' || nr_matr
);
END IF;
END delete_stud;
END manager_faculty;
/
SHOW ERRORS;
However, the code won't run as you expect as DELETE FROM will not throw an exception if it does not delete any rows. You will need to check SQL%ROWCOUNT:
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type)
IS
BEGIN
DELETE from student
WHERE nr_matricol=nr_matr;
IF SQL%ROWCOUNT = 0 THEN
raise_application_error (
-20001,
'There is no student with the number' || nr_matr
);
END IF;
END delete_stud;
END manager_faculty;
/
Aside from using SQL%ROWCOUNT as answered by MTO, you can also use SQL%NOTFOUND.
%NOTFOUND yields TRUE if an INSERT, UPDATE, or DELETE statement affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it yields FALSE.
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type)
IS
BEGIN
DELETE from student
WHERE nr_matricol=nr_matr;
IF SQL%NOTFOUND THEN
raise_application_error (
-20001,
'There is no student with the number' || nr_matr
);
END IF;
END delete_stud;
END manager_faculty;
You can read here, if you want to know other attributes of SQL Cursor.
Related
I'm really new to Oracle, I want to know how to continue to run my procedure if my trigger not detecting any errors.
I just want to continue to run my procedure if those two exception within trigger is not being triggered but when i run it shows me this error
ERROR at line 1:
ORA-01403: no data found
ORA-01403: no data found
ORA-06512: at "TEST.TRG_BOOKING_VALIDATION", line 9
ORA-04088: error during execution of trigger 'TEST.TRG_BOOKING_VALIDATION'
ORA-06512: at "TEST.PRC_ADD_BOOKING", line 44
ORA-06512: at line 1
PROCEDURE
create sequence bookingidvalue minvalue 1 start with 3031;
CREATE OR REPLACE PROCEDURE PRC_ADD_BOOKING(CUST_ID IN NUMBER,PAYMENT_ID IN NUMBER,FRM_DEST IN VARCHAR2,TO_DEST IN VARCHAR2)AS
v_journeystatus VARCHAR2(15) := 'Pending';
v_bookeddate Booking.bookingdate%TYPE;
no_null_on_custID EXCEPTION;
no_null_on_payID EXCEPTION;
no_null_on_FROM_DEST EXCEPTION;
no_null_on_TO_DEST EXCEPTION;
duplicate_error EXCEPTION;
BEGIN
IF CUST_ID < 0
THEN
RAISE no_null_on_custID;
END IF;
IF PAYMENT_ID < 0
THEN
RAISE no_null_on_payID;
END IF;
IF FRM_DEST IS NULL
THEN
RAISE no_null_on_FROM_DEST;
END IF;
IF TO_DEST IS NULL
THEN
RAISE no_null_on_TO_DEST;
END IF;
IF FRM_DEST = TO_DEST
THEN
RAISE duplicate_error;
END IF;
INSERT INTO Booking values(bookingidvalue.nextval,sysdate,v_journeystatus,FRM_DEST,TO_DEST,CUST_ID,PAYMENT_ID);
DBMS_OUTPUT.PUT_LINE('Booking has been added');
EXCEPTION
WHEN no_null_on_custID then
DBMS_OUTPUT.PUT_LINE('Invalid Customer ID');
WHEN no_null_on_payID then
DBMS_OUTPUT.PUT_LINE('Invalid Payment ID');
WHEN no_null_on_FROM_DEST then
DBMS_OUTPUT.PUT_LINE('From Destination must be filled');
WHEN no_null_on_TO_DEST then
DBMS_OUTPUT.PUT_LINE('To Destination must be filled');
WHEN duplicate_error then
DBMS_OUTPUT.PUT_LINE('From destination cannot same with To destination');
END;
/
TRIGGER
CREATE OR REPLACE trigger trg_booking_validation
before insert on booking
for each row
declare
v_journeystatus booking.journeystatus%type;
v_customerid booking.customerid%type;
v_paymentid booking.paymentid%type;
BEGIN
select bo.journeystatus into v_journeystatus
from booking bo
where bo.customerid = :new.customerid;
if SQL%FOUND then
case
when inserting then
if(v_journeystatus = 'In Journey')then
RAISE_APPLICATION_ERROR(-20950,'YOU ARE CURRENTLY IN JOURNEY, PLEASE BOOK AGAIN WHEN YOU REACHED');
end if;
if(v_journeystatus = 'Pending')then
RAISE_APPLICATION_ERROR(-20950,'YOUR PREVIOUS BOOKING IS ALREADY ON PENDING! DRIVER WILL SOON PICK YOU UP, BE PATIENCE!');
end if;
if(v_journeystatus = NULL)then
DBMS_OUTPUT.PUT_LINE('N0 errors');//i want to continue to my procedure here
end if;
end case;
end if;
END;
/
Catch the NO_DATA_FOUND exception in the trigger:
CREATE OR REPLACE trigger trg_booking_validation
before insert on booking
for each row
declare
v_journeystatus booking.journeystatus%type;
BEGIN
select bo.journeystatus
into v_journeystatus
from booking bo
where bo.customerid = :new.customerid;
if v_journeystatus = 'In Journey' then
RAISE_APPLICATION_ERROR(
-20950,
'YOU ARE CURRENTLY IN JOURNEY, PLEASE BOOK AGAIN WHEN YOU REACHED'
);
elsif v_journeystatus = 'Pending' then
RAISE_APPLICATION_ERROR(
-20950,
'YOUR PREVIOUS BOOKING IS ALREADY ON PENDING! DRIVER WILL SOON PICK YOU UP, BE PATIENCE!'
);
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
/
Note: you do not need to check if you are INSERTING as the trigger will only trigger during an INSERT.
However, I'm not sure that you should be using a SELECT statement and should not just be checking the :NEW.journeystatus bind variable if you are referring to the row you are INSERTing:
CREATE OR REPLACE trigger trg_booking_validation
before insert on booking
for each row
BEGIN
if :NEW.journeystatus = 'In Journey' then
RAISE_APPLICATION_ERROR(
-20950,
'YOU ARE CURRENTLY IN JOURNEY, PLEASE BOOK AGAIN WHEN YOU REACHED'
);
elsif :NEW.journeystatus = 'Pending' then
RAISE_APPLICATION_ERROR(
-20950,
'YOUR PREVIOUS BOOKING IS ALREADY ON PENDING! DRIVER WILL SOON PICK YOU UP, BE PATIENCE!'
);
end if;
END;
/
I am writing a procedure to delete department from a table. It takes depatment id as argument and delete the department with given id. but it is not working correctly.When i didnot use EXCEPTION, it only give output when gien department id is present in table but if the id is not present in table it throw error. When i use exception, It did not check the if else condition.
Here is my procedure
CREATE OR REPLACE PROCEDURE del_job(j_id number) IS
jj_id bb_department.iddepartment%type;
BEGIN
SELECT IDDEPARTMENT
INTO jj_id
FROM BB_DEPARTMENT
WHERE IDDEPARTMENT=j_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
jj_id := NULL;
IF (jj_id=j_id) THEN
DELETE FROM BB_DEPARTMENT
WHERE IDDEPARTMENT=j_id;
dbms_output.put_line ('Job Deleted');
ELSIF(jj_id=0) THEN
dbms_output.put_line ('No Job Deleted');
END IF;
END;
/
Your indentation seems to imply that you want your if statement to be part of the normal flow rather than part of the exception block. But your actual code has the if statement in the exception handler. Since you're assigning a null to jj_id in the exception handler before running the if statement and null is never equal to nor unequal to any value, neither your if nor your elsif clause can ever be true so neither dbms_output call will be made.
Assuming your indentation shows your actual intent, my guess is that you want a nested PL/SQL block for the select statement and exception handler.
CREATE OR REPLACE PROCEDURE del_job(j_id number) IS
jj_id bb_department.iddepartment%type;
BEGIN
BEGIN
SELECT IDDEPARTMENT
INTO jj_id
FROM BB_DEPARTMENT
WHERE IDDEPARTMENT=j_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
jj_id := NULL;
END;
IF (jj_id=j_id) THEN
DELETE FROM BB_DEPARTMENT
WHERE IDDEPARTMENT=j_id;
dbms_output.put_line ('Job Deleted');
ELSIF(jj_id=0) THEN
dbms_output.put_line ('No Job Deleted');
END IF;
END;
/
You are making things overly difficult. DELETE sets sql%rowcount to the number of rows processed. So there is no need to select the department; just delete the appropriate id. If you want a confirmation message then test sql%rowcount. If the row was deleted it will contain 1 (or greater), if the id did not exist it will contain 0. Print the appropriate message.
create or replace procedure del_job(j_id number) is
begin
delete
from bb_department
where iddepartment=j_id;
if sql%rowcount > 0 then
dbms_output.put_line ('Job Deleted');
else
dbms_output.put_line ('No Job Deleted');
end if;
end del_job;
/
if i have 3 insert statements in my plsql code.
lets assume them as insert_1, insert_2, insert_3.
my conditions be like : if insert_1 statement successfully executed then automatically insert_3 should be executed as well as if insert_3 executed successfully then insert_1 also should be executed automatically.
if both insert_1 and insert_3 fails then only insert_2 should be executed.
please write plsql code for this requirement.
You can create a package for this:
create a package and inside package body you try something like this.
create or replace PACKAGE BODY PKG_INSERT_QUERY AS
P_ERR_CODE number;
procedure finalPro
is
begin
P_ERR_CODE := 0;
insert into a values('a');
commit;
EXCEPTION WHEN OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE('ERROR ' ||SQLERRM);
P_ERR_CODE := 1;
if(P_ERR_CODE < 1 )then
secondQ;
IF(P_ERR_CODE < 1) THEN
thirdQ;
END IF;
END IF;
end;
procedure secondQ
as
begin
insert into B values('B');
commit;
EXCEPTION WHEN OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE('ERROR ' ||SQLERRM);
P_ERR_CODE := 2;
end;
procedure thirdQ
as
begin
insert into C values('C');
commit;
EXCEPTION WHEN OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE('ERROR ' ||SQLERRM);
P_ERR_CODE := 3;
end;
end;
I am creating a trigger for insert.If one of the value is the same as that in the old table. then I print a message. Here is my code.
Create or replace trigger TR_insert_act
After INSERT On ACTIVITIES
For each row
DECLARE
l_act varchar(30);
Begin
select Activity into l_act
From ACTIVITIES;
if(:new.Activity in l_act) then
DBMS_OUTPUT.PUT_LINE ('There is duplicate.');
end if;
end;
It is not compiled with the error on select of l_act, what to do please?
You need a BEFORE trigger, and a WHERE condition.
The DBMS_OUTPUT will not display the error though.
Create or replace trigger TR_insert_act
before INSERT On ACTIVITIES
For each row
l_act number;
Begin
select count(1) into l_act
From ACTIVITIES
WHERE ACTIVITY = :new.Activity
if(l_act > 0 ) then
RAISE_APPLICATION_ERROR (
num => -20000,
msg => 'There is Duplicate');
end if;
end;
I have a set of table names, let say 150. Each table have mail_id column, now I want to search one mail_id in all of the table. For that I wrote one Plsql block. When I loop through the set of table some tables do not exists so it raises an exception. I have exception handling block to handle that exception. Now I want to loop entire table even though it raise an exception? Any idea? Actually my block didn't handle that particular exception!
declare
my_mail_id varchar2(50):='xyaksj#jsm.com';
tmp_table varchar2(125);
type varchar_collector is table of varchar2(255);
var varchar_collector;
table_does_not_exist exception;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -00942);
begin
for cntr in (select table_name from user_tables)
loop
tmp_table:=cntr.table_name;
dbms_output.put_line(tmp_table);
for mail in (select email_address from tmp_table where lower(email_address) like '%my_mail_id%' )
loop
dbms_output.put_line(tmp_table);
end loop;
end loop;
exception
when no_data_found then
dbms_output.put_line('email address not found');
WHEN table_does_not_exist then
dbms_output.put_line('table dose not exists');
WHEN OTHERS THEN
--raise_application_error(-20101, 'Expecting at least 1000 tables');
IF (SQLCODE = -942) THEN
--DBMS_Output.Put_Line (SQLERRM);
DBMS_Output.Put_Line ('in exception');--this exception not handled
ELSE
RAISE;
END IF;
end;
Just handle your exceptions in anonymous block inside the loop.
DECLARE
my_mail_id VARCHAR2(50) := 'xyaksj#jsm.com';
tmp_table VARCHAR2(125);
TYPE varchar_collector IS TABLE OF VARCHAR2(255);
var varchar_collector;
table_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -00942);
BEGIN
FOR cntr IN (SELECT table_name FROM user_tables)
LOOP
BEGIN
tmp_table := cntr.table_name;
dbms_output.put_line(tmp_table);
FOR mail IN (SELECT email_address
FROM tmp_table
WHERE lower(email_address) LIKE '%my_mail_id%')
LOOP
dbms_output.put_line(tmp_table);
END LOOP;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('email address not found');
WHEN table_does_not_exist THEN
dbms_output.put_line('table dose not exists');
WHEN OTHERS THEN
--raise_application_error(-20101, 'Expecting at least 1000 tables');
IF (SQLCODE = -942)
THEN
--DBMS_Output.Put_Line (SQLERRM);
DBMS_Output.Put_Line('in exception'); --this exception not handled
ELSE
RAISE;
END IF;
END;
END LOOP;
END;
If you're selecting from user_tables and finding that some of them do not exist then you're probably trying to query tables that are in the recycle bin (their names begin BIN$).
If so, change your query to:
select table_name
from user_tables
where dropped = 'NO';
You should replace your second cursor with a call to execute immediate also, constructing the query by concatenating in the table_name not just using a variable as the table name, and you might as well construct the query as:
select count(*)
from table_name
where lower(email_address) like '%my_mail_id%'
and rownum = 1;
That way you'll retrieve a single record that is either 0 or 1 to indicate whether the email address was found, and no need for error handling.
try below code...
DECLARE
foo BOOLEAN;
BEGIN
FOR i IN 1..10 LOOP
IF foo THEN
GOTO end_loop;
END IF;
<<end_loop>> -- not allowed unless an executable statement follows
NULL; -- add NULL statement to avoid error
END LOOP; -- raises an error without the previous NULL
END;