DB2 - Declare Cursor in Stored Procedure - stored-procedures

I've found this "DECLARE CURSOR" Statement on WWW:
CREATE OR REPLACE PROCEDURE "APART21C"."FIND_VALID_ARZTNRN"
(OUT NoOfRows BIGINT)
RESULT SETS 1
LANGUAGE SQL
SPECIFIC SQL140905135133600
BEGIN
DECLARE myARZTNR CHAR(7);
DECLARE END_TABLE INT DEFAULT 0
;
DELETE FROM APART21C.TMP_LANR07_CHECK
;
DECLARE C1 CURSOR FOR
SELECT DISTINCT Arztnr
FROM APART21C.DMP_LEV_TMP
;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1
;
OPEN C1
;
FETCH C1 INTO myARZTNR
;
WHILE END_TABLE = 0 DO
INSERT INTO APART21C.TMP_LANR07_CHECK
SELECT * FROM TABLE(APART21C.CHECK_ARZTNR_BY_CHECKSUM(myARZTNR)) AS ARZTNRCHECK;
SET NoOfRows = NoOfRows + 1;
FETCH C1 INTO myARZTNR;
END WHILE
;
CLOSE C1
;
END
Errormessage is
"DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=<cursor declaration>;;<SQL statement>"
Need your help, please
I'm a beginner of db2, I've more experience in MS SQL Server.
The statement "SELECT * FROM TABLE(..." calls a function which returns a table.

Problem with the below code
DECLARE C1 CURSOR FOR
SELECT DISTINCT Arztnr
FROM APART21C.DMP_LEV_TMP
I have changed as below and it executed
DECLARE C1 CURSOR WITH HOLD FOR
SELECT Arztnr FROM DMP_LEV_TMP;

Related

How to use cursor results in a query in stored procedure

I am trying to get the variable (ACTIVE_INVENTORY) value from sql query dynamically and use it in further below queries. But it seems to be giving error.
Please suggest how could a variable be used in following query.
Thanks
create or replace procedure sp()
returns table (vin varchar, listing_date date, sale_date date, active_inventory boolean)
language sql
as
$$
declare
select_query varchar;
SOLD_THRESHOLD_DATE date;
c1 cursor for select max(sale_date) from TBL;
res resultset;
begin
open c1;
fetch c1 into SOLD_THRESHOLD_DATE;
select_query := 'select vin,listing_date,sale_date,
case when 60 >= DATEDIFF(Day,sale_date,SOLD_THRESHOLD_DATE) then 1 else 0 end as active_inventory from
TBL limit 10';
res:= (execute immediate : select_query);
close c1;
return table(res);
end;
$$;
call sp();
Uncaught exception of type 'STATEMENT_ERROR' on line 13 at position 9 : SQL compilation error: error line 2 at position 41 invalid identifier 'SOLD_THRESHOLD_DATE'
Parametrizing the query:
select_query := 'select vin,listing_date,sale_date,
case when 60>=DATEDIFF(Day,sale_date,?) then 1 else 0 end as active_inventory
from TBL limit 10';
res:= (execute immediate :select_query using (SOLD_THRESHOLD_DATE) );

Error -206 creating Interbase stored procedure

I am attempting to create a stored procedure using an IBConsole interactive SQL window. The intent of the procedure is to gather data from two tables, do some processing on that data, insert rows containing that data into a working table, then return the rows from the working table as the stored procedure result. The stored procedure:
SET TERM ^;
CREATE PROCEDURE BIBLIO_SUBJECT
RETURNS (ID INTEGER, SUBJECT VARCHAR(200))
AS
DECLARE VARIABLE CUR_SUBJECT VARCHAR(200);
DECLARE VARIABLE SUBJECT_LIST VARCHAR(500);
DECLARE VARIABLE BIBLIOID INTEGER;
DECLARE VARIABLE NEXTPOS INTEGER;
BEGIN
DELETE FROM TSUBJECTS;
FOR SELECT BIBLIO.ID, BIBLIO.SUBJECTS
FROM BIBLIO
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :SUBJECT_LIST
DO
BEGIN
SUBJECT_LIST = BIBLIO.SUBJECTS + ';';
NEXTPOS = LOCATE(";", SUBJECT_LIST);
WHILE (:NEXTPOS > 1) DO
BEGIN
CUR_SUBJECT = SUBSTR(:SUBJECT_LIST, 1, NEXTPOS - 1);
SUBJECT_LIST = SUBSTR(:SUBJECT_LIST, NEXTPOS + 1, STRLEN(SUBJECT_LIST));
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
NEXTPOS = LOCATE(";", SUBJECT_LIST);
END
END
FOR SELECT BIBLIO_BEAST.BIBLIO_ID, BEAST.BEAST_NAME
FROM BIBLIO_BEAST
INNER JOIN BEAST ON (BEAST.ID = BIBLIO_BEAST.BEAST_ID)
INNER JOIN BIBLIO ON (BIBLIO.ID = BIBLIO_BEAST.BIBLIO_ID)
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :CUR_SUBJECT
DO
BEGIN
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
END
FOR SELECT ID, SUBJECT
FROM TSUBJECTS
INTO :ID, :SUBJECT
DO
SUSPEND;
END^
SET TERM ;^
When I execute the above code in IBConsole I get the error:
Error at line 2
Dynamic SQL Error
SQL error code = -206
Column unknown
SQL - CREATE PROCEDURE BIBLIO_SUBJECT
RETURNS (ID INTEGER, SUBJECT VARCHAR(200))
AS
DECLARE VARIABLE CUR_SUBJECT VARCHAR(200);
DECLARE VARIABLE SUBJECT_LIST VARCHAR(500);
DECLARE VARIABLE BIBLIOID INTEGER;
DECLARE VARIABLE NEXTPOS INTEGER;
BEGIN
DELETE FROM TSUBJECTS;
FOR SELECT BIBLIO.ID, BIBLIO.SUBJECTS
FROM BIBLIO
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :SUBJECT_LIST
DO
BEGIN
SUBJECT_LIST = BIBLIO.SUBJECTS + ';';
NEXTPOS = LOCATE(";", SUBJECT_LIST);
WHILE (:NEXTPOS > 1) DO
BEGIN
CUR_SUBJECT = SUBSTR(:SUBJECT_LIST, 1, NEXTPOS - 1);
SUBJECT_LIST = SUBSTR(:SUBJECT_LIST, NEXTPOS + 1, STRLEN(SUBJECT_LIST));
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
NEXTPOS = LOCATE(";", SUBJECT_LIST);
END
END
FOR SELECT BIBLIO_BEAST.BIBLIO_ID, BEAST.BEAST_NAME
FROM BIBLIO_BEAST
INNER JOIN BEAST ON (BEAST.ID = BIBLIO_BEAST.BEAST_ID)
INNER JOIN BIBLIO ON (BIBLIO.ID = BIBLIO_BEAST.BIBLIO_ID)
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :CUR_SUBJECT
DO
BEGIN
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
END
FOR SELECT ID, SUBJECT
FROM TSUBJECTS
INTO :ID, :SUBJECT
DO
SUSPEND;
END
It doesn't say which column is "unknown", and line 2 is (apparently) the RETURNS clause of the CREATE PROCEDURE. Not at all helpful.
Each of the SQL statements in the stored procedure (3 SELECTs, a DELETE, 2 INSERTs) work without error if executed separately in an Interactive SQL window, so all of their columns are "known". BIBLIO_SUBJECT is not the name of an existing stored procedure, nor is it the name of an existing table, or anything else in the database.
This has me baffled. Online searches provide no answer. So I am hoping the clever Stack Overflow people can help me get this working.
David
Well, I figured it out. It was the statement:
SUBJECT_LIST = BIBLIO.SUBJECTS + ';';
The SUBJECT_LIST variable is already used in the preceding select. A silly mistake, but I am old.
Not that it matters since the Interbase UDF functions Locate() and Substr() can only handle 80 character strings, which makes them really useless to me... and probably useless to most.

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'))

Firebird stored procedure always returning zero

This is my stored procedure:
SET TERM ^ ;
CREATE PROCEDURE INSERT_ETYPE (
E_ID Integer,
E_NAME Varchar(20) CHARACTER SET NONE )
RETURNS (
NEW_ID Integer)
AS
declare variable addr varchar(20);
declare variable type smallint;
declare variable ord smallint;
declare variable cmd varchar(255);
declare variable answr varchar(255);
begin
insert into ETYPE
select * from ETYPE where ID=:e_id;
select max(ID) from ETYPE into :new_id;
update ETYPE set NAME = :e_name where ID = :new_id;
for
select ADDR,REGTYPE,ORD from ETYPEREGS
where ETYPE_ID=:e_id
into :addr,:type,:ord
do
begin
insert into ETYPEREGS
(ETYPE_ID,ADDR,REGTYPE,ORD)
values
(:new_id,:addr,:type,:ord);
end
for
select CMD,ANSWR,ORD,REGTYPE from ETYPESPECIAL
where ETYPE_ID=:e_id
into :cmd,:answr,:ord,:type
do
begin
insert into ETYPESPECIAL
(ETYPE_ID,CMD,ANSWR,ORD,REGTYPE)
values
(:new_id,:cmd,:answr,:ord,:type);
end
end^
SET TERM ; ^
This is my code in C++:
StoredProc_InsertEType->ParamByName("E_ID")->AsInteger = src_id;
StoredProc_InsertEType->ParamByName("E_NAME")->AsString = _name;
try
{
StoredProc_InsertEType->ExecProc();
new_id = StoredProc_InsertEType->ParamByName(L"NEW_ID")->AsInteger;
}
catch(EDBEngineError & e)
{
errors->Add(e.Message);
return false;
}
Variable new_id is always zero regardless of fact that table ETYPE is not empty. When I run command SELECT MAX(ID) FROM ETYPE from administration tool FlameRobin it returns correct number (~180). What should I do to obtain correct value of NEW_ID parameter?
you need to add
suspend;
in your sp
and query with
select * from your_sp
suspend explained
http://www.janus-software.com/fbmanual/manual.php?book=psql&topic=104
regards,

Resources