PL/SQL INSERT Ignored statement - oracle

What I have to do is to INSERT in table "info" different content, depending on the select result: if it is one row, no rows or more than one row.
I want to set the outretvalue variable on the exception section, then do the insert in the IF section, depending on outretvalue value.
Anyway, I get an error at compiling saying that f2 function is in an invalid state. I have 2 errors: for the INSERT and for not recognising rowcount. Why?
CREATE OR REPLACE FUNCTION f2 (v_nume employees.last_name%TYPE DEFAULT 'Bell')
RETURN NUMBER
IS
salariu employees.salary%type;
outretvalue number(2) := 0;
BEGIN
SELECT salary
INTO salariu
FROM employees
WHERE last_name = v_nume;
RETURN salariu;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := 1;
WHEN TOO_MANY_ROWS THEN
--at this row I have 2 errors: for the INSERT and for not recognising rowcount
INSERT INTO info(`no_lines`) VALUES(SQL%ROWCOUNT);
END f2;
/
SELECT f2('King') FROM dual;

Your function:
DECLARE
BEGIN
END;
... something
END;
Add another BEGIN at begin or move your IF inside existing BEGIN END block and remove second END.
EDIT: after clarification
CREATE OR REPLACE FUNCTION f2 (v_nume employees.last_name%TYPE DEFAULT 'Bell')
RETURN NUMBER
IS
salariu employees.salary%type;
outretvalue number(2) := 0;
BEGIN
SELECT salary
INTO salariu
FROM employees
WHERE last_name = v_nume;
RETURN salariu;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN -1;
WHEN TOO_MANY_ROWS THEN
SELECT count(*)
INTO salariu
FROM employees
WHERE last_name = v_nume;
INSERT INTO info(no_lines) VALUES(salariu);
RETURN -2;
WHEN OTHERS THEN
RETURN -3;
END f2;
/
SET SERVEROUTPUT on
DECLARE
l_ret NUMBER;
BEGIN
dbms_output.put_line(f2('Bell'));
dbms_output.put_line(f2('noBell'));
dbms_output.put_line(f2('King'));
END;

Try this. It will definelty help you out.
CREATE OR REPLACE FUNCTION f2(
v_nume employees.last_name%TYPE DEFAULT 'Bell')
RETURN NUMBER
IS
salariu employees.salary%type;
outretvalue NUMBER(2) := 0;
lv_cnt PLS_INTEGER;
BEGIN
SELECT salary INTO salariu FROM employees WHERE last_name = v_nume;
RETURN salariu;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := 1;
WHEN TOO_MANY_ROWS THEN
SELECT COUNT(1) INTO lv_cnt FROM employees WHERE last_name = v_nume;
INSERT INTO info
( no_lines
) VALUES
( lv_cnt
);
RETURN 2;
WHEN OTHERS THEN
RETURN 3;
END f2;

Oracle saves the compile errors in a table. I use the following query for retrieving the PL/SQL errors in my stored procs/funcs:
SELECT '*** ERROR in ' || TYPE || ' "' || NAME || '", line ' || LINE || ', position ' || POSITION || ': ' || TEXT
FROM SYS.USER_ERRORS
You could try running it and see if it helps identify the error in the function.

Related

ORA-01007: variable not in select list while fetch c2 into cursor2

I have oracle pl/sql procedure with below:
TYPE Paycomp2 IS RECORD(
Row_Id VARCHAR2(15),
Created DATE,
Created_By VARCHAR2(15),
Last_Upd DATE,
Last_Upd_By VARCHAR2(15),
Modification_Num NUMBER(10),
Conflict_Id VARCHAR2(15),
Comp_Price NUMBER(10),
Access_Level VARCHAR2(30),
Comp_Name VARCHAR2(30),
Depends_On VARCHAR2(30),
Gold_Cat VARCHAR2(30),
Order_Type VARCHAR2(30),
Parent_Id VARCHAR2(15),
Price_Plan VARCHAR2(30),
TYPE VARCHAR2(30),
Check_Flag VARCHAR2(1),
PREPAID_INIT_PRICE number(10),
DB_LAST_UPD date,
DB_LAST_UPD_SRC varchar2(50),
Unit_Type varchar2(30),
M2M_CATEGORY varchar2(30));
TYPE Paycomp IS REF CURSOR;
C2 Paycomp;
Cursor2 Paycomp2;
when I do the below operation
FETCH C2 INTO Cursor2;
I am getting this error :
ORA-01007: variable not in select list error.
This piece of script has worked previously.
How to resolve this issue?
script
Vordertype := 'Migration Prepaid - Postpaid';
Curcomp_Sql := Curcomp_Sql || Vordertype || '''' || ' union all ' || '' || Curcomp2sql || '' ||
Vordertype || '''';
OPEN C2 FOR Curcomp_Sql;
Sadmin.Pkg_Spliter.Prcsplitchar(Ppaycompstr, ';', Arrcomplist);
Vtotalcompprc := 0;
Arrcount := Arrcomplist.Count;
BEGIN
Dbms_output.put_line('reached17');
LOOP
FETCH C2
INTO Cursor2;
Dbms_output.put_line('reached18');
EXIT WHEN C2%NOTFOUND;
-- Processing each entry from Array
Compfndflg := 0;
dbms_output.put_line('arrCount 0: reached');
FOR Counter IN 1 .. Arrcount
LOOP
Vstrcommand := Arrcomplist(Counter);
dbms_output.put_line('arrCount : reached');
Sadmin.Pkg_Spliter.Prcsplitchar(Vstrcommand, '?', Arrdisclist);
IF Arrdisclist.Count <> 0 THEN
dbms_output.put_line('arrCount : reached1');
-- Extracting the ? seperated values and putting them into variables
Vcompname := Arrdisclist(1);
--dbms_output.put_line(CURSOR2.comp_name||':- count -'||COUNTER||'--'||VCOMPNAME);
BEGIN
-- Added by Accenture
IF Vcompname IS NOT NULL THEN
--dbms_output.put_line(CURSOR2.comp_name||':- count -'||COUNTER||'--'||ARRDISCLIST(1)||'-'||ARRDISCLIST(2)||'-'||ARRDISCLIST(3));
SELECT COUNT(0)
INTO v_Count_Exist
FROM Siebel.Cx_Paycomp_Mtx a, Siebel.Cx_Paycomp_Mtx b
WHERE a.Row_Id = b.Parent_Id
AND a.Order_Type = Vordertype
AND b.Type = 'Payment Component'
AND b.Comp_Name = Vcompname;
IF (v_Count_Exist = 0) THEN
Err_Msg := 'Invalid Payment Component in String';
Result_Out := '74';
Errflg := 1;
--dbms_output.put_line('Counter 2' || counter);
--dbms_transaction.rollback;
RAISE Error_Out;
END IF;
END IF;
--dbms_output.put_line('Counter 3' || CURSOR2.comp_name);
IF Vcompname = Cursor2.Comp_Name
--and VCOMPNAME != '3'
THEN
Compfndflg := 1;
EXIT;
END IF;
END;
END IF;
END LOOP;
---DBMS_OUTPUT.PUT_LINE('VCOMPNAME, COMPFNDFLG'||VCOMPNAME||','||COMPFNDFLG);
--dbms_output.put_line('CURSOR2.comp_name :'||CURSOR2.comp_name||' - COMPFNDFLG :'||COMPFNDFLG);
IF Compfndflg != 1 THEN
IF Temp_Comp_String IS NULL THEN
Temp_Comp_String := Cursor2.Comp_Name || '?0?;';
---DBMS_OUTPUT.PUT_LINE('STRING 1'||TEMP_COMP_STRING);
ELSE
Temp_Comp_String := Temp_Comp_String || Cursor2.Comp_Name || '?0?;';
---DBMS_OUTPUT.PUT_LINE('STRING 2'||TEMP_COMP_STRING);
END IF;
--- END IF;
ELSE
IF Temp_Comp_String IS NULL THEN
Temp_Comp_String := Arrdisclist(1) || '?' || Arrdisclist(2) || '?' ||
Arrdisclist(3) || ';';
---DBMS_OUTPUT.PUT_LINE('STRING 3'||TEMP_COMP_STRING);
ELSE
Temp_Comp_String := Temp_Comp_String || Arrdisclist(1) || '?' || Arrdisclist(2) || '?' ||
Arrdisclist(3) || ';';
---DBMS_OUTPUT.PUT_LINE('STRING 4'||TEMP_COMP_STRING);
END IF;
-- end if;
--- END IF;
END IF;
END LOOP;
END;
Curcomp_Sql VARCHAR2(2000) := 'SELECT mtx2.*
FROM siebel.CX_PAYCOMP_MTX mtx1, siebel.CX_PAYCOMP_MTX mtx2
WHERE mtx2.parent_id = mtx1.row_id
AND mtx2.comp_name <> ''Security Deposit''
AND mtx2.TYPE = ''Payment Component''
AND mtx1.order_type = ''';
Curcomp2sql VARCHAR2(2000) := 'SELECT mtx2.*
FROM siebel.CX_PAYCOMP_MTX mtx1, siebel.CX_PAYCOMP_MTX mtx2
WHERE mtx2.parent_id = mtx1.row_id
AND mtx2.comp_name = ''Security Deposit''
AND mtx2.TYPE = ''Payment Component''
AND mtx2.depends_on = ''ACCESS LEVEL''
AND mtx1.order_type = ''';
A simplified version of what you're seeing, with a dummy table and simple anonymous block:
create table t42 (id number, some_value varchar2(10));
declare
type t_rec is record(id number, some_value varchar2(10));
l_rec t_rec;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
close l_cur;
end;
/
PL/SQL procedure successfully completed.
To get the error you're seeing I just need to remove one of the table columns:
alter table t42 drop column some_value;
and run exactly the same code again:
declare
type t_rec is record(id number, some_value varchar2(10));
l_rec t_rec;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
close l_cur;
end;
/
ORA-01007: variable not in select list
ORA-06512: at line 10
The field list in the record type declared in the PL/SQL block no longer matches the column type in the cursor query. The record variable you're fetching into expects two columns (in my version; 22 in yours), but the query only gets one value.
You can (some would say should) specify all the columns you're selecting explicitly, but assuming you're actually referring to them all later you would then have done the equivalent of:
open l_cur for 'select id, some_value from t42';
which would still have errored after the column removal, though a bit more helpfully perhaps:
ORA-00904: "SOME_VALUE": invalid identifier
ORA-06512: at line 9
Since you're currently intending to get all columns from a single table, you could also have used the %rowtype syntax instead of your own record type:
declare
l_rec t42%rowtype;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
close l_cur;
end;
/
which with this trivial example runs successfully. You'll still have a problem though as soon as you refer to the removed column, assuming it's still part of the record:
declare
l_rec t42%rowtype;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
dbms_output.put_line(l_rec.some_value);
close l_cur;
end;
/
ORA-06550: line 7, column 30:
PLS-00302: component 'SOME_VALUE' must be declared
ORA-06550: line 7, column 3:
PL/SQL: Statement ignored
(Using %rowtype would give you some breathing space if a column was added, as it would just be ignored, unless and until you added code to refer to that record field. But with your code you'd get ORA-00932 inconsistent data types, rather than ORA-01007, so that doesn't seem to be what's happening here.)
If you aren't referring to the removed column/field anywhere then you shouldn't be selecting it anyway. Change the record type to only include the fields you actually need, and only get the corresponding columns in the cursor query.
If you are referring to the removed column/field then you're stuck anyway - you'll have find out what was removed and why, and then either fix your code to not refer to it (if that makes sense), or get that change reverted.

Function Returning Multiple Values SQL

I have been trying to return 2 values from a function in PL/SQL . The first value i want it to be the salary of the guy i have to search for. The second i want it to be the number of rows affected by this. I searched google for a while and i found out that i must first make a type so that i can return the data. However i get an error :
Error(9,1): PL/SQL: SQL Statement ignored
Error(9,36): PL/SQL: ORA-00936: missing expression
The code that i have is :
CREATE OR REPLACE TYPE return_type AS OBJECT(val1 NUMBER,val2 NUMBER);
CREATE OR REPLACE FUNCTION f2
(v_nume employees.last_name%TYPE DEFAULT 'Bell')
RETURN return_type IS
out_var return_type;
salariu employees.salary%type;
BEGIN
SELECT salary INTO salariu
FROM employees
WHERE last_name = v_nume;
INSERT INTO out_var values(salariu,##ROWCOUNT);
RETURN out_var;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20000, 'Nu exista angajati cu numele dat');
WHEN TOO_MANY_ROWS THEN
RAISE_APPLICATION_ERROR(-20001, 'Exista mai multi angajati cu numele dat');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20002,'Alta eroare!');
END f2;
/
I did it this way:
CREATE OR REPLACE FUNCTION f2
(v_nume employees.last_name%TYPE DEFAULT 'Bell',
nr OUT employees.salary%TYPE )
RETURN NUMBER IS
salariu employees.salary%type;
BEGIN
SELECT salary INTO salariu
FROM employees
WHERE last_name = v_nume;
nr := SQL%ROWCOUNT;
RETURN salariu;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20000,
'Nu exista angajati cu numele dat');
WHEN TOO_MANY_ROWS THEN
RAISE_APPLICATION_ERROR(-20001,
'Exista mai multi angajati cu numele dat');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20002,'Alta eroare!');
END f2;
/

PL/SQL Execute immediate exception handling inside for loop

In the below PL/SQL code, TABLE_ONE holds table name tname , column name cname and rowid rid. The For loop fetches records from TABLE_ONE and updates column cname in table tname for the record with row id rid. But if the record to be updated in tname is locked then the for loop gets stuck and no further records from TABLE_ONE are processed. Ideally, the script to ignore the records for which update failed and proceed further. Please advise what could be the issue.
BEGIN
FOR c IN (SELECT * FROM TABLE_ONE a )
LOOP
DECLARE
TNAME varchar2(30);
CNAME varchar2(30);
RID ROWID;
X number;
updt_stmt varchar2(300);
BEGIN
BEGIN
TNAME := c.TNAME;
CNAME := c.CNAME;
RID := c.RID;
DBMS_OUTPUT.PUT_LINE( TNAME || '=>' || CNAME);
updt_stmt := 'UPDATE ' || TNAME || ' SET ' || CNAME || ' = ''123'' WHERE ROWID like ''%' || RID || '%''';
EXECUTE IMMEDIATE updt_stmt;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR');
END;
END;
END LOOP;
END;
Untested, but I think you could first try to lock the record with FOR UPDATE and by specifying NOWAIT cause a failure if some other transaction was active. You could then catch this exception and skip processing. Here is an untested example:
DECLARE
x ROWID;
resource_busy EXCEPTION;
PRAGMA EXCEPTION_INIT(resource_busy,
-00054);
BEGIN
FOR c IN (SELECT *
FROM table_one a)
LOOP
DECLARE
tname VARCHAR2(30);
cname VARCHAR2(30);
rid ROWID;
x NUMBER;
updt_stmt VARCHAR2(300);
BEGIN
BEGIN
tname := c.tname;
cname := c.cname;
rid := c.rid;
dbms_output.put_line(tname || '=>' || cname);
BEGIN
EXECUTE IMMEDIATE 'SELECT rowid FROM ' || tname ||
' WHERE rowid = :x FOR UPDATE NOWAIT'
INTO x
USING rid;
EXCEPTION
WHEN resource_busy THEN
dbms_output.put_line('Record locked; try again later.');
CONTINUE;
END;
updt_stmt := 'UPDATE ' || tname || ' SET ' || cname ||
' = ''123'' WHERE ROWID like ''%' || rid || '%''';
EXECUTE IMMEDIATE updt_stmt;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('ERROR');
END;
END;
END LOOP;
END;

Is it possible to use sql%rowcount for SELECT?

The code below may return more than one row. Will sql%rowcount return the number of rows fetched?
select * from emp where empname = 'Justin' and dept='IT'
if sql%rowcount>0
...
This is my sample proc; am I using sql%rowcount in correct way?
CREATE PROCEDURE Procn(in_Hid IN VARCHAR2,outInststatus OUT VARCHAR2,outSockid IN NUMBER,outport OUT VARCHAR2,outIP OUT VARCHAR2,outretvalue OUT NUMBER)
AS
BEGIN
select INST_STATUS into outInststatus from TINST_child where INST_ID = in_Hid and INST_STATUS = 'Y';
if outInststatus = 'Y' then
select PORT_NUMBER,STATIC_IP into outport,outIP from TINST where INST_ID = in_Hid and IP_PORT_STATUS = 'Y';
if sql%rowcount >= 1 then
select SOCK_ID into outSockid from TINST where PORT_NUMBER = outport AND STATIC_IP = outIP;
outretvalue := 0;
else
outretvalue := -12;
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -13;
end if;
END;
Yes, you can use SQL%ROWCOUNT. It's valid in PL/SQL.
However, in PL/SQL the result of your query needs to go somewhere e.g. into a PL/SQL table. PL/SQL will never send the result to the output (terminal, window etc.). So SELECT * FROM won't work.
Your code could look like this:
DECLARE
TYPE emp_t ...;
emp_tab emp_t;
BEGIN
SELECT *
BULK COLLECT INTO emp_tab
FROM emp
WHERE empname = 'Justin' AND dept='IT';
IF sql%rowcount > 0 THEN
.. do something ...
END IF;
END;
/
Update:
The updated questions suggests that you're looking for something else.
Option 1: Use exceptions
If there are 0 rows or more than 1 row, these cases are handled separately (as errors):
BEGIN
select PORT_NUMBER,STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y';
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
RETURN;
WHEN TOO_MANY_ROWS THEN
outretvalue := -13;
RETURN;
END;
Option 2: Use aggregations
Using aggregations, the query will always return exactly one row. If now source row matched the WHERE clause, then both result values will be NULL. If there WHERE clause matched more than one row, the maximum will be taken.
Note that this query might return a port number and an IP address that originally were not on the same row.
select MAX(PORT_NUMBER), MAX(STATIC_IP) into outport, outIP
from TINST
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y';
IF outport IS NULL OR outIP IS NULL THEN
outretvalue := -12;
RETURN;
END IF;
Option 3: Use ROWNUM
This query returns at most one row. If no row matched the WHERE clause, an exception is thrown and needs to be handled:
BEGIN
select PORT_NUMBER, STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y'
AND ROWNUM = 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
RETURN;
END;
Based on your comment
If 2nd 'select' query returns more than one row i want to take the first one and process with it
... this ought to work, but perhaps not quite as you expect, as you haven't defined what the 'first one' means.
CREATE PROCEDURE Procn(in_Hid IN VARCHAR2, outInststatus OUT VARCHAR2,
outSockid IN NUMBER, outport OUT VARCHAR2, outIP OUT VARCHAR2,
outretvalue OUT NUMBER)
AS
BEGIN
select INST_STATUS into outInststatus
from TINST_child
where INST_ID = in_Hid and INST_STATUS = 'Y';
-- no need to check if outInstatus is Y, that's all it can be here
-- restricting with `rownum` means you'll get at most one row, so you will
-- not get too_many_rows. But it will be an arbitrary row - you have no
-- criteria to determine which of the multiple rows you want. And you can
-- still get no_data_found which will go to the same exception and set -12
select PORT_NUMBER, STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid and IP_PORT_STATUS = 'Y'
and rownum < 2;
-- no need to check sql%rowcount; it can only be 1 here
-- not clear if this can return multiple rows too, and what should happen
-- if it can; could use rownum restriction but with the same caveats
select SOCK_ID into outSockid
from TINST
where PORT_NUMBER = outport AND STATIC_IP = outIP;
outretvalue := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
END;
The exception handler applies to the whole block. If any of the select statements find no rows, the no_data_found exception will be handled by that block and will set outretvalue to -12.
If you want a different outretvalue for each select then you can wrap them in sub-blocks, each with their own exception handling section:
CREATE PROCEDURE Procn(in_Hid IN VARCHAR2, outInststatus OUT VARCHAR2,
outSockid IN NUMBER, outport OUT VARCHAR2, outIP OUT VARCHAR2,
outretvalue OUT NUMBER)
AS
BEGIN
BEGIN
select INST_STATUS into outInststatus
from TINST_child
where INST_ID = in_Hid and INST_STATUS = 'Y';
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
END;
BEGIN
select PORT_NUMBER, STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid and IP_PORT_STATUS = 'Y'
and rownum < 2;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -13;
END;
BEGIN
select SOCK_ID into outSockid
from TINST
where PORT_NUMBER = outport AND STATIC_IP = outIP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -14;
END;
outretvalue := 0;
END;
You only need to do that if the caller needs to know which select failed, and if you never really expect any of them to fail then it's probably more common not to catch the exception at all and let the caller see the raw no_data_found and decide what to do. Depends what the exception condition means to you and your application though.

How to find out if this SELECT query executed successfully?

CREATE PROCEDURE Pname(in_empno IN NUMBER out_name OUT VARCHAR2)
AS
BEGIN
select EmpName into out_name from emptable where Empno = in_empno;
END Pname;
In the above procedure, how can I check if the SELECT query executed successfully or not with the given condition?
You can use the EXCEPTION block to determine if rows were returned or if some other exceptions occurred. Try this
BEGIN
SELECT EmpName into out_name from emptable where Empno = in_empno
EXCEPTION
WHEN NO_DATA_FOUND THEN
out_name := NULL;
END;
If you would like to see the output of out_name parameter try as follows
CREATE OR REPLACE PROCEDURE pname (in_empno IN NUMBER, out_name OUT VARCHAR2)
IS
BEGIN
SELECT empName
INTO out_name
FROM emptable
WHERE empno = in_empno;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
raise_application_error (
-20000,
'Unable to execute procedure because of: ' || SQLERRM
);
END pname;
This procedure can be executed from sql plus as
var ret varchar2(512);
exec pname(2345,:ret);
print ret;
Update 1
If you would like to return a value if sql query executes successfully and if there is an error return another value then do as
CREATE OR REPLACE PROCEDURE pname (in_empno IN VARCHAR2,
out_name OUT VARCHAR2,
returnval IN OUT NUMBER
)
IS
BEGIN
SELECT employee_name
INTO out_name
FROM employees
WHERE emp_number = in_empno;
returnval := 0;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
returnval := 1;
END pname;
and call the procedure from sql plus as
var ret varchar2(512);
var ret2 number;
exec pname(2346,:ret,:ret2);
print ret;
print ret2;
In this example i can stop using one more out variable for return right? and ill check for the condition in my front end like if 'out_name' returns null ill handle in someway, if it returns value it'll be handled in other way, Which one is efficient?????Using one more out variable for Retvalue, or doing like this
CREATE OR REPLACE PROCEDURE pname (in_empno IN VARCHAR2, out_name OUT VARCHAR2)
IS
BEGIN
SELECT employee_name
INTO out_name
FROM employees
WHERE emp_number = in_empno;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
out_name := NULL;
END;

Resources