PLS-00201: identifier must be declared in Procedure - oracle

I have a PL/SQL Procedure code, which runs when it is / , but doesn't runs when it's executed. The error message I get is
SQL> EXECUTE MAXINUM;
BEGIN MAXINUM; END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'MAXINUM' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
The code which I'm working on is :
DECLARE
N NUMBER;
M NUMBER;
O NUMBER;
P NUMBER;
X NUMBER;
PROCEDURE MAXINUM(N IN NUMBER, M IN NUMBER, O IN NUMBER, P IN NUMBER, X OUT NUMBER) IS
BEGIN
IF N>M AND N>O AND N>P THEN
X:=N;
ELSIF M>N AND M>O AND M>P THEN
X:=M;
ELSIF O>N AND O>M AND O>P THEN
X:=O;
ELSIF P>N AND P>M AND P>O THEN
X:=P;
END IF;
END;
BEGIN
N:=&NUMBER;
M:=&NUMBER;
O:=&NUMBER;
P:=&NUMBER;
MAXINUM(N,M,O,P,X);
DBMS_OUTPUT.PUT_LINE('HIGHEST NUMBER = '||X);
END;
/
When it gave the 'identifier error', I tried dropping this procedure I got the error:
SQL> DROP PROCEDURE MAXINUM;
DROP PROCEDURE MAXINUM
*
ERROR at line 1:
ORA-04043: object MAXINUM does not exist
I have so far read this, this, this solutions and other solutions some what related to this error.

You have written an anonymous block with a local procedure MAXINUM(). This procedure can be called within that block but does not exist outside that block. Consequently you cannot call it independently.
If you want to use the procedure elsewhere you need to create it as a first class database object:
create or replace procedure MAXINUM
(N IN NUMBER, M IN NUMBER, O IN NUMBER, P IN NUMBER, X OUT NUMBER)
is
BEGIN
IF N>M AND N>O AND N>P THEN
X:=N;
ELSIF M>N AND M>O AND M>P THEN
X:=M;
ELSIF O>N AND O>M AND O>P THEN
X:=O;
ELSIF P>N AND P>M AND P>O THEN
X:=P;
END IF;
END;
/
Now you can call it in your code, like this:
DECLARE
N NUMBER;
M NUMBER;
O NUMBER;
P NUMBER;
X NUMBER;
BEGIN
N:=&NUMBER;
M:=&NUMBER;
O:=&NUMBER;
P:=&NUMBER;
MAXINUM(N,M,O,P,X);
DBMS_OUTPUT.PUT_LINE('HIGHEST NUMBER = '||X);
END;
/
Points to note:
what happens if a parameter is null?
what happens if two arguments have the same value?
the convention would be to declare this as a function and return the highest value instead of setting an OUT parameter.
Incidentally I assume you're doing this as an exercise, as it is a re-implementation of an existing Oracle built-in function, greatest().

Related

Encountered the symbol "2"

In this procedure I want to make a list of all procedures in my code and the user chooses a number to execute a certain procedure or function.
Here's my code
CREATE OR REPLACE PROCEDURE calling
IS
chosen VARCHAR2(1);
V_count NUMBER;
BEGIN
&chosen;
IF chosen='1' THEN
V_count:=visited.count_nb_city_visited(&idclient);
ELSIF chosen='2' THEN
V_count:=visited.max_vis;
visited.extract_best(V_count);
ELSIF chosen='3' THEN
ORDER_ORIGIN_CITY.ORDER_CITY;
ELSIF chosen='4' THEN
ORDER_ORIGIN_CITY.ORDER_CLIENT;
END IF;
END;
When running the code, this warning pops up "PLS-00103: Symbol "2" encountered (if I choose the number 2 and the same error is shown with any number I choose)
You can't (shouldn't) use substitution variables in a stored procedure as it will substitute the values in on compilation (and not as you are probably expecting on execution).
So if you substitute 2 for &chosen and 42 for &idclient then your code will be compiled as:
CREATE OR REPLACE PROCEDURE calling
IS
chosen VARCHAR2(1);
V_count NUMBER;
BEGIN
2;
IF chosen='1' THEN
V_count:=visited.count_nb_city_visited(42);
ELSIF chosen='2' THEN
V_count:=visited.max_vis;
visited.extract_best(V_count);
ELSIF chosen='3' THEN
ORDER_ORIGIN_CITY.ORDER_CITY;
ELSIF chosen='4' THEN
ORDER_ORIGIN_CITY.ORDER_CLIENT;
END IF;
END;
And will always execute with those fixed values.
You are getting the error because 2; is not a valid PL/SQL statement.
Instead, you should pass all the bind variables in the signature. Something like:
CREATE OR REPLACE PROCEDURE calling (
chosen IN NUMBER,
idclient IN NUMBER
)
IS
V_count NUMBER;
BEGIN
IF chosen = 1 THEN
V_count:=visited.count_nb_city_visited(idclient);
ELSIF chosen = 2 THEN
V_count:=visited.max_vis;
visited.extract_best(V_count);
ELSIF chosen = 3 THEN
ORDER_ORIGIN_CITY.ORDER_CITY;
ELSIF chosen = 4 THEN
ORDER_ORIGIN_CITY.ORDER_CLIENT;
END IF;
END;
/
If you want to call it from an anonymous PL/SQL block, then you can use substitution variables in that block:
BEGIN
calling(
chosen => &chosen,
idclient => &idclient
);
END;
/

not able to delete an element from array

PLS-00306: wrong number or types of arguments in call to 'DELETE'
create or replace PACKAGE BODY MYPACKAGE AS
PROCEDURE LeaveDates4
(
I_STDATE IN DATE,
I_ENDDATE IN DATE,
O_DATES OUT DateArray
)
AS
n INTEGER := LEAST( I_ENDDATE - I_STDATE, 29 );
just_date DATE;
H_dates DateArray;
--cursor cur_holidates is select HOLIDAY_DATE from TSL_HOLIDAYLIST;
x number;
BEGIN
select count(*) into x from TSL_HOLIDAYLIST;
O_DATES := DateArray();
H_dates := DateArray();
O_DATES.EXTEND( n + 1 );
-- h_dates.extend;
dbms_output.put_line(n);
dbms_output.put_line(x);
FOR i IN 0 .. n LOOP
O_DATES(i+1) := I_STDATE + i;
dbms_output.put_line(I_STDATE + i);
END LOOP;
for cur in (select HOLIDAY_DATE from TSL_HOLIDAYLIST)
loop
h_dates.extend;
h_dates(h_dates.last):= cur.HOLIDAY_DATE;
end loop;
FOR i IN h_DATES.first..h_DATES.last LOOP
dbms_output.put_line(h_DATES(i)||i);
END LOOP;
for i in O_DATES.first..O_DATES.last LOOP
FOR j IN h_DATES.first..h_DATES.last LOOP
if o_dates(i)=h_dates(j)
then o_dates.delete(i); -- PLS-00306 error here
end if;
end loop;
end loop;
END LeaveDates4;
END MYPACKAGE;
The above code is failing with an error at o_dates.delete(i);
I want to delete the date from o_dates if it exists in h_dates.
The error I am getting is:
PLS-00306: wrong number or types of arguments in call to 'DELETE'
You can't delete elements from the middle of a varray.
PL/SQL Language Reference: PL/SQL Collections and Records: DELETE Collection Method
For a simpler example, define both a varray and a nested table collection:
create or replace type date_varray as varray(3) of date;
create or replace type date_ntab as table of date;
Now declare a collection of each type and try to deletion element from it.
Nested table:
declare
my_ntable date_ntab := date_ntab(sysdate -1, sysdate, sysdate +1);
begin
my_ntable.delete(2);
end;
PL/SQL procedure successfully completed.
Varray:
declare
my_varray date_varray := date_varray(sysdate -1, sysdate, sysdate +1);
begin
my_varray.delete(2);
end;
my_varray.delete(2);
*
ERROR at line 4:
ORA-06550: line 4, column 5:
PLS-00306: wrong number or types of arguments in call to 'DELETE'
ORA-06550: line 4, column 5:
PL/SQL: Statement ignored

Script is failing to pass XMLTYPE argument to PLSQL procedure

I have a script that is supposed to open an xml file and read the contents and process it. The plsql procedure TEST_LOAD.BOB_LOAD has been created successfully.
TEST_LOAD.BOB_LOAD looks like this:
PROCEDURE BOB_LOAD(p_uuid IN varchar2,
xml_in IN xmltype,
msg_status OUT varchar2,
xml_out OUT xmltype);
END BOB_LOAD;
/
The script below calls this procedure in the final line and seems to be the cause of the error. I am assuming that it is not recognising the variable x as XMLTYPE.
DECLARE
xml_file UTL_FILE.FILE_TYPE;
chars_read INTEGER;
xml_clob CLOB;
xamount INTEGER :=32767;
char_buffer VARCHAR2(32767);
x XMLType;
BEGIN
xml_file := utl_file.fopen('/export/hm/testpit/bob', 'test.xml', 'r', xamount);
DBMS_LOB.CREATETEMPORARY(xml_clob, true);
LOOP
BEGIN
UTL_FILE.GET_LINE(xml_file, char_buffer);
chars_read :=LENGTH(char_buffer);
DBMS_LOB.WRITEAPPEND(xml_clob, chars_read, char_buffer);
DBMS_LOB.WRITEAPPEND(xml_clob, 1, CHR(10));
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT;
END;
END LOOP;
UTL_FILE.FCLOSE(xml_file);
x := XMLType.createXML(xml_clob);
TEST_LOAD.BOB_LOAD('9718fa05-9995-4f17-jk1k-763113b8f4a4', x );
END;
/
However when I run the script above I get an ORA-06550, PLS:00306 error saying:
ORA-06550: line 39, column 3:
PLS-00306: wrong number or types of arguments in call to 'BOB_LOAD'
ORA-06550: line 39, column 3:
PL/SQL: Statement ignored
Your procedure has 4 parameters. You call it with only 2. You need to call it with the out parameters as well.
Much easier way to read a file's contents into a CLOB:
function read_clob_from_file(p_directory varchar2
,p_filename varchar2) return clob is
l_amt number := dbms_lob.lobmaxsize;
l_dst_loc clob;
l_dst_offset number := 1;
l_lang_ctx number := dbms_lob.default_lang_ctx;
l_src_loc bfile;
l_src_offset number := 1;
l_warning number;
begin
l_src_loc := bfilename(p_directory, p_filename);
dbms_lob.createtemporary(l_dst_loc, true);
dbms_lob.fileopen(l_src_loc, dbms_lob.file_readonly);
dbms_lob.loadclobfromfile(l_dst_loc
,l_src_loc
,l_amt
,l_dst_offset
,l_src_offset
,dbms_lob.default_csid
,l_lang_ctx
,l_warning);
dbms_lob.fileclose(l_src_loc);
return l_dst_loc;
end;

expression 'string' cannot be used as an assignment target -SQL PLUS

I wrote the following procedure which was meant to be anonymous and remove all the vowels from a string, but when I call it I get an error: I've followed the advice given in a similar post, but it didn't help:Oracle PLS-00363: expression '' cannot be used as an assignment target
SQL> CREATE OR REPLACE PROCEDURE disemvowel (string IN OUT NVARCHAR2)
2 IS
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(translate(string,'euioa',''));
5 END disemvowel;
6 /
Procedure created.
So good so far, but now I call it:
SQL> BEGIN
2 disemvowel('hahahahaha');
3 END;
4 /
The Error message says:
disemvowel('hahahahaha');
*
ERROR at line 2:
ORA-06550: line 2, column 12:
PLS-00363: expression 'hahahahaha' cannot be used as an assignment target
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
Your procedure has IN OUT parameter. So while calling the procedure you should supply a variable to it, so that it can hold the value that the procedure gives back. You cannot supply a value directly, as it cannot be modified by the procedure.
DECLARE
param NVARCHAR2 (20) := 'hahahahaha';
BEGIN
disemvowel (param);
END;
/
Generate new VARCHAR2 type variable to assign your IN (input) string.
PROCEDURE sp_name(
ps_list IN VARCHAR2,
...
write here other IN's and OUT's
...
)
AS
ps_list_copy VARCHAR2 (32000);
BEGIN
ps_list_copy := ps_list;
...
do your works with ps_list_copy
...
...
EXCEPTION WHEN OTHERS THEN
....
END sp_name;

How to drop overloaded functions in Oracle?

I have faced this question during an interview very recently. Please hep me on this. Let us say there are two functions in our schema the prototypes of which are as follows,
display(a varchar2, b number)
display(c varchar2, d varchar2, e number)
and I issue the following statement
drop function display;
which function will be dropped?
overloading means use of same subprograms to call different subprograms. this is an example
declare
x number;
y number;
function findenqno (fname1 varchar2) return number is --–function 1
enqno1 number (10);
begin
select enquiryno
into enqno1
from enquiry
where fname = fname1;
return(enqno1);
end;
function findenqno (refcode1 number) return number is --–function 2
enqno1 number (10);
begin
select enquiryno
into enqno1
from enquiry
where refcode = refcode1;
return (enqno1);
end;
begin
-- You call the function as:
X := findenqno ('ANIL');
dbms_output.put_line('using name '||x);
Y := findenqno (1002);
dbms_output.put_line('using refcode '||y);
end;
/
this is not a standlone subprogram so there is no point droping a overloaded function .
as it is not written in the db.

Resources