How to define array/collection in stored procedure? - sql

I have a fixed array of strings on which I want to operate. How should I declare them in stored procedure? Is it even possible?
CREATE OR REPLACE PROCEDURE testing AS
BEGIN
operations...
END;
Can we declare like DECLARE #v1 varchar(15); or something similar for collection of string?(PS "#" throwing error on Oracle SQL Developer )
A newbie in SQL, so expecting a sample code if possible thanks.

You can use this:
declare
type array_t is varray(3) of varchar2(2);
array array_t := array_t('aa', 'bb', 'cc');
begin
for i in 1..array.count loop
dbms_output.put_line(array(i));
end loop;
end;

Related

Oracle PL/SQL: how to execute a procedure with a varray as out parameter?

I'm writing a stored procedure that will receive a code and return one or more VARCHAR2 values. The number of values will vary according to the code the procedure receives.
I don't know if this is the best approach (needless to say I'm a beginner), but I created a user-defined type and a table to store these values.
create or replace type t_desc as varray(15) of varchar2(15);
create table all_values(code int, list t_desc);
insert into all_values values (0, t_desc('a','b','c','d'));
insert into all_values values (1, t_desc('a','b'));
Then, I wrote the procedure as follows:
create or replace procedure teste(v_code int, v_list out t_list) is
begin
select list into v_list from all_values where code = v_code;
end;
This is where I'm stuck. How should this procedure be executed to return the values I've stored in the list column?
you have to declare a variable and pass it in you proc.
declare
t t_desc ;
i int;
begin
teste(i, t);
end;
to see the results you can itarate through your varray:
FOR x IN 1..t.COUNT LOOP
dbms_output.put_line(t(x));
END LOOP;

What is this doing? Listing variables without declaring them?

This is my code:
--this section creates/replaces the C_PND Procedure
--and passes 2variables
create or replace PROCEDURE C_PND
(
p_whse in varchar2,
p_RC OUT INT
)
--No clue what we're doing here as there is no DECLARE
as
cv SYS_REFCURSOR; -- cursor variable
v_pull_zone locn_hdr.pull_zone%TYPE;
v_active varchar2(1);
v_low_wm number(3);
v_high_wm number(3);
v_lock_code resv_locn_hdr.locn_putaway_lock%TYPE;
--initializes this variable
BEGIN
p_RC := 0;
--setting values of the the CV
OPEN cv FOR
select code_id,
nvl(trim(substr(sc.misc_flags,1,1)),'N') v_active,
nvl(trim(substr(sc.misc_flags,2,3)),'100') high_wm,
nvl(trim(substr(sc.misc_flags,5,3)),'0') low_wm,
trim(substr(sc.misc_flags,8,2)) lock_code
from sys_code sc
where sc.rec_type = 'C'
and sc.code_type = 'PND';
--inputting the CV into these variables
LOOP
FETCH cv INTO v_pull_zone, v_active, v_high_wm, v_low_wm, v_lock_code;
EXIT WHEN cv%NOTFOUND;
............
............
............
I think I understand most of it but my problem comes in with the five lines after the as (lines 6-11 of code snippet). I'm under the impression that anytime you use variables in PL SQL you have to DECLARE them. Even if you are using cursor variables.
Am I simply wrong about that? Or is there no need to DECLARE variables in use with CVs? I also included some comments (prefaced by --) that show what I think what the SQL is doing.
You are sort of right. You have to declare variables using DECLARE in an anonymous block as in:
DECLARE
...
BEGIN
...
END;
Your code is a procedure and the DECLARE is implicit after the
CREATE OR REPLACE xxx as
(implicit DECLARE)
BEGIN
...
END;

Inserting multipe values in PL/SQL

I am trying to insert values into a table using a for loop. I can't understand why it isnt working. I am a beginner. Any help would be appreciated.
create or replace procedure valueinput
as i number;
begin
for i in 1..10
loop
man_id number:=&Manager_Id;
man_fname varchar2(100):=&First_Name;
man_lname varchar2(100):=&Last_Name;
emp_id number:=&Employee_ID_Managed;
insert into managerinfo
values (man_id,man_fname,man_lname,emp_id);
i:=i+1;
end loop;
end;
You must declare your variables in the DECLARATION section of your PL/SQL block, right now you're trying to do it in the EXECUTION section.
Also, for a PL/SQL FOR..IN loop, you don't need to declare or increment your index.
Try something like this-
create or replace procedure valueinput
as
man_id number;
man_fname varchar2(100);
man_lname varchar2(100);
emp_id number;
begin
for i in 1..10
loop
man_id :=&Manager_Id;
man_fname :=&First_Name;
man_lname :=&Last_Name;
emp_id :=&Employee_ID_Managed;
insert into managerinfo
values (man_id,man_fname,man_lname,emp_id);
end loop;
end;
It would also be best practice to declare your variable types as the same as the table column that you're inserting into.
For example-
man_id managerinfo.manager_id%TYPE;

Sending multiple sets of parameters to procedure

I'm using vb.net and oracle db, and currently I have a stored-procedure that is called from my code. Right now it looks similar to this:
CREATE OR REPLACE PROCEDURE MYPROCEDURE(
param1 table.field1%TYPE,
param2 table.field2%TYPE,
param3 table.field3%TYPE,
param4 varchar2,
output OUT number) AS
BEGIN
DO STUFF
END;
I want to ask if it is possible to change this to send multiple sets of parameters at once, so I could use a FOR LOOP inside my procedure to minimize the number of calls. I want to achieve something like this:
CREATE OR REPLACE PROCEDURE MYPROCEDURE(
param myArray
output OUT number) AS
BEGIN
FOR i IN 1..myArray.COUNT LOOP
UPDATE FIELD FROM TABLE WHERE ID = myArray(i).field1;
END LOOP;
END;
Or if there's anything else that would work the same it would be great.
Many thanks.
Yes you can pass a list of objects as parameter in oracle procedure. First you must create the datatype of this list of objects, but you can't do this inside a procedure you have to define it as an oracle object. For example:
CREATE OR REPLACE TYPE TEST."MY_TYPE" AS OBJECT
(PARAM1 VARCHAR (20), PARAM2 NUMBER);
Unfortunately you can define dynamic datatypes inside objects (table.field1%TYPE), but I think you know what datatype this field have.
Second, create a package that have the list of parameter and procedure definition like this:
CREATE OR REPLACE PACKAGE ARRAY_EXAMPLE2
AS
TYPE COL IS TABLE OF MY_TYPE;
PROCEDURE PROCESS_ARRAY (ArrayIn IN COL);
END;
And finally the package implementation
CREATE OR REPLACE PACKAGE BODY ARRAY_EXAMPLE2
AS
PROCEDURE PROCESS_ARRAY (ArrayIn IN COL)
IS
BEGIN
FOR i IN 1 .. ArrayIn.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE ('Hello ' || ArrayIn (i).PARAM1);
END LOOP;
END;
END;
You can try it using this lines of code:
BEGIN
ARRAY_EXAMPLE2.
PROCESS_ARRAY (
array_example2.
COL (MY_TYPE ('Peter', 12),
MY_TYPE ('Jorge', 4),
MY_TYPE ('Bryan', 5)));
END;

How do I return a SYS_REFCURSOR from a stored procedure after a loop?

I am a bit new to Oracle and PL SQL. I have a procedure like the following.
{
CREATE OR REPLACE PROCEDURE MyProcedure (MyRecordset OUT SYS_REFCURSOR)
AS
BEGIN
DECLARE
CURSOR MyRecordset IS
select
...
from table1, table2, etc..
BEGIN
FOR Record in MyRecordset
LOOP
--Do something
END LOOP; -- IMPLICIT CLOSE OCCURS
-- THIS IS WHERE I NEED TO RETURN THE CURSOR. DOES THIS NOT OPEN IT AT BEGINNING AGAIN?
OPEN MyRecordset;
END;
END MyProcedure;
/
}
I need to return a SYS_REFCURSOR. Is this sufficient? When I try to test it with the following in Toad I get no output in the data grid.
{
DECLARE
type result_set is ref cursor;
BEGIN
BIZTALK.GetCustomerPaymentsDebug(:result_set);
END;
}
This example works for me. I think it should help you.
Declare cursor like:
TYPE genCurType IS REF CURSOR;
PROCEDURE return_in
( p_ime IN VARCHAR2
, po_seznam OUT genCurType
, po_errid OUT errorIdType
, po_errmsg OUT errorMsgType
)
IS
cc_module_name CONSTANT VARCHAR2(60):= 'return_ins';
BEGIN
OPEN po_seznam FOR SELECT IME, OPIS, NAZIV, OBRAZEC
FROM test
WHERE upper(IME) = upper(p_ime);
EXCEPTION
WHEN OTHERS THEN
po_errid := SQLCODE;
po_errmsg := 'Poizvedba ni bila uspešna! ('||SQLERRM||''||gc_package||'.'||cc_module_name||')';
END;