create or replace package XXX_MWA_LOV_TEST AS
TYPE t_ref_csr IS REF CURSOR;
PROCEDURE XXX_USERS_LOV (p_user_name IN VARCHAR2,x_users OUT NOCOPY t_ref_csr);
end XXX_MWA_LOV_TEST;
How to run XXX_USERS_LOV procedure in SQL*Plus?
I tried this code but getting the syntax error:
SQL> EXECUTE XXX_MWA_LOV_TEST.XXX_USERS_LOV('%',:my_p_out);
Procedure body:
create or replace package body XXX_MWA_LOV_TEST AS
PROCEDURE XXX_USERS_LOV (x_users OUT NOCOPY t_ref_csr,p_user_name IN VARCHAR2) IS
BEGIN
OPEN x_users FOR select user_id,user_name,description
from fnd_user
where user_name like p_user_name;
DBMS_OUTPUT.PUT_LINE('TESTING DATA');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR IN USER LOV '|| SQLERRM);
END XXX_USERS_LOV;
end XXX_MWA_LOV_TEST;
First of all, the order of the parameters must be the same in the spec and in the package body.
You can call the ref cursor like this:
declare
v_cursor xxx_mwa_lov_test.t_ref_csr;
var1 the_type_you_need;
var2 the_type_you_need;
...
begin
xxx_mwa_lov_test.xxx_users_lov(v_cursor,'username...');
loop
fetch v_cursor into var1, var2...;
exit when v_cursor%notfound;
... do what you want with the vars...
end loop;
end;
/
Related
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;
/
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.
I have a problem with procedures in PL/SQL. I have a public procedure declared in a package and I want to call another procedure(private) inside the first one.
PROCEDURE show_notesforstudent (number_id IN number) as
...
DBMS_OUTPUT.PUT_LINE('The notes for the student with number_id X are: '|| Y);
DBMS_OUTPUT.PUT_LINE('here is the call for the private procedure');
erase_student(number_id);
END;
This code is a general example, my code is bigger and I can't put it all here. Here is only the main idea.
For this call I face this error: "Error(31,5): PLS-00313: 'erase_student' not declared in this scope".
The implementation of erase_student procedure is:
PROCEDURE erase_student(n_id students.number_id%type) AS
student_inexistent EXCEPTION;
PRAGMA EXCEPTION_INIT(student_inexistent, -20002);
counter integer;
BEGIN
SELECT COUNT(nmber_id) INTO counter FROM studens where number_id = n_id;
IF counter = 0 THEN
raise student_inexistent;
END IF;
DELETE FROM students WHERE number_id = n_id;
EXCEPTION
WHEN student_inexistent THEN
raise_application_error (-20002, 'Student with number_id' || n_id || ' doesn't exists in database');
END stergere_student;`
Lets simplify your code and make it syntactically correct:
CREATE OR REPLACE PACKAGE package_name
AS
PROCEDURE show_notesforstudent (number_id IN number);
END;
/
CREATE OR REPLACE PACKAGE BODY package_name
AS
PROCEDURE show_notesforstudent (number_id IN number)
AS
BEGIN
erase_student(number_id);
END;
PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END;
END;
/
However, it still won't compile as we get PLS-00313: 'ERASE_STUDENT' not declared in this scope. It can be fixed by re-organising the package to ensure that the private procedure is declared before it is called; like this:
CREATE OR REPLACE PACKAGE BODY package_name
AS
PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; -- Header and body
PROCEDURE show_notesforstudent (number_id IN number)
AS
BEGIN
erase_student(number_id);
END;
END;
/
However, if you want to keep the order of the procedures in the package then you could just use a forward declaration to declare the header for the private procedure before it is called and declare the body afterwards; like this:
CREATE OR REPLACE PACKAGE BODY package_name
AS
PROCEDURE erase_student(n_id NUMBER); -- Header only
PROCEDURE show_notesforstudent (number_id IN number)
AS
BEGIN
erase_student(number_id);
END;
PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; -- Header and body
END;
/
I wrote this code in pl/sql but I couldnt take answer.
create or replace function mostafa.sbs_Topic_LedgerBalance8Column
(BranchID number,DateFrom number,DateTo number)
RETURN SYS_REFCURSOR
IS O_RESULT SYS_REFCURSOR;
BEGIN
open O_RESULT for
Select s* From Mostafa.topic ;
RETURN O_RESULT;
end sbs_Topic_LedgerBalance8Column;
and I called it this way:
DECLARE v_refcursor SYS_REFCURSOR;
BEGIN
v_refcursor :=mostafa.sbs_topic_ledgerbalance8column(12,12,12);
FOR employee_rec IN v_refcursor
LOOP
DBMS_OUTPUT.put_line (
employee_rec.ID);
END LOOP;
end;
why did I get error when I retrieve result?
error is :v_refcursor is not a procedure or is undefined
When you are using a refcursor, you can't access it by using the cursor for loop. Use something like the following instead (Untested):
DECLARE
v_refcursor SYS_REFCURSOR;
v_emp_rec topic%ROWTYPE;
BEGIN
v_refcursor :=mostafa.sbs_topic_ledgerbalance8column(12,12,12);
LOOP
FETCH v_refcursor INTO v_emp_rec;
EXIT WHEN v_refcursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_rec.id);
END LOOP;
close v_refcursor;
END;
I have a package P and a precedure A in it.
create or replace package pkg_get_users_info_by_role
as
type user_info_ref_cur is ref cursor;
procedure get_user_info_proc
(p_role_name varchar2, p_user_info out user_info_ref_cur);
end pkg_get_users_info_by_role;
/
and the body;
create or replace package body pkg_get_users_info_by_role
as
procedure get_user_info_proc
(p_role_name varchar2, p_user_info out user_info_ref_cur)
as
begin
open p_user_info for
select user_id,username,user_password,role_name from user_info,role_info
where user_info.user_role=role_info.role_id
and role_info.role_name like p_role_name;
end;
end pkg_get_users_info_by_role;
My question is, how can I call the procedure? Do I need a variable of pkg_get_users_info_by_role.user_info_ref_cur type to call it? I cannot create a variable of this type. Is there any way to solve this?
Thanks!!
Yes, you simply define your cursor in your calling program as the package.type. Here's a simple-minded illustration that should work on most any oracle database:
CREATE OR REPLACE PACKAGE pkg AS
TYPE rc IS REF CURSOR;
PROCEDURE get_rc(p_rc OUT rc);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE get_rc(p_rc OUT rc) IS
BEGIN
OPEN p_rc FOR
SELECT t.owner, t.table_name FROM all_tables t;
END get_rc;
END pkg;
/
DECLARE
crsr pkg.rc;
v1 VARCHAR2(32);
v2 VARCHAR2(32);
BEGIN
pkg.get_rc(crsr);
LOOP
EXIT WHEN crsr%NOTFOUND;
FETCH crsr INTO v1, v2;
dbms_output.put_line(v1||': '||v2);
END LOOP;
CLOSE crsr;
END;
/