How to run a complete package in oracle - oracle

create or replace package first_pckg IS
PROCEDURE print_name;
FUNCTION ret_eid return number;
END;
create or replace PACKAGE BODY FIRST_PCKG IS
ename employees.first_name%type;
eid employees.employee_id%type;
PROCEDURE print_name is
BEGIN
select first_name into ename from employees where employee_id=100;
dbms_output.put_line(ename);
END;
Function ret_eid return number is
BEGIN
select department_id into eid from employees where employee_id=100;
return eid;
END;
END;
We can execute procedures and functions in packages using execute first_pckg.print_name
can someone let me know how to execute entire package once?
Thank you

A package declares types, functions and procedures: It basically represents a repository of definitions and code. 'Executing' a package does not make much sense in general.
However, packages come with optional initialisation code which will be executed the first time a symbol from the package is referenced during a db session. In your example:
create or replace package first_pckg IS
PROCEDURE print_name;
-- ...
Function ret_eid return number is
BEGIN
select department_id into eid from employees where employee_id=100;
return eid;
END;
BEGIN
-- package init code goes here ...
END package;

Related

PL/SQL Package Cursor with custom return value (like in the procedure)

Is it possible to define a cursor with custom return value (columns from different tables..) ?
For example:
CREATE OR REPLACE PACKAGE pkg
IS
CURSOR emp_cur (id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg
IS
CURSOR emp_cur (id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE
IS
SELECT *
FROM employees
WHERE employee_id = id_in;
END;
/
This works because the employees is a single table.
In the procedure i can define cursor
CURSOR CUR_TEST ....
and the later
TYPE t_cur_test IS TABLE OF CUR_TEST %ROWTYPE INDEX BY BINARY_INTEGER;
var_t_cur_test t_cur_test ;
an it works.
In the package however with
CREATE OR REPLACE PACKAGE TEST
IS
-- Public types
CURSOR CUR_TEST
RETURN CUR_TEST%ROWTYPE;
i am getting -> 1/14 PLS-00304: cannot compile body of 'CUR_TEST' without its specification.
Is there any way to do this ?

Oracle 11g - Add query results to SYS_REFCURSOR in a LOOP

Currently, I'm working on creating a stored procedure that I can pass a list of strings to from my C# application using a DataReader. So part of it is also properly declaring that Associative Array so the stored procedure can accept the data.
Here is what I currently have (I'm not too concerned about the C# side of things at the moment):
CREATE OR REPLACE PACKAGE TEST_PACKAGE_01
AS
TYPE t_string_list is table of VARCHAR2(4000) index by pls_integer;
PROCEDURE SP_TEST_01(in_list IN t_string_list, out_cursor OUT SYS_REFCURSOR);
END TEST_PACKAGE_01;
/
CREATE OR REPLACE PACKAGE BODY TEST_PACKAGE_01
AS
PROCEDURE SP_TEST_01(in_list IN t_string_list, out_cursor OUT SYS_REFCURSOR)
IS
BEGIN
OPEN out_cursor;
FORALL indx IN 1..in_list.COUNT
-- I have tried numerous different things here with no success, this is just what I have in my latest iteration
INSERT INTO out_cursor Values (SELECT * FROM SOME_TABLE WHERE SOME_COLUMN = in_list(indx));
CLOSE out_cursor;
END SP_TEST_01;
END TEST_PACKAGE_01;
Within the body of the procedure, I managed to get it to return a SYS_REFCURSOR just fine, albeit just a test without any input. Something kind of like:
OPEN out_cursor FOR
SELECT * FROM SOME_TABLE;
I can't use a simple IN statement for the query against SOME_TABLE since in_list can potentially contain thousands of records. Ideally, I'd like to populate out_cursor with one statement, instead of performing a loop.
Cursors are pretty new territory for me, so maybe it isn't possible to do what I'm thinking with them, but I haven't seen anything to the contrary.
In 11g you can't access the PL/SQL table type from SQL, even if that SQL is within a PL/SQL block. You can create a schema-level type instead:
CREATE OR REPLACE TYPE t_string_list AS TABLE OF VARCHAR2(4000)
/
Then your package becomes:
CREATE OR REPLACE PACKAGE TEST_PACKAGE_01
AS
PROCEDURE SP_TEST_01(in_list IN t_string_list, out_cursor OUT SYS_REFCURSOR);
END TEST_PACKAGE_01;
/
CREATE OR REPLACE PACKAGE BODY TEST_PACKAGE_01
AS
PROCEDURE SP_TEST_01(in_list IN t_string_list, out_cursor OUT SYS_REFCURSOR)
IS
BEGIN
OPEN out_cursor FOR
SELECT *
FROM SOME_TABLE
WHERE SOME_COLUMN IN (
SELECT * FROM TABLE(in_list)
);
END SP_TEST_01;
END TEST_PACKAGE_01;
/
or with a join instead of IN:
CREATE OR REPLACE PACKAGE BODY TEST_PACKAGE_01
AS
PROCEDURE SP_TEST_01(in_list IN t_string_list, out_cursor OUT SYS_REFCURSOR)
IS
BEGIN
OPEN out_cursor FOR
SELECT st.*
FROM TABLE(in_list) t
JOIN SOME_TABLE st ON st.SOME_COLUMN = t.COLUMN_VALUE;
END SP_TEST_01;
END TEST_PACKAGE_01;
/
The TABLE() is a table collection expression.
db<>fiddle with made-up table and anonymous block to test.

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;

create package create package body record data type

i have an existing package named "fusion". The package definition goes like
create or replace package "fusion' as
create procedure first_procedure(abc in number)
create procedure second_procedure(efg in number)
end fusion;
The package body definition is like
create or replace package body fusion as
procedure first_procedure(abc in number) is
begin
....
end first_procedure;
procedure second_procedure(efg in number) is
begin
....
end second_procedure;
end fusion;
In this existing package i need to include a third procedure which has a custom record type as output. So where should i declare the custom record type? i have written like
create or replace package "fusion' as
type finalrecord is record(column1 varchar2,column2 number);
type mytable is table of finalrecord;
create procedure first_procedure(abc in number)
create procedure second_procedure(efg in number)
create procedure third_procedure(mt out mytable)
end fusion;
and package body as
create or replace package body fusion as
procedure first_procedure(abc in number) is
begin
....
end first_procedure;
procedure second_procedure(efg in number) is
begin
....
end second_procedure;
procedure third_procedure(mt out mytable) is
myissueid number(2);
begin
--do something
end third_procedure;
end fusion;
This is compiling in SQLDeveloper but showing these errors
subprogram or cursor 'third_procedure' is declared in a package specification and must be defined in the package body.
mytable should be declared
Try compiling the Procedure Specification with this update code
create or replace package fusion as
type finalrecord is record(column1 varchar2(20),column2 number);
type mytable is table of finalrecord;
procedure first_procedure(abc in number);
procedure second_procedure(efg in number);
procedure third_procedure(mt out mytable);
end fusion;
/

Find out name of PL/SQL procedure

Can PL/SQL procedure in Oracle know it's own name?
Let me explain:
CREATE OR REPLACE procedure some_procedure is
v_procedure_name varchar2(32);
begin
v_procedure_name := %%something%%;
end;
After %%something%% executes, variable v_procedure_name should contain 'SOME_PROCEDURE'. It is also OK if it contains object_id of that procedure, so I can look up name in all_objects.
Try:
v_procedure_name := $$PLSQL_UNIT;
There's also $$PLSQL_LINE if you want to know which line number you are on.
If you are pre-10g, you can 'dig' (parse) it out of
dbms_utility.format_call_stack
Procedures/functions in packages can be overloaded (and nested), so the package name/line number is normally better than the name.
In 10g and 11g I use the "owa_util.get_procedure" function. I normally use this in packages as it will also return the name of an internal procedure or function as part of the package name, i.e. (package_name).(procedure name). I use this to provide a generic EXCEPTION template for identifying where an exception occured.
CREATE OR REPLACE procedure some_procedure is
v_procedure_name varchar2(32);
begin
v_procedure_name := owa_util.get_procedure;
end;
CREATE OR REPLACE PACKAGE some_package
AS
FUNCTION v_function_name
RETURN DATE;
END;
/
CREATE OR REPLACE PACKAGE BODY some_package
AS
FUNCTION v_function_name
RETURN DATE
IS
BEGIN
RETURN SYSDATE;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR IN '||owa_util.get_procedure);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
END;
/
Here's a neat function that takes advantage of REGEXP_SUBSTR.
I've tested it in a package (and it even works if another procedure in the package calls it):
FUNCTION SET_PROC RETURN VARCHAR2 IS
BEGIN
RETURN NVL(REGEXP_SUBSTR(DBMS_UTILITY.FORMAT_CALL_STACK,
'procedure.+\.(.+)\s', 1,1,'i',1), 'UNDEFINED');
END SET_PROC;

Resources