PLS-00306: wrong number or types of arguments in call to procedure PROC_T - oracle

declare
TYPE stag_tab IS TABLE OF d_staging%ROWTYPE;
stag_tab1 stag_tab;
begin
--Bulk Collect
select * bulk collect into staging_tab1 from d_staging;
PKG_T.PROC_T(stag_tab1);
end;
/
Package definition:
--Package
CREATE OR REPLACE PACKAGE PKG_T
AS
TYPE staging IS TABLE OF d_staging%ROWTYPE;
PROCEDURE PROC_T(p_staging IN staging);
END PKG_T;
/
-- Package Body
CREATE OR REPLACE PACKAGE BODY PKG_T
AS
PROCEDURE PROC_T (p_staging IN staging)
AS
VAR1 d_staging%ROWTYPE;
CUR1 SYS_REFCURSOR;
QUERY_STRING VARCHAR2(2000);
BEGIN
OPEN CUR1 FOR SELECT * from table(p_staging);
LOOP
FETCH CUR1 into VAR1;
EXIT WHEN cur1%NOTFOUND;
INSERT into d (testdata) VALUES (var1.testval1);
COMMIT;
END LOOP;
END;
END PKG_T;
/

You are receiving the error because the procedure PKG_T.PROC_T is expecting a parameter of type staging, but when you are calling the procedure you are passing it a variable of type stag_tab. The type of the variable being passed to the procedure needs to match the type of the parameter definition for the procedure.

Your procedure declaration:
PROCEDURE PROC_T (p_staging IN staging)
Takes the argument as type staging.
You are passing the argument as a locally defined type:
TYPE stag_tab IS TABLE OF d_staging%ROWTYPE;
These are different types. Instead, you need the PL/SQL block to be:
declare
stag_tab1 package_name.staging;
begin
select *
bulk collect into stag_tab1
from d_staging;
PKG_T.PROC_T(stag_tab1);
end;
/

Related

Oracle PL/SQL Developer: Return %RowType from Package Procedure

i'm kind of new to Oracle Pl\SQL. I was just trying to create a simple Package with a procedure that returns a set of object id's; the code is as follows:
--Package Spec
CREATE OR REPLACE PACKAGE TEST IS
--GET OBJECT ID'S FROM CONTROL TABLE
PROCEDURE get_object_id_control(p_obj_id OUT abc_table%ROWTYPE);
END;
--Package Body
PROCEDURE get_object_id_control(p_obj_id OUT abc_table%ROWTYPE) AS
BEGIN
SELECT object_id
INTO p_obj_id
FROM abc_table
WHERE fec_proc IS NULL;
END;
I get Error: PL/SQL: ORA-00913: too many values. Is this the correct way for returning multiple values of same data type, or is there a better approach. Thanks in advance.
You can create a custom table type and set the out parameter of the procedure to that type.
CREATE TABLE ABC_TABLE(ID varchar2(100));
create or replace type abc_tab is table of varchar2(100);
/
CREATE OR REPLACE PACKAGE TEST IS
PROCEDURE get_object_id_control(p_obj_id OUT abc_tab);
END;
/
CREATE OR REPLACE PACKAGE BODY TEST IS
PROCEDURE get_object_id_control(p_obj_id OUT abc_tab) AS
BEGIN
SELECT id
bulk collect INTO p_obj_id
FROM abc_table;
END;
END;
/
Then you can call it like so:
declare
v abc_tab;
begin
TEST.get_object_id_control(p_obj_id => v);
for i in v.first..v.last loop
dbms_output.put_line(v(i));
end loop;
end;
/
Similar to GurV's answer (since he beat me by like 30 seconds...), you can use a PL/SQL object type as well. You do not need the CREATE TYPE statement if you don't need to reference the type in SQL.
--Package Spec
CREATE OR REPLACE PACKAGE TEST AS
TYPE id_table_type IS TABLE OF NUMBER;
--GET OBJECT ID'S FROM CONTROL TABLE
PROCEDURE get_object_id_control(p_obj_id_list OUT id_table_type);
END;
--Package Body
CREATE OR REPLACE PACKAGE BODY TEST AS
PROCEDURE get_object_id_control(p_obj_id_list OUT id_table_type) AS
BEGIN
SELECT object_id
BULK COLLECT INTO p_obj_id_list
FROM abc_table
WHERE fec_proc IS NULL;
END;
END;
To use it:
DECLARE
l_id_list test.id_table_type;
BEGIN
test.get_object_id_control (p_obj_id_list => l_id_list);
FOR i IN l_id_list.FIRST .. l_id_list.LAST LOOP
DBMS_OUTPUT.put_line (l_id_list (i));
END LOOP;
END;

How can a stored procedure be executed in Oracle with in and out parameters?

Here's my stored procedure:
CREATE OR REPLACE PROCEDURE STATS_SD
(
P_ID IN NUMBER,
PRC OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN PRC FOR
SELECT
ID,
SESID
FROM RESPONSES
WHERE ID IN (P_ID)
END;
When I try to execute it using
EXEC EXAM_STATS_STUDENTS_SD('6901');
I get the following error:
PLS-00306: wrong number or types of arguments in call to 'STATS_SD'
Do you have any ideas why?
Here is an example using an OUT parameter that is a sys_refcursor. Note that I close the cursor in the pl/sql block that uses it (which is important!):
create or replace procedure get_data(o_cur OUT SYS_REFCURSOR) as
begin
OPEN o_cur FOR
select * from emp;
end;
And using the get_data procedure:
declare
l_cur sys_refcursor;
l_row emp%rowtype;
begin
get_data(l_cur);
LOOP
fetch l_cur
into l_row;
exit when l_cur%notfound;
-- do something with l_row here
END LOOP;
close l_cur;
end;
You are passing a wrong datatype to your procedure.
According to your declaration a NUMBER is expected:
P_ID IN NUMBER
However, you pass a VARCHAR2 in your exec command:
EXEC EXAM_STATS_STUDENTS_SD('6901');
Note the '' around the value.
Try calling this instead:
EXEC EXAM_STATS_STUDENTS_SD(6901);
Apart from that you are missing the second parameter completely.

How to transfer cursor to the procedure dynamically and to set rowtype variable dynamically?

I have written the procedure with dynamically set cursor and %rowtype variable:
create or replace procedure process(source_table IN varchar2, my_cursor IN sys_refcursor)
is
c sys_refCURSOR;
rec my_cursor%rowtype;
begin
Dbms_Output.put_line('process starts');
open c for 'select * from '||source_table;
loop
fetch c into rec;
exit when c%notfound;
end loop;
close c;
Dbms_Output.put_line('process is over');
end process;
I am going to transfer cursor to the procedure with the function as follows:
CREATE OR REPLACE FUNCTION ddp_get_allitems (source_table IN Varchar2)
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR 'SELECT * FROM '|| source_table;
RETURN my_cursor;
END ddp_get_allitems;
While compiling the procedure "process" I have the error:
PLS-00320 the declaration of the type of the expression is incomplete or malformed.
The compiler has hilighted the row with "rec my_cursor%rowtype;" as the error source. The varibale "source_table" and "my_cursor" are based upon the same table (select * from my_table).
So Why the error has arisen and how to remove it?
Since PL/SQL is statically typed the compiler needs to know the types of all the variables at compile time.
So there is no room for advanced metaprogramming. I'm afraid you can't do that.
There are, however, generic types found at SYS.STANDARD and a few internal functions accepting them.
-- The following data types are generics, used specially within package
-- STANDARD and some other Oracle packages. They are protected against
-- other use; sorry. True generic types are not yet part of the language.
type "<ADT_1>" as object (dummy char(1));
type "<RECORD_1>" is record (dummy char(1));
type "<TUPLE_1>" as object (dummy char(1));
type "<VARRAY_1>" is varray (1) of char(1);
type "<V2_TABLE_1>" is table of char(1) index by binary_integer;
type "<TABLE_1>" is table of char(1);
type "<COLLECTION_1>" is table of char(1);
type "<REF_CURSOR_1>" is ref cursor;
Take "<ADT_1>" for example. There is XMLTYPE constructor or DBMS_AQ ENQUEUE and DEQUEUE functions. You can pass any kind of object there.
For now you cannot use this datatype in custom functions since they are "not yet part of the language", but maybe some day there will be some support for this.
Just a thought to modify soe params which can basically same output
you want to achieve. Basically here for Function i have replaced
RETURN type as TABLE TYPE which can be easilt called in Procedure abd
rest manipulations can be done.Let me know if this helps
--SQL Object creation
CREATE TYPE source_table_obj IS OBJECT
(<TABLE_ATTRIBITES DECLARATION>);
--SQL TABLE type creation
CREATE TYPE source_table_tab IS TABLE OF source_table_obj;
--Function creation with nested table type as RETURN type
CREATE OR REPLACE FUNCTION ddp_get_allitems(
source_table IN VARCHAR2)
RETURN source_table_tab
AS
src_tab source_table_tab;
BEGIN
SELECT * BULK COLLECT INTO src_tab FROM source_table;
RETURN src_tab;
END ddp_get_allitems;
-- Using Function's OUT param as an IN Param for Procedure an do all the requird processing
CREATE OR REPLACE PROCEDURE process(
source_table IN VARCHAR2,
src_tab_in IN source_table_tab)
IS
BEGIN
FOR i IN src_tab_in.FIRST..src_tab_in.LAST
LOOP
dbms_output.put_line('job processing');
END LOOP;
END process;

Calling one procedure from another procedure

The code below is saved in a file named proc1.sql
DECLARE
B VARCHAR2(25);
C NUMBER;
PROCEDURE Get_manager_detailS(NO IN NUMBER,NAME OUT VARCHAR2,SAL1 OUT NUMBER)
IS
BEGIN
SELECT ENAME, SAL
INTO NAME, SAL1
FROM EMP
WHERE EMPNO = NO;
END;
BEGIN
Get_manager_detailS(7900,B,C);
DBMS_OUTPUT.PUT_LINE(B);
DBMS_OUTPUT.PUT_LINE(C);
END;
/
This procedure is stored in another file proc3.sql
PROCEDURE Test_Procedure()
IS
BEGIN
b varchar2(25);
c number;
DBMS_OUTPUT.PUT_LINE('CALLING');
Get_manager_details(7900,b,c);
END;
When I am running it in sqlplus, it is showing an error
SP2-0734 UNKNOWN COMMAND BEGINING PROCEDURE.. REST OF THE LINES IGNORED.
SP2-0042 UNKNOWN COMMAND" IS "..REST OF THE LINE IGNORED.
Creating a PROCEDURE/FUNCTION vs. ANONYMOUS BLOCK
Stored PROCEDURES/FUNCTIONS always starts with CREATE OR REPLACE ... and ends with END;
CREATE OR REPLACE serves as the implicit declare for stored functions and procedures, thus you dont have to write DECLARE anymore inside the block
An anonymous block starts with DECLARE and ends with END;
As for the code/block of codes saved in proc1.sql.
Your declaration is misplaced.You should place it after the end of
the procedure
Start the procedure with CREATE OR REPLACE PROCEDURE
Try This Block:
-- DECLARE
-- B VARCHAR2(25);
-- C NUMBER;
CREATE OR REPLACE PROCEDURE Get_manager_detailS(NO IN NUMBER,
NAME OUT VARCHAR2,
SAL1 OUT NUMBER)
IS
BEGIN
SELECT ENAME, SAL
INTO NAME, SAL1
FROM EMP
WHERE EMPNO = NO;
END; -- end of procedure
/
DECLARE -- start of anonymous block
B VARCHAR2(25);
C NUMBER;
BEGIN
Get_manager_detailS(7900,B,C);
DBMS_OUTPUT.PUT_LINE(B);
DBMS_OUTPUT.PUT_LINE(C);
END;
As for the procedure that will call the get_manager_details procedure.Its will be just the same as the anonymous block, the only difference will be is that it is stored
Base from what have you done already
If you will not declare parameters in your procedure, parenthesis are not necessary so remove it.
If you dont have output parameters that will catch the result of your procedure, you can use dbms_output.put_line as you have used in
the anonymous block above
variable declarations should be done after the IS keyword and before BEGIN statements, because as I have noted above CREATE OR
REPLACE ... IS is the implicit declare for the stored functions and
procedures
TRY THIS:
CREATE OR REPLACE PROCEDURE Test_Procedure
IS -- always start with CREATE OR REPLACE
b varchar2(25);
c number;
BEGIN
-- b varchar2(25); misplaced declarations
-- c number;
DBMS_OUTPUT.PUT_LINE('CALLING');
Get_manager_details(7900,b,c);
DBMS_OUTPUT.PUT_LINE(B); -- displays the results b
DBMS_OUTPUT.PUT_LINE(C); -- and c
END;
Sorry for the long post.
HOPE THIS HELPS.
CHEERS
Your first block is anonymous block in which you declare procedure - you can call procedure Get_manager_details within anonymous block only. You can't call Get_manager_details from Test_Procedure because there is no such procedure. You need to create your procedure Get_manager_details first
Create or replace procedure Get_manager_details ....
Then you can run
Create or replace procedure Test_Procedure ....
Or it will not compile.
If you are trying to call the procedure get_manager_details inside test_procedure then you first need to create the test procedure.
Add create or replace procedure test_procedure .
Then after creating the test_procedure you can execute it in an anonymous block which will call the get_manager_details procedure.

pass pl/sql record as arguement to procedure

How to pass pl/sql record type to a procedure :
CREATE OR REPLACE PACKAGE BODY PKGDeleteNumber
AS
PROCEDURE deleteNumber (
list_of_numbers IN List_Numbers
)
IS
i_write VARCHAR2(5);
BEGIN
--do something
END deleteNumber;
END PKGDeleteNumber;
/
In this procedure deleteNumber I have used List_Numbers, which is a record type. The package declaration for the same is :
CREATE OR REPLACE PACKAGE PKGDeleteNumber
AS
TYPE List_Numbers IS RECORD (
IID NUMBER
);
TYPE list_of_numbers IS TABLE OF List_Numbers;
PROCEDURE deleteNumber (
list_of_numbers IN List_Numbers
);
END PKGDeleteNumber;
I have to execute the procedure deleteNumber passing a list of values. I inserted numbers in temp_test table, then using a cursor U fetched the data from it :
SELECT *
BULK COLLECT INTO test1
FROM temp_test;
Now, to call the procedure I am using
execute immediate 'begin PKGDELETENUMBER.DELETENUMBER(:1); end;'
using test1;
I have tried many other things as well(for loop, dbms_binding, etc). How do I pass a pl/sql record type as argument to the procedure?
EDIT:
Basically, I want to pass a list of numbers, using native dynamic sql only...
adding the table temp_test defn (no index or constraint):
create table test_temp (
IID number
);
and then inserted 1,2,3,4,5 using normal insert statements.
For this solution,
In a package testproc
CREATE TYPE num_tab_t IS TABLE OF NUMBER;
CREATE OR REPLACE PROCEDURE my_dyn_proc_test (p_num_array IN num_tab_t) AS
BEGIN
dbms_output.put_line(p_num_array.COUNT);
END;
/
this is called from sql prompt/toad
DECLARE
v_tab testproc.num_tab_t := testproc.num_tab_t(1, 10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN testproc.my_dyn_proc_test(:1); END;' USING v_tab;
END;
this will not work.This shows error.I am not at my workstation so am not able to reproduce the issue now.
You can't use RECORD types in USING clause of EXECUTE IMMEDIATE statement. If you just want to pass a list of numbers, why don't you just use a variable of TABLE OF NUMBER type? Check below example:
CREATE TYPE num_tab_t IS TABLE OF NUMBER;
CREATE OR REPLACE PROCEDURE my_dyn_proc_test (p_num_array IN num_tab_t) AS
BEGIN
dbms_output.put_line(p_num_array.COUNT);
END;
/
DECLARE
v_tab num_tab_t := num_tab_t(1, 10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN my_dyn_proc_test(:1); END;' USING v_tab;
END;
Output:
2
Edit
Try this:
CREATE TYPE num_tab_t IS TABLE OF NUMBER;
CREATE OR REPLACE PACKAGE testproc AS
PROCEDURE my_dyn_proc_test (p_num_array IN num_tab_t);
END;
/
CREATE OR REPLACE PACKAGE BODY testproc AS
PROCEDURE my_dyn_proc_test (p_num_array IN num_tab_t) AS
BEGIN
dbms_output.put_line(p_num_array.COUNT);
END;
END;
/
DECLARE
v_tab num_tab_t := num_tab_t(1, 10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN testproc.my_dyn_proc_test(:1); END;' USING v_tab;
END;
Use an object type. object types are visible to all packages

Resources