Oracle stored procedure combine results - stored-procedures

I am working on the following Oracle (PL/SQL) stored procedure:
Procedure myProc(idParam IN Number, RESULT OUT SYS_REFCURSOR)
IS
BEGIN
FOR myMetaData in (select status, idData from Table1 where id=idParam)
LOOP
IF myMetaData.status='test1'
SELECT column1, column2, column3 from Table2 where cond1=cond2;
ELSE
SELECT column1, column2, column3 from Table2 where column4=
(select column4 from.....);
END IF;
END LOOP;
END myProc;
Assuming above is my code now I need to return combined results from both IF clause select statement and Else clause. I tried with dbms_sql.return_result(); but it didn't help.
How can I combine both result sets and return the value?

There are many ways to achieve your requirement however i would prefer to use a table to achieve your requirement. See below:
--Create a table to hold your result of if clause
Create table Rslt (col1 number,col2 number, col3 number);
/
--Use sysrefcursor to get the final result out of the table
Procedure myProc(idParam IN Number, RESULT OUT SYS_REFCURSOR)
IS
BEGIN
FOR myMetaData in (select status, idData from Table1 where id=idParam)
LOOP
IF myMetaData.status='test1'
insert into rslt SELECT column1, column2, column3 from Table2 where cond1=cond2;
ELSE
insert into rslt SELECT column1, column2, column3 from Table2 where column4=
(select column4 from.....);
END IF;
END LOOP;
Open result for select * from rslt;
END myProc;
Another apporach could be Object Oriented using a Object having table columns. See below:
Create type rslt is object
(col1 number,
col2 number,
col3 number
);
Create type var_rslt is table of rslt ;
Procedure myProc(idParam IN Number, V_RESULT OUT SYS_REFCURSOR)
IS
v_rslt1 var_rslt:=var_rslt();
v_rslt2 var_rslt:=var_rslt();
v_rslt3 var_rslt:=var_rslt();
v_rslt4 var_rslt:=var_rslt();
BEGIN
FOR myMetaData in (select status, idData from Table1 where id=idParam)
LOOP
IF myMetaData.status='test1'
SELECT rslt(column1, column2, column3) bulk collect into v_rslt1 from Table2 where cond1=cond2;
v_rslt2:=v_rslt2 Multiset union all v_rslt1;
ELSE
SELECT rslt(column1, column2, column3) bulk collect into v_rslt13 from Table2 where column4= (select column4 from.....);
v_rslt4:=v_rslt4 multiset union all v_rslt13;
END IF;
END LOOP;
v_rslt2 := v_rslt2 multiset union all v_rslt4;
OPEN V_RESULT FOR SELECT * FROM table( v_rslt2 );
END myProc;
Demo:
Table Preparation:
Create table Table1 (id number, status varchar2(10));
/
Insert into table1 values(1,'test1');
Insert into table1 values(2,'test2');
Create table Table2 (id number,column1 number, column2 number, column3 number);
/
insert into table2 values(1,10,20,30);
insert into table2 values(1,70,60,50);
insert into table2 values(1,20,40,30);
insert into table2 values(2,80,40,20);
insert into table2 values(2,60,20,10);
Create type rslt is object
(col1 number,
col2 number,
col3 number
);
Create type var_rslt is table of rslt ;
Procedure:
CREATE OR REPLACE Procedure myProc(idParam IN Number, V_RESULT OUT sys_refcursor)
IS
v_rslt1 var_rslt:=var_rslt();
v_rslt2 var_rslt:=var_rslt();
v_rslt3 var_rslt:=var_rslt();
v_rslt4 var_rslt:=var_rslt();
BEGIN
FOR myMetaData in (select status, id from Table1)
LOOP
IF myMetaData.status='test1' then
SELECT rslt(column1, column2, column3) bulk collect into v_rslt1 from Table2 where id=myMetaData.id;
v_rslt2:=v_rslt2 Multiset union all v_rslt1;
ELSE
SELECT rslt(column1, column2, column3) bulk collect into v_rslt3 from Table2 where id=myMetaData.id;
v_rslt4:=v_rslt4 multiset union all v_rslt3;
END IF;
END LOOP;
v_rslt4 := v_rslt4 multiset union all v_rslt2;
open V_RESULT for Select * from table(v_rslt4);
END myProc;
Execution:
DECLARE
var sys_refcursor;
var1 NUMBER;
var2 NUMBER;
var3 NUMBER;
BEGIN
myProc(1, var);
LOOP
FETCH var INTO var1,var2,var3;
EXIT WHEN var%notfound;
dbms_output.put_line(var1);
END LOOP;
END;
OUTPUT:
SQL> /
anonymous block completed
80
60
10
70
20
Note: This solution will work on Oracle 11g and onward versions. Incase you are working on lower version of Oracle, then you need to modify the Object definition as below:
Create type rslt is object
(col1 number,
col2 number,
col3 number,
map member function mem return number);
This is due to a bug in Oracle 10g while using MULTISET operator.
Read more about the bug at http://raajeshwaran.blogspot.com/2010/07/pls-00801-internal-error-assert-at-file.html

Related

stored procedure for inserting values of tables into another tables with automatic identifier as FK PGadmin4

I want to make an insert procedure for specific values of an table into another existing table.
The dificulty is that my excisting table has automatic identifiers as fk of another table.
When I insert them individually, I use a look up function. But now I don't known in PGadmin how to put this in a procedure. In oarcle I can use collections but in pgadmin I can't figure it out.
my tables:
CREATE TABLE public.field (field_id INT GENERATED BY DEFAULT AS IDENTITY
CONSTRAINT pk_veld_id PRIMARY KEY,
object_number INT,
experiment_number INT,
repetition INT,
plants_field INT,
stem_field INT,
plants_square_meter numeric,
stem_square_meter_start numeric,
stem_square_meter_end numeric,
date_extra_stem date,
row_number_field INT);
CREATE TABLE public.sticky_plates_fields (ID_sticky_plate INT GENERATED BY DEFAULT AS IDENTITY
CONSTRAINT pk_sticky_plate_id PRIMARY KEY,
sticky_plate_number INT,
brand_sticky_plate varchar,
version_plate numeric,
field_id INT constraint fk_sticky_plates_fields references field );
ALTER TABLE IF EXISTS public.sticky_plates_fields
ADD CONSTRAINT sticky_plates_fields_unique UNIQUE (sticky_plate_number, field_id);
DROP TABLE IF EXISTS public.make_sticky_plate_counts CASCADE;
CREATE TABLE public.make_sticky_plate_counts (
experiment_number INT,
object_number INT,
repetition INT,
sticky_plate_number INT,
brand_sticky_plate varchar,
version_plate numeric,
date_start date,
date_count date,
species varchar,
stage varchar,
count_species INT);
look_up _function:
CREATE OR REPLACE FUNCTION project.lookup_field_id
(p_objectnumber INT,
p_experimentnumber INT,
p_repetition INT)
RETURNS integer
LANGUAGE 'plpgsql'
AS
$BODY$
DECLARE
ln_field_id integer;
BEGIN
SELECT field_id INTO ln_field_id
FROM field
WHERE p_objectnumber = object_number AND p_experimentnumber = experiment_number AND p_repetition = repetition;
RETURN ln_field_id;
END;
$BODY$;
values:
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (1,4072022,1,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),10);
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (1,4072022,2,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),15);
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (1,4072022,3,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),20);
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (1,4072022,4,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),25);
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (2,4072022,1,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),10);
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (2,4072022,2,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),15);
insert into public.field(object_number,experiment_number,repetition,stem_field,stem_square_meter_start,stem_square_meter_end,date_extra_stem,row_number_field)
values (2,4072022,3,20,2.5,3.3,TO_DATE('1-04-2022','DD-MM-YYYY'),20);
insert into public.sticky_plates_fields(sticky_plate_number,brand_sticky_plate,version_plate,field_id)
values(2,'BIOBEST',3,project.lookup_field_id(1,4072022,2));
insert into public.sticky_plates_fields(sticky_plate_number,brand_sticky_plate,version_plate,field_id)
values(1,'BIOBEST',3,project.lookup_field_id(1,4072022,1));
insert into public.sticky_plates_fields(sticky_plate_number,brand_sticky_plate,version_plate,field_id)
values(3,'BIOBEST',3,project.lookup_field_id(1,4072022,3));
insert into public.sticky_plates_fields(sticky_plate_number,brand_sticky_plate,version_plate,field_id)
values(4,'BIOBEST',3,project.lookup_field_id(1,4072022,4));
insert into public.make_sticky_plate_counts(experiment_number,object_number,repetition,sticky_plate_number,brand_sticky_plate,version_plate,date_start,date_count,species,stage,count_species)
values(4072022,2,1,6,'BIOBEST',2.1,TO_DATE('1-04-2022','DD-MM-YYYY'),TO_DATE('14-04-2022','DD-MM-YYYY'),'WHITE_FLY_T','ADULT',12) ;
insert into public.make_sticky_plate_counts(experiment_number,object_number,repetition,sticky_plate_number,brand_sticky_plate,version_plate,date_start,date_count,species,stage,count_species)
values(4072022,2,2,7,'BIOBEST',2.1,TO_DATE('1-04-2022','DD-MM-YYYY'),TO_DATE('14-04-2022','DD-MM-YYYY'),'WHITE_FLY_T','ADULT',12) ;
insert into public.make_sticky_plate_counts(experiment_number,object_number,repetition,sticky_plate_number,brand_sticky_plate,version_plate,date_start,date_count,species,stage,count_species)
values(4072022,2,3,8,'BIOBEST',2.1,TO_DATE('1-04-2022','DD-MM-YYYY'),TO_DATE('14-04-2022','DD-MM-YYYY'),'WHITE_FLY_T','ADULT',12) ;
insert into public.make_sticky_plate_counts(experiment_number,object_number,repetition,sticky_plate_number,brand_sticky_plate,version_plate,date_start,date_count,species,stage,count_species)
values(4072022,2,4,9,'BIOBEST',2.1,TO_DATE('1-04-2022','DD-MM-YYYY'),TO_DATE('14-04-2022','DD-MM-YYYY'),'WHITE_FLY_T','ADULT',12) ;
try out of stored procedure
Here I want some values of table make_sticky_plate_counts to insert into table sticky_plates_fields.
I don't know how I can make a procedure to insert the whole (distinct table) winto the sticky plate field table and using the look up function for finding the related FK integer.
CREATE OR REPLACE PROCEDURE insert_records
() LANGUAGE 'plpgsql'
AS
$BODY$
DECLARE
p_object_number INT;
p_experiment_number INT;
p_r_epetitition INT;
p_sticky_plate_number INT;
p_brand_sticky_plate VARCHAR;
p_version_plate VARCHAR;
max_rownumbers_insert INT := 0;
BEGIN
max_rownumbers_insert := SELECT COUNT(*) FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp;
FOR i IN 1..max_rownumbers_insert
LOOP
p_object_number := SELECT object_number [i] FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp ;
p_experiment_number := SELECT experiment_number [i] FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp ;
p_repetitition:= SELECT repetitition [i] FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp ;
p_sticky_plate_number:=SELECT sticky_plate_number [i] FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp);
p_brand_sticky_plate :=SELECT brand_sticky_plate [i] FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp);
p_version_plate :=SELECT version_plate [i] FROM (SELECT DISTINCT object_number,experiment_number,repetition FROM make_sticky_plate_counts) as temp);
INSERT INTO sticky_plate_fields(field_id, sticky_plate_number, brand_sticky_plate,version_plate)
VALUES (project.lookup_field_id(p_object_number,p_experiment_number,p_repetition),p_sticky_plate_number,p_brand_sticky_plate,p_version_plate);
END LOOP; ```
I could figure it out. Maybe it is helpfull for someone else:
CREATE OR REPLACE PROCEDURE insert_records
() LANGUAGE 'plpgsql'
AS
$BODY$
DECLARE
curs cursor for select * FROM (SELECT DISTINCT object_number,experiment_number,repetition,sticky_plate_number,brand_sticky_plate,version_plate FROM make_sticky_plate_counts) as temp;
BEGIN
FOR row IN curs LOOP
INSERT INTO sticky_plates_fields(field_id, sticky_plate_number, brand_sticky_plate,version_plate)
VALUES (project.lookup_field_id(row.object_number,row.experiment_number,row.repetition),row.sticky_plate_number,row.brand_sticky_plate,row.version_plate);
END LOOP;
END ;
$BODY$;

update a column inside a stored procedure

I have two snowflake tables as below
TEST1
create OR REPLACE table TEST1 (
id varchar(100),
name varchar(100),
org VARCHAR(64)
);
INSERT INTO TEST1 values (100, 'ABC', null);
INSERT INTO TEST1 values (200, 'XYZ', null);
INSERT INTO TEST1 values (300, 'VBN', null);
CONTROL
create OR REPLACE table CONTROL (
KEY_COLUMNS VARCHAR,
TABLE_NAME VARCHAR,
org VARCHAR
);
INSERT INTO CONTROL values ('id,name, address','TEST1','Z');
INSERT INTO CONTROL values ('id,name, address','TEST2','T');
I have created a stored procedure which updates column 'org' in TEST1 table with the values from CONTROL table (column org) where table name is TEST1.
CREATE OR REPLACE PROCEDURE TEST(source_tbl VARCHAR)
RETURNS string
LANGUAGE SQL
AS
$$
DECLARE
query1 STRING;
BEGIN
QUERY1 := 'update TEST1 set ORG = (select org from CONTROL WHERE TABLE_NAME = ''source_tbl'');';
EXECUTE IMMEDIATE :QUERY1;
RETURN :QUERY1;
END;
$$;
call TEST((select TABLE_NAME from CONTROL WHERE TABLE_NAME = 'TEST1'));
expected output
My output
The parameter should be bound variable instead of passing as the string constant ''source_tbl'':
CREATE OR REPLACE PROCEDURE TEST(source_tbl VARCHAR)
RETURNS string
LANGUAGE SQL
AS
$$
DECLARE
query1 STRING;
BEGIN
QUERY1 := 'update TEST1 set ORG = (select org from CONTROL WHERE TABLE_NAME = ?);';
EXECUTE IMMEDIATE :QUERY1 USING (SOURCE_TBL);
RETURN :QUERY1;
END;
$$
Related: EXECUTE IMMEDIATE:
EXECUTE IMMEDIATE '<string_literal>'
[ USING (bind_variable_1 [, bind_variable_2 ...] ) ] ;

Dynamic Insert through Teradata Stored procedure

I am trying to run Insert statement to load data into table using Teradata Stored procedure. Here I am trying to Input Table Name, Databasename as Parameter. My stored procedure compiled and ran well. But its not inserting any data into table. Could someone please help me with this. Below is the query I am using..
REPLACE PROCEDURE DB.TEST_SP
(
IN SRC_DB_NM VARCHAR(30)
, IN SRC_TBL_NM VARCHAR(30)
, OUT MESSAGE VARCHAR(200)
)
DYNAMIC RESULT SETS 1
BEGIN
DECLARE QUERY1 VARCHAR(200);
DECLARE RESULT1 VARCHAR(200);
DECLARE REC_COUNT INTEGER DEFAULT 0;
DECLARE STATUS CHAR(10) DEFAULT '00000';
DECLARE C1 CURSOR FOR S1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION,SQLWARNING
BEGIN
SET STATUS = SQLCODE;
IF(TRIM(STATUS)) = '3807' THEN
SET MESSAGE = 'PASSED TABLE '||SRC_DB_NM||'.'||SRC_TBL_NM||' DOES NOT EXIST';
ELSE
SET MESSAGE = 'LOADED';
END IF;
END;
BEGIN
SET QUERY1 ='INSERT INTO TABLE1 SELECT ColX , count(*) from DB.table2 where Col in ( SELECT Col1 FROM ' || SRC_DB_NM || '.' || SRC_TBL_NM || ' where ColY = 999 ) group by 1;' ;
EXECUTE IMMEDIATE QUERY1;
PREPARE S1 FROM QUERY1;
OPEN C1 USING SRC_DB_NM,SRC_TBL_NM;
FETCH C1 INTO RESULT1;
SET MESSAGE = RESULT1;
END;
END;

DB2 - how to call a stored procedure that returns a result set in another user defined table function

I have a db2 stored procedure that takes in some parameters, gets some data from somewhere and then returns a result set through a cursor.
Now I want to write a table function in db2, that will call this stored procedure, read from the result set and return the data in the result set as a table (eventually I want to use this table function in a join).
I would like to know if this is permitted in db2 (we're using DB2 v10.5), i.e. execute a stored procedure in a table function and fetch and read from the result set from the stored procedure. If so, what is the right syntax for calling the stored procedure and reading the result set inside a table function in db2? Thanks!
Yes, it's possible. See the example below.
--#SET TERMINATOR #
CREATE OR REPLACE PROCEDURE TEST_PROC(P_TABSCHEMA VARCHAR(128))
DYNAMIC RESULT SETS 1
READS SQL DATA
BEGIN
DECLARE C1 CURSOR WITH HOLD WITH RETURN FOR
SELECT TABSCHEMA, TABNAME, COLCOUNT
FROM SYSCAT.TABLES
WHERE TABSCHEMA=P_TABSCHEMA;
OPEN C1;
END#
--CALL TEST_PROC('SYSCAT')#
CREATE OR REPLACE FUNCTION TEST_PROC(P_TABSCHEMA VARCHAR(128))
RETURNS TABLE (
TABSCHEMA VARCHAR(128)
, TABNAME VARCHAR(128)
, COLCOUNT INT
)
READS SQL DATA
BEGIN
DECLARE SQLSTATE CHAR(5);
DECLARE V_TABSCHEMA VARCHAR(128);
DECLARE V_TABNAME VARCHAR(128);
DECLARE V_COLCOUNT INT;
DECLARE V1 RESULT_SET_LOCATOR VARYING;
CALL TEST_PROC(P_TABSCHEMA);
ASSOCIATE RESULT SET LOCATOR (V1) WITH PROCEDURE TEST_PROC;
ALLOCATE C1 CURSOR FOR RESULT SET V1;
L1: LOOP
FETCH C1 INTO V_TABSCHEMA, V_TABNAME, V_COLCOUNT;
IF SQLSTATE<>'00000' THEN LEAVE L1; END IF;
PIPE(V_TABSCHEMA, V_TABNAME, V_COLCOUNT);
END LOOP L1;
CLOSE C1;
RETURN;
END#
SELECT * FROM TABLE(TEST_PROC('SYSCAT'))#
You need to create the DB2 table-function as follows:
CREATE FUNCTION database_schema.function_name ( IN_PARTID VARCHAR(1000) )
RETURNS TABLE ( PARTNO CHAR(25), PARTDS CHAR(30), QUANTITY INT )
BEGIN
RETURN SELECT PARTNO , PARTDS , CASE WHEN QUANTITY > 0 THEN QUANTITY ELSE 0 END QUANTITY
FROM
(
SELECT PARTNO
,MAX(PARTDS) AS PARTDS
,SUM(QUANTITY) AS QUANTITY
FROM database_schema.table_name
WHERE 1=1
AND PARTID = (CAST(IN_PARTID AS INT))
GROUP BY PARTNO
) AA;
END;
Then invoke the table-function as join or straight SQL:
SELECT partno,partds,quantity
FROM TABLE(database_schema.function_name('parameter_1'))

function or stored procedure for bulk insert in table by sets

how can i convert the following to teradata stored procedure or some function :
WHILE EXISTS (SELECT * FROM #temp_set1)
BEGIN
/*group of statemnts :delete insert etc
like */
INSERT INTO #temp_set
SELECT TOP 200 * FROM #temp_set1;
INSERT INTO Activepull
as select * from #temp_set1
and this should occur for each set of 200 untill all inserts
end;
There are more than 60000 rows in #temp_set1 so want to insert by sets.
Thanks.
Written on my phone, but I would use the over expression. It creates a kind of pseudo Identity column that you can then use to paginate. And you can even choose the order based on an order by clause.
Declare #IntervalSize int = 100
Declare #BeginSet int = 0,
#EndSet int = #IntervalSize
While #Counter < (Select Max(ROW_NUMBER() OVER (ORDER BY someColumn desc) From #temp_set1)
Begin
Insert Into #temp_set
Select *, Row_Number() Over (Order By someColumn desc) As MyIdentity
Where MyIdentity Between #BeginSet And #EndSet
Select #BeginSet = #BeginSet + #IntervalSize,
#EndSet = #EndSet + #IntervalSize
End

Resources