I have written a stored procedure as
CREATE OR REPLACE PROC1()
DECLARE VAR1 INT;
DECLARE VAR2 INT;
DECLARE TEXT VARCHAR(1000);
DECLARE exitcode INTEGER DEFAULT 0;
DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE CUR1 CURSOR WITH HOLD for STMT1 ;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET exitcode = 1;
SET TEXT= (-----);
PREPARE STMT1 FROM TEXT;
open cur1;
fetch from cur1 into var1,var2;
while(sqlcode =0)
do
--
--
CALL SYSPROC.ADMIN_CMD('REORG TABLE emp1 ');
set exit code = 0;
fetch from cur1 into var1,var2;
IF (exitcode = 1)
THEN
LEAVE wloop;
END IF;
end while;
close cur1;
My question is even I declared my cursor as WITH HOLD option, after the first fetch the cursor is closing & throwing -501 error.If i remove the REORG statement from the loop. Then cursor is working normally,fetching all the rows. Can some one tel me the way to keep my cursor to be open even If i use the REORG statement inside the loop.
Thanks in advance
Related
CREATE or replace PROCEDURE return_result_set ( )
LANGUAGE SQL
SPECIFIC return_result_set
DYNAMIC RESULT SETS 1
rrs: BEGIN
DECLARE rs_cur CURSOR WITH RETURN
FOR SELECT *
FROM dummytable;
OPEN rs_cur;
END rrs
I can return result set using cursor by using above stored procedure, but I want to use cursor variable (Weakly-typed) in my stored procedure as the select query and table are going to vary based on a condition. Sample code here seems to be for different use case..
How to return a result set using a Cursor Variable?
Try this as is:
--#SET TERMINATOR #
SET SERVEROUTPUT ON#
BEGIN
DECLARE V_C1 CURSOR;
DECLARE V_I INT;
DECLARE PROCEDURE L_PROC(OUT LP_C1 CURSOR)
BEGIN
-- Dynamic cursor
--DECLARE V_STMT VARCHAR(128) DEFAULT 'SELECT * FROM (VALUES 1) T(I)';
--PREPARE V_S1 FROM V_STMT;
--SET LP_C1 = CURSOR FOR V_S1;
-- Static cursor
SET LP_C1 = CURSOR FOR SELECT * FROM (VALUES 1) T(I);
OPEN LP_C1;
END;
CALL L_PROC(V_C1);
FETCH V_C1 INTO V_I;
CALL DBMS_OUTPUT.PUT_LINE('I: ' || V_I);
CLOSE V_C1;
END#
SET SERVEROUTPUT OFF#
I have a sample stored procedure where in I have to use a table for multiple operations. I want to declare the table name as a constant and then re-use it wherever required. Below is the sample code which i wrote:
CREATE OR REPLACE FUNCTION get_data()
RETURNS void AS
$func$
DECLARE
table_name_a CONSTANT TEXT = asp.monitoring_bookmark_original;
cursor_file CURSOR FOR
select distinct filename,systemuid from table_name_a;
cursor_data CURSOR FOR
select * from table_name_a where filename = v_filename and systemuid=v_systemuid order by mindatetime, maxdatetime;
BEGIN
--open the file cursor
//logic goes here
END;
$func$
LANGUAGE plpgsql;
When I try to run this procedure I am getting error:
ERROR: missing FROM-clause entry for table "asp"
LINE 1: SELECT asp.monitoring_bookmark_original
What is wrong in this code? How do I correct this?
Well you can use dynamic SQL, but realize dynamic SQL often adds way more complexity. Good when really needed but should be avoided when possible. The following shows what would be needed for what you want to do. Is not having to type the table name for each SQL statement worth the additional trouble?
create or replace function get_data()
returns void as
$func$
declare
table_name_a constant text = 'asp.monitoring_bookmark_original';
file_cursor text = 'select distinct filename,systemuid from %i';
file_ref refcursor;
file_rec record;
data_cursor text =$stmt$select * from %i where filename = '%s' and systemuid= '%s' order by mindatetime, maxdatetime$stmt$;
data_ref refcursor;
data_rec record;
begin
--open the file cursor
open file_ref for execute format(file_cursor,table_name_a);
loop
fetch next from file_ref into file_rec;
exit when not found;
-- and extending from what the second query inplies
open data_ref for execute format(data_cursor,table_name_a,file_rec.filename,file_rec.systemid);
loop
fetch next from data_ref into data_rec;
exit when not found;
--//logic goes here
end loop;
end loop ;
end;
$func$
language plpgsql;
I wrote trigger to execute a query after the update of the column (retard) in my table, but sometimes there are many rows updated how to solve that?
CREATE OR ALTER TRIGGER notifRetard
ON Taches
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #value INT
IF UPDATE(retard)
-- How to make this for every row updated???
SELECT
#value = inserted.retard
FROM
inserted;
IF #value = 1
-- run SQL query
END
The solution if someone else need it is to use CURSOR.
CREATE or alter TRIGGER notifRetard
ON Taches
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(retard)
begin
DECLARE #RefTache varchar(50),#RefPhase numeric(4,0),#IDprojet varchar(50),#IDressource varchar(50) #retard bit;
DECLARE TrigTempUpdate_Cursor CURSOR FOR
SELECt RefTache,RefPhase,IDprojet,IDressource,retard
FROM
inserted;
begin
OPEN TrigTempUpdate_Cursor;
FETCH NEXT FROM TrigTempUpdate_Cursor INTO #RefTache, #RefPhase,#IDprojet,#IDressource,#retard
WHILE ##FETCH_STATUS = 0
BEGIN
if #retard=1
--DO QUERY HERE
FETCH NEXT FROM TrigTempUpdate_Cursor INTO #RefTache, #RefPhase,#IDprojet,#IDressource,#retard
END;
end;
CLOSE TrigTempUpdate_Cursor;
DEALLOCATE TrigTempUpdate_Cursor;
end;
end;
I know the right way to insert value from a table:
insert into city (pop) select pop+2 from city
I just want to know how cursor works in Pl/pgsql .
I wish to use cursor in loop to insert some value:
create or replace function test( ) returns void as
$$
declare
cur cursor for select pop+2 from city order by pop;
b int;
row record;
begin
for row in cur
LOOP
fetch cur into b;
insert into city(pop) select b;
end loop;
end;
$$ language plpgsql
However, when I type select test() and the result table is:
It's very strange that only two rows are inserted. So I want to know what lead to this result?
Update my question in 04/05/2016:
I revise the function like this:
create or replace function test( ) returns void as
$$
declare
cur cursor for select * from city order by pop;
b record;
begin
for b in cur
LOOP
insert into city(pop) select b.pop+2;
RAISE NOTICE ' % IS INSERTED' , b;
end loop;
end;
$$ language plpgsql
Then I get the correct result:
But I still wonder why in the first function, only two rows are inserted.
I finally figure out that why the result is wrong, just like Abelisto's comment . I did two fetchers in loop at each step:
at for row in cur LOOP ,
at fetch cur into b
So the first row where pop=500 and the third row where pop =1000 have already been fetched in for loop, and it can't be fetched by b.
I have written one procedure. I am getting the below error.
Can someone help me with this.
Create procedure p1()
declare cur1 cursor WITH HOLD for STMT1;
DECLARE CONTINUE HANDLER FOR SQLSTATE '24501'
BEGIN
OPEN index_list ;
set exitcode = 1;
END ;
set TEXT =();
PREPARE STMT1 FROM TEXT;
OPEN cur1 ;
FETCH FROM cur1 INTO VAR2,
VAR1 ;
WHILE (SQLCODE = 0)
DO
EXECUTE IMMEDIATE 'SET PASSTHRU SAMPLE' ;
----
-----
EXECUTE IMMEDIATE 'SET PASSTHRU RESET' ;
FETCH FROM cur1 INTO VAR2,
VAR1 ;
END WHILE;
This is my code outline. My problem is After that 'SET PASSTHRU RESET', cursor is getting closed & the second fetch is failing with the below error.even I specified the curos a WITH HOLD option.
error:
The cursor specified in a FETCH statement or CLOSE statement is not open or a cursor variable in a cursor scalar function reference is not open.. SQLCODE=-501, SQLSTATE=24501, DRIVER=4.17.30
Run of routine failed.
can some one please let me know, what i have to add here.
I am new bee for db2 & never met with this scenario. That is why I am asking the experts.