Ora Error - 06553 - Wrong number of arguments in a call - oracle

I created a type as below:
create type colist_array as table of varchar(3);
Created function:
create or replace function sel_tst(colm_lst colist_array)
return colist_array
as
--Declaration and Initialization
a colist_array := colist_array();
begin
for i in 1..colm_lst.count
loop
a.extend;
a(i):= colm_lst(i);
end loop;
return (a);
end;
Now when am calling, it throws error -
wrong number of arguments
Any suggestions here please.
select sel_tst('XXY') from dual; -- Not working
select sel_tst('XXY,SDD,DFS') from dual; -- Not working
select sel_tst('XXY','YDY') from dual; -- Not working

Your function expects a single parameter of type colist_array. You are calling it with one or more varchar parameters.
The correct syntax to create an instance of your type is e.g.: colist_array('XXY','SDD','DFS')
So your select statement should be:
select sel_tst(colist_array('XXY','SDD','DFS'))
from dual;

Related

Oracle PL/SQL SELECT INTO clause thinks it needs another INTO

I have a simple test function where I'm passing in a specific ID (the primary key of the table I'm selecting from), and computing a simple function on it and the parameters.
The skeleton code and test:
create or replace function test(id varchar2, area float) return float is
theRow forest%ROWTYPE;
begin
select * into theRow from forest where Forest_No = id;
return area / theRow.Area;
end;
begin
select test('1', 16000) from dual;
end;
The output:
[2019-10-14 21:19:10] [65000][6550] ORA-06550: line 2, column 5:
[2019-10-14 21:19:10] PLS-00428: an INTO clause is expected in this SELECT statement
I am at a loss for what to do here, as far as I can tell the documentation and examples use the same order and syntax. I have tried moving the into clause to the end as in Postgresql, but that did not work.
What have I missed here?
Issue is in calling statement.
Whenever select statement is used in plsql block it must have into clause to assign return value to variable.
You should remove begin and end from your calling code:
--begin -- remove this
select test('1', 16000) from dual;
--end; -- remove this
Or if you want to use it in plsql block then add into clause:
Declare
Area_ float(precision);
begin
select test('1', 16000) into area_ from dual;
-- use area_ in your code wherever required
dbms_output.put_line('area: ' || area_);
end;
Cheers!!

How to run Oracle function which returns more than one value

My test function is this
CREATE OR REPLACE FUNCTION MULTI_VAL
(MYNAME OUT EMP2017.ENAME%TYPE)
RETURN NUMBER AS
MYSAL EMP2017.SAL%TYPE;
BEGIN
SELECT SAL, ENAME INTO MYSAL, MYNAME FROM EMP2017 ;
RETURN MYSAL;
END;
/
When I run it like
variable mynm varchar2(20)
SELECT MULTI_VAL(:mynm) FROM dual;
it gives this error
ERROR at line 1:
ORA-06553: PLS-561: character set mismatch on value for parameter 'MYNAME'
The error you get now indicates a datatype mismatch.
However there is a fundamental problem with your code. We cannot use functions which have OUT parameters in SQL. So once you have fixed the datatype issue you will get this error: ORA-06572: Function MULTI_VAL has out arguments.
You can run it like this:
declare
n varchar2(20);
x number;
begin
x := multi_val(n);
end;
/
Generally, functions with OUT parameters are considered bad practice. The syntax allows them, but the usage is hard to understand. It's better to use a procedure with two OUT parameters (because we can only call the program in PL/SQL anyway) or else have the function return a user-defined type.
CREATE TABLE EMP2017(ENAME VARCHAR2(10),SAL NUMBER);
INSERT INTO EMP2017 VALUES ('SMITH',5000);
INSERT INTO EMP2017 VALUES ('JOHNS',1000);
COMMIT;
CREATE TYPE RET_MULT AS OBJECT
(ENAME VARCHAR2(10),SAL NUMBER);
CREATE TYPE T_RET_MULT AS TABLE OF RET_MULT;
CREATE OR REPLACE FUNCTION MULTI_VAL RETURN T_RET_MULT PIPELINED IS
MYSAL RET_MULT;
BEGIN
FOR I IN(SELECT SAL, ENAME FROM EMP2017) LOOP
MYSAL := RET_MULT(I.ENAME,I.SAL);
PIPE ROW(MYSAL);
END LOOP ;
RETURN ;
END;
SELECT * FROM TABLE(MULTI_VAL());
I think this question can be solved without using pipeline functions. Just like this. All pre required data as described #Sedat.Turan except function. Sorry for copy/past.
CREATE TABLE EMP2017(ENAME VARCHAR2(10),SAL NUMBER);
INSERT INTO EMP2017 VALUES ('SMITH',5000);
INSERT INTO EMP2017 VALUES ('JOHNS',1000);
COMMIT;
CREATE TYPE RET_MULT AS OBJECT
(ENAME VARCHAR2(10),SAL NUMBER);
CREATE TYPE T_RET_MULT AS TABLE OF RET_MULT;
create or replace function MULTI_VAL return T_RET_MULT is
RET_SET T_RET_MULT;
begin
select RET_MULT(ENAME, SAL) bulk collect into RET_SET from EMP2017;
return RET_SET;
end;

how to corectly call table function in PL/SQL

I have table function which returns table of file names (type t_file_list is table of clob;) from .zip file (in BLOB format) the header is like:
function get_file_list(
p_zipped_blob in blob
,p_encoding in varchar2 := null
)
return t_file_list
is
.....
end;
and I need to select these file names and for each call some procedure, but i cant find way to call function get_file_list correctly, I try this:
for i in (select * from table(zip_util_pkg.get_file_list(ab_zipped_blob)))
loop
.....
end loop;
but it gives me some errors like ORA-22905 and PLS-00642. Can someone tell me what I am doing wrong and how to call table function correctly?
No need to use SQL - you can do it entirely in PL/SQL:
DECLARE
p_files ZIP_UTIL_PKG.T_FILE_LIST;
BEGIN
p_files := zip_util_pkg.get_file_list(ab_zipped_blob);
FOR i IN 1 .. p_files.COUNT LOOP
some_procedure( p_files(i) );
END LOOP;
END;
/

PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER

I'm executing PL/SQL code to display the Currency Code from the Failed Reservation table. Object type and Nested Table collections are used.
When the PL/SQL code is run, the following error is generated. The corresponding line is highlighted in the PL/SQL code section.
Error report:
ORA-06550: line 27, column 11:
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
ORA-06550: line 27, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code is pasted below:
DDL - Table creation:
CREATE TABLE FAILEDRESERVATION
(
FAILEDRESERVATIONID NUMBER(18,0),
FK_TRANSACTIONID NUMBER(18,0),
DEBITRESERVATIONID NUMBER(18,0),
RESERVATIONTIME DATE,
RESERVATIONAMOUNT NUMBER(18,5),
CURRENCYCODE CHAR(3 BYTE),
AVAILABLEAMOUNT NUMBER(18,5)
);
ALTER TABLE FAILEDRESERVATION
ADD CONSTRAINT "PK_FAILEDRESERVATION" PRIMARY KEY ("FAILEDRESERVATIONID");
Object Type:
CREATE OR REPLACE TYPE TYPE type_failedreservation AS OBJECT
(
FK_TRANSACTIONID NUMBER(18),
DEBITRESERVATIONID NUMBER(18),
RESERVATIONTIME DATE,
RESERVATIONAMOUNT NUMBER(18,5),
CURRENCYCODE CHAR(3),
AVAILABLEAMOUNT NUMBER(18,5)
);
DML:
INSERT INTO FAILEDRESERVATION (FAILEDRESERVATIONID,FK_TRANSACTIONID,DEBITRESERVATIONID,RESERVATIONTIME,RESERVATIONAMOUNT,CURRENCYCODE,AVAILABLEAMOUNT)
VALUES (289,2,1,to_date('07-MAR-16','DD-MON-RR'),20000,'USD',10000);
INSERT INTO FAILEDRESERVATION (FAILEDRESERVATIONID,FK_TRANSACTIONID,DEBITRESERVATIONID,RESERVATIONTIME,RESERVATIONAMOUNT,CURRENCYCODE,AVAILABLEAMOUNT)
VALUES (288,1,1,to_date('01-MAR-16','DD-MON-RR'),10000,'NOK',10000);
Nested Tables:
CREATE OR REPLACE TYPE type_failedreservation_coll as TABLE OF type_failedreservation;
CREATE OR REPLACE TYPE type_dbtrsid_coll AS TABLE OF NUMBER;
PL/SQL Code:
DECLARE
P_FAILEDRESERVATION APPDATA.TYPE_FAILEDRESERVATION_COLL;
vdbtid_coll type_dbtrsid_coll := type_dbtrsid_coll();
BEGIN
SELECT TYPE_FAILEDRESERVATION(fk_transactionid,debitreservationid,reservationtime,reservationamount,currencycode,availableamount)
BULK COLLECT
INTO p_failedreservation
FROM failedreservation;
-- This is line 27
SELECT frs.debitreservationid
INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST
LOOP
dbms_output.put_line('The currency code is: '||v_iterate);
END LOOP;
END;
Why is the code generating this error ?
You've declared vdbtid_coll as a collection type, so you need to bulk collect into that too:
SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
With that change:
PL/SQL procedure successfully completed.
The currency code is: 1
The currency code is: 2
That's just giving you the index number in the collection though, so I don't think it's what you really want. You may want:
FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST
LOOP
dbms_output.put_line('The currency code is: '
|| p_failedreservation(v_iterate).currencycode);
END LOOP;
which gets:
PL/SQL procedure successfully completed.
The currency code is: USD
The currency code is: NOK
You don't really need the second select/collection at all though, you can do:
FOR v_iterate IN 1..p_failedreservation.COUNT
LOOP
dbms_output.put_line('The currency code is: '
|| p_failedreservation(v_iterate).currencycode);
END LOOP;
... for the same result. Although I'm not sure what the relevance of the debitreservationid is in that second query, as it is the same value (1) in both rows.
You are trying to select multiple rows into a collection. You need to use BULK COLLECT INTO rather than just INTO.
Change
SELECT frs.debitreservationid
INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
To
SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
and you probably want the output to be:
FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST LOOP
dbms_output.put_line('The currency code is: '|| vdbtid_coll(v_iterate) );
END LOOP;
However, you could simplify it all to:
DECLARE
P_FAILEDRESERVATION APPDATA.TYPE_FAILEDRESERVATION_COLL;
BEGIN
SELECT TYPE_FAILEDRESERVATION(
fk_transactionid,
debitreservationid,
reservationtime,
reservationamount,
currencycode,
availableamount
)
BULK COLLECT INTO p_failedreservation
FROM failedreservation;
FOR v_iterate IN p_failedreservation.FIRST .. p_failedreservation.LAST LOOP
dbms_output.put_line(
'The currency code is: '|| p_failedreservation(v_iterate).currencycode
);
END LOOP;
END;
Try casting the type array to its type as follows
SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(CAST(p_failedreservation as APPDATA.TYPE_FAILEDRESERVATION_COLL)) frs;
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got CHAR
You may get this error in case you write type table in place of type object when
using BULK COLLECT INTO, i faced this error coz i did so.
FOR EXAMPLE:
CREATE OR REPLACE TYPE OBJ_TYPE AS OBJECT (NAME VARCHAR2(20));
/
CREATE OR REPLACE TYPE TBL_TYPE IS TABLE OF OBJ_TYPE;
/
CREATE OR REPLACE FUNCTION FUNC1 RETURN TBL_TYPE AS
TBL_TEXT TBL_TYPE := TBL_TYPE();
BEGIN
SELECT ***OBJ_TYPE*** (NAME) BULK COLLECT INTO ***TBL_TEXT*** FROM <table-name> ;
RETURN ***TBL_TEXT***;
END;
/
Care should be taken when using object type and table type in the function.

Stored procedure to insert new values into the class table

This is homework.
The goal is to create a stored procedure which will insert new values into the class table. If the end_date is prior to the start_date, then the stored procedure needs to add two weeks to the start date by default.
Here's what I have so far:
CREATE OR REPLACE PROCEDURE insert_class(
Teacher_name_param class.teacher_name%TYPE,
class_name_param class.class_name%TYPE,
Start_Date_param class.start_date%TYPE,
End_date_param class.end_date%TYPE,
class_category_param class.class_category%TYPE,
Topic_param class.topic%TYPE,
Teacher_credential_param class.teacher_credential%TYPE)
AS
class_number_var class.class_number%TYPE;
--start_date_var class.start_date%TYPE;
end_date_var class.end_date%TYPE;
BEGIN
-- Creates the next ID
SELECT class_number_seq.NEXTVAL
INTO class_number_var
FROM dual;
IF end_date_param < start_date_param THEN
SELECT end_date_param INTO end_date_var
FROM class
WHERE class_number_var = class.class_number;
end_date_var := start_date_param + 14;
ELSE
end_date_var := end_date_param;
END IF;
INSERT INTO class (class_number, teacher_name, class_name, start_date, end_date,
class_category, topic, teacher_credential)
VALUES (class_number_var, teacher_name_param, class_name_param, start_date_param, end_date_param,
class_category_param, topic_param, teacher_credential_param);
COMMIT;
END;
/
Example call statement:
CALL insert_class('Collin Hannah', 'Intro to psychology', 01-OCT-15, 01-SEP-15, 'Psychology', 'Intro Classes', 'BS psychology');
This looks like solid logic to me. I get a "procedure insert_class" compiled message. However, when I try to call the procedure, I get an error message not a valid function or procedure name.
I'm assuming that end_date_var will take the place of the end_date_param if the original end_date_param value is before the start_date_param. Is this correct? If I try to place both end_date_var and end_date_param in the VALUES portion of the INSERT INTO statement, it throws the entire thing off of balance.
Try this. It seems procedure is good from compilation end. Just to add always put date format properly as illuistrated below. Lte me know if this helps.
BEGIN
insert_class('Collin Hannah', 'Intro to psychology', TO_DATE('01-OCT-15','DD-MON-YY'), TO_DATE('01-SEP-15','DD-MON-YY'), 'Psychology', 'Intro Classes', 'BS psychology');
END;
--OR
EXEC insert_class('Collin Hannah', 'Intro to psychology', TO_DATE('01-OCT-15','DD-MON-YY'), TO_DATE('01-SEP-15','DD-MON-YY'), 'Psychology', 'Intro Classes', 'BS psychology');
CALL insert_class
not a valid function or procedure name
CALL is not a valid syntax to execute the procedure. You need to either EXECUTE in SQL*Plus, or call it in a PL/SQL block.
SQL> create or replace procedure p
2 as
3 begin
4 null;
5 end;
6 /
Procedure created.
SQL> sho err
No errors.
Procedure is created.
Error reproduce
SQL> CALL p;
CALL p
*
ERROR at line 1:
ORA-06576: not a valid function or procedure name
Correct way
SQL> EXEC p;
PL/SQL procedure successfully completed.
Also,
01-OCT-15
01-OCT-15 is not a valid DATE. You should either use TO_DATE or ANSI Date literal to explicitly convert a literal into date.
For example,
TO_DATE('01-OCT-2015', 'DD-MON-YYYY','NLS_DATE_LANGUAGE=ENGLISH')
Remember, TO_DATE is NLS dependent.
Since, you are not concerned with the time portion, I would prefer using ANSI Date literal which uses a fixed date format 'YYYY-MM-DD'.
For example,
DATE '2015-10-01'

Resources