I am writing a trigger in DB2. Inside that i wanted to use a loop.
This is to iterate through a set of values returned from a select statement.
How can this be done?
Anybody please share a tutorial or link which explains this.
Also is it ok to have nested loop?
You can use a cursor in your trigger:
http://en.wikipedia.org/wiki/Cursor_%28databases%29
A simple cursor example looks like this:
DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
DECLARE p_sum INTEGER;
SET p_sum = 0;
DECLARE p_sal INTEGER;
DECLARE c CURSOR FOR SELECT SALARY FROM EMPLOYEE;
OPEN c;
FETCH FROM c INTO p_sal;
WHILE(SQLSTATE = '00000') DO
SET p_sum = p_sum + p_sal;
FETCH FROM c INTO p_sal;
END WHILE;
CLOSE c;
Related
I have the following problem with a procedure:
CREATE PROCEDURE TEST()
LANGUAGE SQL
BEGIN
DECLARE V_TEST VARCHAR(100);
DECLARE V_TEST_EXT VARCHAR(100);
DECLARE SQLCODE INTEGER DEFAULT -1;
DECLARE RET_CODE INTEGER DEFAULT -2;
DECLARE LIST_CMD VARCHAR(512);
DECLARE LIST_CMD_EXT VARCHAR(512);
DECLARE CUR_TEST CURSOR WITH RETURN FOR LIST_STMT;
DECLARE CUR_TEST_EXT CURSOR WITH RETURN FOR LIST_EXT_STMT;
DECLARE CONTINUE HANDLER FOR SQLEXECPTION SET RET_CODE = SQLCODE;
SET LIST_CMD = 'SELECT TEST FROM TESTTAB';
PREPARE LIST_STMT FROM LIST_CMD;
OPEN CUR_TEST;
FETCH CUR_TEST INTO V_TEST;
WHILE (RET_CODE <> 100) DO
FETCH CUR_TEST INTO V_TEST;
END WHILE;
CLOSE CUR_TEST;
SET LIST_CMD_EXT = 'SELECT TEST FROM TESTTAB';
PREPARE LIST_STMT_EXT FROM LIST_CMD_EXT;
OPEN CUR_TEST_EXT;
FETCH CUR_TEST_EXT INTO V_TEST_EXT;
WHILE (RET_CODE <> 100) DO
FETCH CUR_TEST_EXT INTO V_TEST_EXT;
END WHILE;
CLOSE CUR_TEST_EXT;
END;
The problem I am having is that the procedure does the first cursor loop but ignores the second one. I tried adding BEGIN and END to each loop but that didn't help as well.
I am running DB2 v10.5 Windows. I need this to work as a procedure. Is there any way to make the procedure run both loops?
Thank you for your help.-
You don't reset the RET_CODE variable before processing the 2-nd cursor.
Use something like this:
SET RET_CODE = 0;
OPEN CUR_TEST_EXT;
...
BTW, don't declare a cursor using 'WITH RETURN' clause if you process this cursor inside the procedure.
I am unable to use %notfound as I get the following error. How can I get past this?? I'm unable to figure out a way to use cursors apart from this method. Please help with other methods to use a cursor loop without using %notfound.
The character "%" following "EXIT WHEN c_rqstid" is not valid.. SQLCODE=-7, SQLSTATE=42601, DRIVER=3.63.123 SQL Code: -7, SQL State: 42601
I have set # as the delimeter and the code is as follows
create PROCEDURE TEST111()
AS:
begin
DECLARE c_id integer;
DECLARE c_isactive integer;
DECLARE c_status integer;
CURSOR c_rqstid is SELECT REQUESTID,REQUESTSTATUS,ISACTIVE FROM SAMPLE.REQUEST;
OPEN c_rqstid;
FOR LOOP FETCH c_rqstid into c_id,c_status,c_isactive ;
----will code this later
EXIT WHEN c_rqstid%NOTFOUND;
END LOOP;
CLOSE c_rqstid;
end
#
Thanks for any help in advance...
You'll need to check the SQLCODE or SQLSTATE variables:
http://pic.dhe.ibm.com/infocenter/db2luw/v10r1/topic/com.ibm.db2.luw.apdv.sqlpl.doc/doc/c0009028.html
DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
WHILE(SQLSTATE = '00000') DO
SET p_sum = p_sum + p_sal;
FETCH FROM c INTO p_sal;
END WHILE;
I wanted to know how to insert into a table using stored procedures in DB2 using SQL.
I have created a table as follows:
create table ADCLIBT.Itest
(ITNBR CHAR(15) CCSID 65535 NOT NULL DEFAULT '');
This table contains a list of items. Using this list I want to insert various other fields to another table. But, just for example sake, let's say I just want to insert these values one by one using cursors.
I have written the stored procedure as follows:
create procedure ADCLIBT.itest1()
LANGUAGE SQL
BEGIN
DECLARE itemno char(15);
DECLARE END_TABLE INT DEFAULT 0;
DECLARE not_found CONDITION FOR SQLSTATE '20000';
DECLARE c CURSOR FOR
select ITNBR from ADCLIBT.ITEMAT;
DECLARE CONTINUE HANDLER FOR not_found
SET END_TABLE = 1;
open c;
fetch from c into itemno;
WHILE END_TABLE = 0 DO
insert into ADCLIBT.ITEST
(ITNBR)
values
(select a.ITNBR from ADCLIBT.ITEMAT a where ITNBR=itemno GROUP BY a.ITNBR);
END WHILE;
Close c;
END;
This is giving me an infinite loop. Can anyone please tell me how do I stop the infinite loop and insert these records. I want to use the cursor because I want to further use itemno to compare and get single results.
You are opening the cursor but not feching in the while, you must do a fetch in the while of the cursor. Here an example from the IBM documentation.
CREATE PROCEDURE sum_salaries(OUT sum INTEGER) LANGUAGE SQL
BEGIN
DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
DECLARE p_sum INTEGER;
DECLARE p_sal INTEGER;
DECLARE c CURSOR FOR SELECT SALARY FROM EMPLOYEE;
SET p_sum = 0;
OPEN c;
FETCH FROM c INTO p_sal;
WHILE(SQLSTATE = '00000') DO
SET p_sum = p_sum + p_sal;
FETCH FROM c INTO p_sal;
END WHILE;
CLOSE c;
SET sum = p_sum;
END%
I can't get this stored procedure to compile, I simply want to declare and set one variable that will be used in the proc. NOTE: shipNo is the only incoming parameter, and is VARCHAR(32).
P1: BEGIN
DECLARE #likeShipNo VARCHAR(32);
SET likeShipNo = '%' || shipNo || '%';
DECLARE cursor1 CURSOR WITH RETURN FOR
SELECT ADV_SHIP_NOTICE_NO,
VNDR_ID,
LOC,
CARR_CD,
CARR_PRO_NO,
BL_NO,
SHIP_EQUIP_ID,
TS_LOAD
FROM TRITS
WHERE ADV_SHIP_NOTICE_NO LIKE(#likeShipNo);
OPEN cursor1;
END P1
The variables in DB2 doesn't need the # like in MSSQL. Also, when you return a cursor, you need to add the sentence RESULT SET 1 before begin and add the WITH RETURN TO CLIENT to the cursor that you want to return. The procedure should look like this:
CREATE BEGIN MYSCHEMA.MYPROC (
IN shipNo VARCHAR(30) )
BEGIN
DECLARE likeShipNo VARCHAR(32);
SET likeShipNo = '%' || shipNo || '%';
DECLARE cursor1 CURSOR WITH RETURN TO CLIENT FOR
SELECT
ADV_SHIP_NOTICE_NO,
VNDR_ID,
LOC,
CARR_CD,
CARR_PRO_NO,
BL_NO,
SHIP_EQUIP_ID,
TS_LOAD
FROM
TRITS
WHERE
ADV_SHIP_NOTICE_NO LIKE likeShipNo;
OPEN cursor1;
END;
My problem is fairly simple. I have table sets that store product sets (more products looking like one on the outside - computer, mouse and keyboard for ex.) it's connected M:N using sets_products table to products table. Each product can have parameters (connected again M:N).
I have a procedure, that generates all parameters as string (for search cache - like 'hdd:120GB, LCD:1440:900, ..'), but now I need to loop through the set's products and call the procedure for each of them. I CAN'T DO IT IN PHP, because this is used in trigger.
I'd like to use something like this (pseudo SQL)
FOREACH(SELECT products_id FROM sets_products WHERE set_id = 1)
generate_parameter_list(product_id,#result)
#param = CONCAT(#param,",",#result);
END FOREACH;
Can this be done in MySQL or not?
Here's the mysql reference for cursors. So I'm guessing it's something like this:
DECLARE done INT DEFAULT 0;
DECLARE products_id INT;
DECLARE result varchar(4000);
DECLARE cur1 CURSOR FOR SELECT products_id FROM sets_products WHERE set_id = 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO products_id;
IF NOT done THEN
CALL generate_parameter_list(#product_id, #result);
SET param = param + "," + result; -- not sure on this syntax
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
-- now trim off the trailing , if desired
This can be done with MySQL, although it's highly unintuitive:
CREATE PROCEDURE p25 (OUT return_val INT)
BEGIN
DECLARE a,b INT;
DECLARE cur_1 CURSOR FOR SELECT s1 FROM t;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET b = 1;
OPEN cur_1;
REPEAT
FETCH cur_1 INTO a;
UNTIL b = 1
END REPEAT;
CLOSE cur_1;
SET return_val = a;
END;//
Check out this guide: mysql-storedprocedures.pdf