SQL exceptions don't appear to be working [duplicate] - oracle

This question already has an answer here:
delete statement not deleting records
(1 answer)
Closed 5 years ago.
Anyone know why my exceptions aren't working? When i test the sql the only exception that appears is the when others.
This is my first stored procedure, i want it to insert new students using parameter values.
create or replace PROCEDURE ADD_STUDENT_TO_DB (pSTUid number, pSTUname varchar2) AS
Out_Of_Range Exception;
BEGIN
IF pSTUid <=1 AND pSTUid >=499 THEN
RAISE Out_Of_Range;
END IF;
INSERT INTO STUDENT (STUid, STUname)
VALUES (pSTUid, pSTUname);
EXCEPTION
WHEN DUP_VAL_ON_iNDEX THEN
dbms_output.put_line('-20010. Duplicate student ID');
WHEN Out_Of_Range THEN
dbms_output.put_line('-20002. student ID out of range');
WHEN OTHERS THEN
dbms_output.put_line('-20000. Error');
END;
This is my second stored procedure, i want this to call my first sp.
create or replace PROCEDURE ADD_STUDENT_VIASQLDEV (pSTUid number, pSTUname varchar2) AS
BEGIN
INSERT INTO STUDENT (STUid, STUname)
VALUES (pSTUid, pSTUname);
dbms_output.put_line('--------------------------------------------');
dbms_output.put_line('Adding student ID: ' || pSTUid || ' Name: ' || pSTUname);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('-20000. Error');
END;

there should exist IF pSTUid <=1 OR pSTUid >=499 THEN instead of your statement for out_of_range

Related

Display stored procedure in an anonymous block without getting too many rows error

I have a created stored procedure that has one in parameter and two out parameters.
I want to display the stored procedure in an anonymous PL/SQL block.
The code
CREATE OR REPLACE PROCEDURE task_one
(coun_id IN countries.country_id%TYPE,
coun_name OUT countries.country_name%TYPE,
reg_name OUT regions.region_name%TYPE) IS
BEGIN
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Error! No data found!');
END;
Here you can see my table
When I try to execute the procedure in an anonymous block, I get an error which is too many rows.
In order to block the error, I thought that I can use for loop. However, It didn't work as well. Maybe the way I tried is not right at all.
Here's the anonymous block that tries to display stored procedure
DECLARE
c_name countries.country_name%TYPE;
r_name regions.region_name%TYPE;
BEGIN
FOR c IN (SELECT country_name, region_name INTO c_name, r_name FROM Countries, Regions) LOOP
(task_one('CA', c_name, r_name)
DBMS_OUTPUT.PUT_LINE(c.c_name || ' ' || c.r_name);
END LOOP;
END;
The code of your procedure is incomplete or you did not post everything.
The procedure could look like this:
CREATE OR REPLACE PROCEDURE task_one
(coun_id IN countries.country_id%TYPE,
coun_name OUT countries.country_name%TYPE,
reg_name OUT regions.region_name%TYPE) IS
BEGIN
SELECT country_name, region_name
INTO coun_name, reg_name
FROM countries
JOIN regions ON Countries.region_id = Regions.region_id
WHERE country_id = coun_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Error! No data found!');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Error! Too many rows!');
coun_name := NULL;
reg_name := NULL;
END;
/
You have to join the two tables via the region_id.
If you also want to get the error "Too many rows", because you might get back several entries for one Country_id (error in the data?), you can do it like in the example.
You can then use the procedure in the anonymous block as follows:
DECLARE
c_name countries.country_name%TYPE;
r_name regions.region_name%TYPE;
BEGIN
task_one('CA', c_name, r_name);
DBMS_OUTPUT.PUT_LINE(c_name || ' ' || r_name);
END;
/

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;
/

Exception error when creating procedure oracle sql developer

i have been whacking my brain for the past 2 hours can't find a solution to this error. I am creating a simple procedure to find an employee. PL/SQL keeps giving me error. What is the problem ? what am i doing wrong here ?
This is my Procedure:
create or replace PROCEDURE find_employee (employeeNo IN number) as
INVALID_ID exception;
TOO_MANY_ROWS exception;
res number;
BEGIN
dbms_output.enable;
Select count(*) into res from employee where ID=employeeNo;
if (res>1)then -- Checking that the total count of the employee is 1 or not
raise TOO_MANY_ROWS; -- if greater then 1 then it raise TOO_MANY_ROWS error
ELSE IF (NOT EXISTS (Select ID from employee where ID=employeeNo)) -- Checking that the employeeNo user passes exist or not
then
raise INVALID_ID; -- if employeeNo doesnot exit then display invalid id message
ELSE
Select* from Employee where ID=employeeNo; -- else return employee info whose id==employeeNo
END IF;
EXCEPTION
when TOO_MANY_ROWS then
DBMS_OUTPUT.PUT_LINE ('Too many Rows with same employee id');
when INVALID_ID then
DBMS_OUTPUT.PUT_LINE ('Invalid employee id');
END find_employee;
And error is this:
Error(15,1): PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following: ( begin case declare end exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
Error(20,18): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: end not pragma final instantiable order overriding static member constructor map
Please God Help me :'(
You're missing END IF (line #16). it is easier to spot it if you write formatted code (nested IF should have been indented).
SQL> create or replace PROCEDURE find_employee (employeeNo IN number) as
2 INVALID_ID exception;
3 TOO_MANY_ROWS exception;
4 res number;
5 BEGIN
6 dbms_output.enable;
7 Select count(*) into res from employee where ID=employeeNo;
8 if (res>1)then -- Checking that the total count of the employee is 1 or not
9 raise TOO_MANY_ROWS; -- if greater then 1 then it raise TOO_MANY_ROWS error
10 ELSE IF (NOT EXISTS (Select ID from employee where ID=employeeNo)) -- Checking that the employeeNo user passes exist or not
11 then
12 raise INVALID_ID; -- if employeeNo doesnot exit then display invalid id message
13 ELSE
14 Select* from Employee where ID=employeeNo; -- else return employee info whose id==employeeNo
15 END IF;
16 END IF; --> this is missing
17 EXCEPTION
18 when TOO_MANY_ROWS then
19 DBMS_OUTPUT.PUT_LINE ('Too many Rows with same employee id');
20 when INVALID_ID then
21 DBMS_OUTPUT.PUT_LINE ('Invalid employee id');
22 END find_employee;
As #Dornaut commented, that code probably isn't the best one could produce. Here's another option; see if it helps.
CREATE OR REPLACE PROCEDURE find_employee (employeeNo IN NUMBER)
AS
res NUMBER;
e_row employee%ROWTYPE;
BEGIN
SELECT *
INTO e_row
FROM employee
WHERE id = employeeNo;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('Invalid employee ID');
WHEN TOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line ('Too many rows with same employee ID');
END find_employee;
So: if SELECT returns NO_DATA_FOUND or TOO_MANY_ROWS, it'll be handled. Otherwise, it'll fetch the whole row into a variable.

ORACLE PL/SQL: Calling stored procedure function with multiple parameters (DML query)

New PL/SQL person here. I have a (successfully compiled) PL/SQL function block that manipulates a table in my database by adding a new term to it:
create or replace FUNCTION add_new_term
(TERM_ID_IN IN NUMBER, TERM_IN IN VARCHAR2, IS_METATERM_IN IN NUMBER)
RETURN VARCHAR2
IS
add_term CV_TERMS.TERM_NAME%TYPE; --TERM_NAME is VARCHAR2 type
BEGIN
INSERT INTO CV_TERMS (TERM_ID, TERM_NAME, IS_METATERM)
VALUES (TERM_ID_IN, TERM_IN, IS_METATERM_IN);
dbms_output.put_line('New term successfully added to CV_TERMS table: ' || TERM_IN);
RETURN add_term;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
raise_application_error (-20001, 'You have tried to insert a duplicate term.');
WHEN OTHERS THEN
raise_application_error (-20002, 'An error has occurred inserting a term - '|| SQLCODE ||' -ERROR- '|| SQLERRM);
END add_new_term;
I call this function like calling a stored procedure:
DECLARE
add_term_success cv_terms.term_name%type;
BEGIN
add_term_success := add_new_term(cv_terms_pk.NEXTVAL, 'TESTTT', 0);
END;
SQLDeveloper tells me the procedure was successfully completed, however, the term has not been added to the table. I created the sequence cv_terms_pk independently (it's not in the table CV_TERMS' SQL). Does it need to be there? Am I passing it improperly? Or is something wrong with my add_term declaration? Ideas?
After the DML INSERT you have to commit the transaction.
create or replace FUNCTION add_new_term
(TERM_ID_IN IN NUMBER, TERM_IN IN VARCHAR2, IS_METATERM_IN IN NUMBER)
RETURN VARCHAR2 IS
add_term CV_TERMS.TERM_NAME%TYPE; --TERM_NAME is VARCHAR2 type
BEGIN
INSERT INTO CV_TERMS(TERM_ID, TERM_NAME, IS_METATERM
VALUES (TERM_ID_IN, TERM_IN, IS_METATERM_IN);
COMMIT; ---LINE ADDED ...

Sqlplus using stored procedures to update a row

This is what I have so far. When I enter valid data and run it the table updates correctly. When I run it using author numbers that I know don't exist in the table it still runs, and doesn't output the exception statements. Does anyone know why my exceptions don't seem to be working. Any help would be appreciated thanks!
CREATE OR REPLACE PROCEDURE update_authorname
(selected_author_num IN NUMBER,
new_author_first IN CHAR,
new_author_last IN CHAR) AS
BEGIN
UPDATE author
SET author_first = new_author_first, author_last = new_author_last
WHERE author_num = selected_author_num;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.PUT_LINE('No author with this number exists: ' || selected_author_num);
WHEN ROWTYPE_MISMATCH
THEN
DBMS_OUTPUT.PUT_LINE('Error: There was a row type mismatch when updating');
END;
/
This is what I used to call the procedure:
BEGIN
update_authorname(6,'Emma','White');
END;
/
An update statement doesn't throw an exception when the where clause isn't matched, it just fails silently. Instead, you need to check either:
The row exists before trying to update or
The update changed something.
1. The row exists
CREATE OR REPLACE PROCEDURE update_authorname
(selected_author_num IN NUMBER,
new_author_first IN CHAR,
new_author_last IN CHAR) AS
BEGIN
IF NOT EXISTS (SELECT 1 FROM author WHERE author_num = selected_author_num;
DBMS_OUTPUT.PUT_LINE('No author with this number exists: ' || selected_author_num);
ELSE
UPDATE author
SET author_first = new_author_first, author_last = new_author_last
WHERE author_num = selected_author_num;
EXCEPTION
WHEN ROWTYPE_MISMATCH
THEN
DBMS_OUTPUT.PUT_LINE('Error: There was a row type mismatch when updating');
END;
/
2. The update made changes
CREATE OR REPLACE PROCEDURE update_authorname
(selected_author_num IN NUMBER,
new_author_first IN CHAR,
new_author_last IN CHAR) AS
BEGIN
UPDATE author
SET author_first = new_author_first, author_last = new_author_last
WHERE author_num = selected_author_num;
IF ##ROWCOUNT <= 0
DBMS_OUTPUT.PUT_LINE('No author with this number exists: ' || selected_author_num);
EXCEPTION
WHEN ROWTYPE_MISMATCH
THEN
DBMS_OUTPUT.PUT_LINE('Error: There was a row type mismatch when updating');
END;
/
There are certainly other ways to achieve the same result, but these are the two most common.

Resources