How to pass an array of values from Oracle Apex Page into Oracle stored procedure - oracle

I'm stuck with the passing Dates as an array parameters from the Oracle Apex page into package. Package contains one procedure with an array of type of dates. So what I want to do is to pass a simple dates into it from the Apex page, pl/sql block. Here is my code so far:
create or replace PACKAGE PK_NAME AS
TYPE DATES_ARRAY_TYPE IS VARRAY(100) OF DATE;
PROCEDURE PASS_DATES (
DATES DATES_ARRAY_TYPE
);
END PK_NAME;
create or replace PACKAGE BODY PK_NAME AS
PROCEDURE PASS_DATES (
DATES DATES_ARRAY_TYPE
) AS
BEGIN
for i in 1..DATES.count loop
HTP.P(DATES(i));
end loop;
END;
END PASS_DATES;
END PK_NAME;
Simple as that. And I call this procedure from the Apex page pl/sql block:
PK_NAME.PASS_DATES (
DATES => '15-JAN-15', '16-JAN-15', '17-JAN-15'
);
However, it doesn't work, every time I'm trying to save it, it gives me an error:
•ORA-06550: line 3, column 25: PLS-00312: a positional parameter association may not follow a named association ORA-06550: line 2, column 1: PL/SQL: Statement ignored
What is wrong with it or what have I missed ?

https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/05_colls.htm
you must init constructor DATES_ARRAY_TYPE()
i think it must look like this
create TYPE DATES_ARRAY_TYPE IS VARRAY(100) OF DATE;
create or replace procedure test_case( p_dates DATES_ARRAY_TYPE) is
begin
dbms_output.put_line(p_dates(1));
end;
declare
a DATES_ARRAY_TYPE;
begin
a := DATES_ARRAY_TYPE(sysdate, sysdate + 1,to_date('1.01.2016','dd.mm.yyyy'));
test_case(a);
end;
also if you want to use TYPE in PACKAGE PK_NAME (not global) you must use object like PK_NAME.DATES_ARRAY_TYPE in your code.
ok, lets go in your case:
1. create package and body:
https://gyazo.com/789b875ce47852e859c395c2021f9cd4
create or replace PACKAGE PCK AS
-- your type in pck
TYPE DATES_ARRAY_TYPE IS VARRAY(100) OF DATE;
procedure test_case(p_dates DATES_ARRAY_TYPE);
END PCK;
create or replace PACKAGE body PCK AS
procedure test_case(p_dates DATES_ARRAY_TYPE) IS
BEGIN
--here just raise second element in array for DEMO
raise_application_error('-20000',p_dates(2) );
END;
END PCK;
2.create page and button and after submit process:
https://gyazo.com/755f6e089db0a6a8ea058567d2b3384b
declare
asd PCK.DATES_ARRAY_TYPE := PCK.DATES_ARRAY_TYPE('31-JUL-15', '01-AUG-15', '02-AUG-13', '03-AUG-13');
begin
pck.test_case(asd);
end;
after button that submit page i get this:
https://gyazo.com/b894fc6b9b6dd28964ba2e6548244bc8

Related

Hi, I'm new to PL/SQL and I want to know how to add a variable type in a package

I want to know how is ROT_TMLN_ARRAY type added to a variable in sql developer. I see that ROT_TMLN_ARRAY is also a type and I want to create something similar with another variable.
create or replace PACKAGE BODY AS PKG TMLN
PROCEDURE SP TMLN SVC (
rotnPrngNb IN VARCHAR2
empiRotnDetails OUT ROT_TMLN ARRAY)
U can add the variable as a Type in both IN or OUT Parameter.
CREATE OR REPLACE PROCEDURE P_TMLN_SVC(I_ID IN NUMBER,
O_RESULT OUT T_TABLE)
AS
BEGIN
SELECT OWNER_TYPE BULK COLLECT INTO O_RESULT FROM OWNERES WHERE OWNERS_ID=I_ID;
END P_TMLN_SVC;
Calling Statement:
DECLARE
T_ARRAY T_TABLE;
BEGIN
P_TMLN_SVC(100,T_ARRAY);
END;

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

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;
/

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;

Call a Package from Apex passing two values

I'm using Oracle 11.g and Apex 4.2.
I have an Oracle package (body and spec) that works fine with a stub of test data. My next step is to call this package from an Apex screen. I'd like to pass in two variables:
mail_event_prim_key - a number
mail_list_name - a varchar2(1024)
I have two questions.
1) How do I construct the package to receive two IN-only values from Apex? No values need to be returned to Apex.
2) How do I call this from Apex. I assume I'd use a PL/SQL function to do so.
My current package spec is:
create or replace PACKAGE "PKG_MAIL_SEND" as
PROCEDURE proc_mail_send;
PROCEDURE proc_job_mail_send;
PROCEDURE proc_kill_job_mail;
end PKG__MAIL_SEND;
A portion of my package body is:
create or replace PACKAGE BODY "PKG_MAIL_SEND" as
PROCEDURE proc_parish_mail_send
is
mail_event_prim_key number;
mail_list_name varchar2(1024);
crlf varchar2(2) := CHR(10) || CHR(13);
l_html clob;
l_html_header varchar2(1024);
l_html_body clob;
l_html_footer varchar2(1024);
l_html_total clob;
l_addresses DBMS_SQL.varchar2_table;
l_from varchar2(1024);
l_to varchar2(2048);
l_subject varchar2(2048);
l_smtp_hostname varchar2(2048);
l_smtp_port varchar2(2048);
l_smtp_username varchar2(2048);
l_smtp_password varchar2(2048);
BEGIN
-- Initialize Variables
mail_event_prim_key := '1';
mail_list_name := 'My List Name';
Select lu_value into l_smtp_hostname from hymn_lookup where lu_type = 'smtp_hostname';
-- Lots more code here
End proc_mail_send;
-- Code for PROCEDURE proc_job_mail_send;
-- Code for PROCEDURE proc_kill_job_mail;
end PKG_MAIL_SEND;
Thanks for looking at this.
To receive 2 values in package you obviously need procedure with 2 parameters. For example for your package:
create or replace PACKAGE "PKG_MAIL_SEND" as
-- let this procedure have 2 parameters:
PROCEDURE proc_mail_send(p_address in varchar2, p_topic in varchar2);
PROCEDURE proc_job_mail_send;
PROCEDURE proc_kill_job_mail;
end PKG__MAIL_SEND;
First way
After that click on Create page (or Create region), select type Form, then Form on Procedure. Pass all steps of wizard. After that you will have a region with fields for every parameters of procedure and button to run procedure.
Second way
Create page process. Write in source of process anonymous block, call your procedure from that block (here you need to create manually all things that apex creates automatically in first way - process, items, buttons, etc.).
Third way
Call procedure from dynamic action (it is bit more harder way if you are new to APEX).
Forth way
Call using ajax (procedure will be called inside application process). It is the most hard way, it is used rarely.

Calling a stored PROCEDURE in Toad

I have a defined a new stored procedure but get a error while calling it,
CREATE OR REPLACE PROCEDURE SCOTT.getempsal(
p_emp_id IN NUMBER,
p_emp_month IN CHAR,
p_emp_sal OUT INTEGER)
AS
BEGIN
SELECT EMP_SAL
INTO p_emp_sal
FROM EMPLOYEE_SAL
WHERE EMP_ID = p_emp_id
AND EMP_MONTH = p_emp_month;
END getempsal;
And trying to call it:
getempsal(1,'JAN',OUT) --Invalid sql statement.
Your procedure contains an out parameter, so you need to call it in block like:
declare
a number;
begin
getempsal(1,'JAN',a);
dbms_output.put_line(a);
end;
A simple procedure (let's say with a number parameter) can be called with
exec proc(1);
or
begin
proc(1);
end;
Just write EXECUTE procedure_name('provide_the_valueof_IN parameter','value of in parameter', :k) ;
Run this statement a popup will come set the parameters as in out and the datatype too. U will see the output in another popup window.

Resources