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

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;

Related

ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'TEST' ORA-06550: line 1, column 7: PL/SQL: Statement ignored

create or replace procedure test(supplierid in number,
supplier out varchar) is
begin
select first_name
into Supplier
from lup_sup_master
where sup_id = supplierid;
end;
/
execute test(2279, :supplierid);
or
begin
execute test(2279, :supplierid); dbms_output.enable; dbms_output.put_line(supplier);
end;
Your procedure test has 2 input arguments. One has type IN which is supposed to be used with the procedure and the other parameter supplier has type OUT which means this parameter is suppose to hold the value which the Procedure returns.
As explained by #Barbaros, if you want to execute the Procedure via a SQL command prompt, you can follow the steps.
However the second way you showed was using a PLSQL Block.
begin
execute test(2279, :supplierid);
dbms_output.enable;
dbms_output.put_line(supplier); end;
In the above example of calling, you must note that Execute keyword is only be used whenever you use a SQL command line prompt. While using a PLSQL block you cal directly call the Procedure by its name as shown below. Also note that incase you have a OUT parameter, you must have OUT parameter passed to the Procedure since the Procedure is expecting 2 arguments. See below demo.
declare
var varchar2(100);
begin
test( supplierid => 2279, supplier =>var);
dbms_output.enable;
dbms_output.put_line(var);
End;
It seems you're confused between supplierid and supplier. You need to define a variable for supplier to get an output line printed, and most probably you defined a command line variable supplierid which's numeric type.
So, use below :
SQL> set serveroutput on;
SQL> var supplier varchar2;
SQL> execute test(2279, :supplier);
supplier
---------
Afzal -- as an example name

PLS-00306: wrong number or types of arguments in call to a Oracle SP

I'm trying to execute a below SP and it throws be the below error:
CREATE OR REPLACE PROCEDURE denodo.CLEAR_INDEX
( INDEX_NAME1 IN VARCHAR2,
INDEX_NAME2 IN VARCHAR2,
IT_WORKED OUT BOOLEAN ) as
BEGIN
IT_WORKED := FALSE;
EXECUTE IMMEDIATE 'drop index ' || INDEX_NAME1;
EXECUTE IMMEDIATE 'drop index ' || INDEX_NAME2;
IT_WORKED := TRUE;
EXCEPTION
WHEN OTHERS THEN
IT_WORKED := FALSE;
END CLEAR_INDEX;
CLEAR_INDEX#0 [JDBC ROUTE] [ERROR] Received exception with message 'ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'CLEAR_INDEX'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
What is going on here? appreciate your help.
This error you generally face when you deal with BOOLEAN datatype as OUT parameter and you try to print it or do any operation with any other inbuilt Oracle packages. You cannot directly use BOOLEAN datatype in dbms_output.put_line or any other DBMS package. For instance,if you want to print the OUT parameter you need to use sys.diutil.bool_to_int.
See below example which demonstrate the error you faced when you try to execute as below:
DECLARE
inx VARCHAR2(100):='ABC';
var BOOLEAN;
BEGIN
CLEAR_INDEX(INDEX_NAME1=>inx ,IT_WORKED =>var);
dbms_output.put_line(var);
END;
You face the issue:
ORA-06550: line 6, column 3:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action
To overcome such issue you must execute as below:
DECLARE
inx VARCHAR2(100):='ABC';
var BOOLEAN;
var1 varchar2(10);
BEGIN
CLEAR_INDEX(INDEX_NAME1=>inx ,IT_WORKED =>var);
var1:=CASE WHEN (sys.diutil.bool_to_int(var)) = 1 THEN 'TRUE'
WHEN (sys.diutil.bool_to_int(var)) = 0 THEN 'FALSE'
END;
dbms_output.put_line(var1);
END;
Output:
anonymous block completed
Mine is a similar case, however, a different call to a function, which has return type as Boolean and the input to the function is varchar2.
So, this is what I am doing:
Declare
v_ret1 varchar2(1000);
v_ret BOOLEAN;
Begin
v_ret := CASE WHEN SEI_PROCESS_MF_MNL_INVC_PKG.f_process_mf_mnl_invc(v_ret1) = 1 THEN 'TRUE'
WHEN SEI_PROCESS_MF_MNL_INVC_PKG.f_process_mf_mnl_invc(v_ret1) = 0 THEN 'FALSE'
END;
dbms_output.put_line(v_ret);
end;
I just wanted to see output of v_ret so that I can use that for further decision making. If v_ret is of type Boolean, the output should be either "TRUE" or "FALSE".

PLS-00201: identifier must be declared in Procedure

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().

Executing Stored Procedure - Oracle PL SQL

I'm currently trying to execute a stored procedure in Oracle PL SQL. I keep running into the same error for the below with execution.
I've tried both execution with the same error
SET SERVEROUTPUT ON;
EXEC get_phone(200.00,500.00);
OR
SET SERVEROUTPUT ON;
DECLARE
c_minprice products.price%type;
c_maxprice products.price%type;
BEGIN
c_minprice := get_phone(200);
c_maxprice := get_phone(500);
END;
ERROR from executing the above:
c_minprice := get_phone(200);
*
ERROR at line 5:
ORA-06550: line 5, column 15:
PLS-00306: wrong number or types of arguments in call to 'GET_PHONE'
ORA-06550: line 5, column 1:
PL/SQL: Statement ignored
ORA-06550: line 6, column 15:
PLS-00306: wrong number or types of arguments in call to 'GET_PHONE'
ORA-06550: line 6, column 1:
PL/SQL: Statement ignored
****Sample Snip-its form my code:
CREATE OR REPLACE PROCEDURE get_phone
(
c_minprice IN products.price%type,
c_maxprice IN products.price%type,
i_result OUT VARCHAR2
) AS
--Checking if starting price range is valid or not
IF c_minprice IS NULL THEN
i_result := 'Starting price range should be valid and cannot be empty';
RAISE V_MINPRICE; -- Raising exception if starting price is null
END IF;
--Checking if end price range is valid or not
IF c_maxprice IS NULL THEN
i_result := 'End price range should be valid and cannot be empty';
RAISE V_MAXPRICE; -- Raising exception if end price is null
END IF;
Your procedure requires three parameters so you have to pass in three parameters
DECLARE
l_result varchar2(100);
BEGIN
get_phone( 200, 500, l_result );
END;
/
should work. Of course, your procedure seems rather pointless. And if the goal is simply to return a result, you really ought to be using a function rather than a procedure with an out parameter.
get_phone expects 3 arguments, c_minprice, c_maxprice and i_result. You are only passing it one number. Pass it the rest of the arguments.

MD5 in Oracle (DBMS_OBFUSCATION_TOOLKIT.MD5)

I'm trying to compose a function to obtain MD5 hashes from bits I've gathered here and there. I want to obtain the lower-case hexadecimal representation of the hash. I have this so far:
CREATE OR REPLACE FUNCTION MD5 (
CADENA IN VARCHAR2
) RETURN DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM
AS
BEGIN
RETURN LOWER(
RAWTOHEX(
UTL_RAW.CAST_TO_RAW(
DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => CADENA)
)
)
);
END;
I'm not sure about the return type of the function. DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM looks like the appropriate choice and as far as I can tell it works as expected but the package definition for dbms_obfuscation_toolkit as displayed by SQL Developer shows this:
SUBTYPE varchar2_checksum IS VARCHAR2(16);
The output has 32 characters so I must be doing something wrong. My questions:
What's the correct type for the RETURN statement?
Am I doing unnecessary conversions to calculate the hash?
Here you go:
create or replace function getMD5(
in_string in varchar2)
return varchar2
as
cln_md5raw raw(2000);
out_raw raw(16);
begin
cln_md5raw := utl_raw.cast_to_raw(in_string);
dbms_obfuscation_toolkit.md5(input=>cln_md5raw,checksum=>out_raw);
-- return hex version (32 length)
return rawtohex(out_raw);
end;
The 32 length is because it is a hex representation of the raw(16) value. Or, modify above to output the raw version and store the raw in a RAW column (less space used, but you'll be doing future rawtohex and hextoraw conversions, believe me).
Cheers
It's a peculiarity of Oracle PL/SQL that stored procedure parameters and function return types cannot be limited. That is, we cannot have a procedure with a signature like this:
SQL> create or replace procedure my_proc (p1 in varchar2(30))
2 is
3 begin
4 null;
5 end;
6 /
Warning: Procedure created with compilation errors.
SQL> show error
Errors for PROCEDURE MY_PROC:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/34 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= . ) , # % default character
The symbol ":=" was substituted for "(" to continue.
SQL> create or replace procedure my_proc (p1 in varchar2)
2 is
3 begin
4 null;
5 end;
6 /
Procedure created.
SQL>
Sure we can define the procedure's parameter using a SUBTYPE but Oracle will ignore it. Same goes for function return types...
SQL> create or replace package my_subtypes as
2 subtype ltd_string is varchar2(30);
3 end;
4 /
Package created.
SQL> create or replace function my_func return my_subtypes.ltd_string
2 is
3 begin
4 return lpad('a', 4000, 'a');
5 end;
6 /
Function created.
SQL> select length(my_func) from dual
2 /
LENGTH(MY_FUNC)
---------------
4000
SQL>
The only way of limiting parameters and return types is to declare variables using subtypes within the stored procedure. Use the variables within the package, and assign them to the OUT paramters (or RETURN the variable for functions).
Which is a long-winded way of saying, you can use DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM in your code confident that it won't prevent your function returning 32 characters.
However, it will confuse developers who will lookup the SUBTYPE declaration. In the worst case these people will use the subtype to declare their own working variables with the following tragic result:
SQL> declare
2 v my_subtypes.ltd_string;
3 begin
4 v := my_func;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4
SQL>
So, it is better not to use an inappropriate subtype. Instead declare your own.

Resources