473,399 Members | 2,278 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

Informix "foreach execute procedure": converting to DB2

Hello,

I'm writing an automatic SQL parser and translator from Informix to
DB2. Now I'm faced with one of the most difficult things to translate,
the "foreach execute procedure" functionality provided by Informix.
This is the problem: the execution of the translated SQL leaves the
rows in the temp table correctly but raises error SQL0480N. It's very
simple to try it:

------------
Original SQL:
------------

create temp table a(a smallint)
;
drop procedure a
;
create procedure a() returning smallint;
return 1 with resume;
return 2 with resume;
end procedure
;
drop procedure b
;
create procedure b()
define b smallint;
foreach execute procedure a() into b
insert into a values(b);
end foreach;
end procedure
;
execute procedure b()
;
select * from a
;
drop table a
;

Results:
-------
1
2
----------------------------
Automatically translated SQL:
----------------------------

DECLARE GLOBAL TEMPORARY TABLE a(a SMALLINT) ON COMMIT PRESERVE ROWS
NOT LOGGED WITH REPLACE
@
CREATE PROCEDURE DROP_IFEXISTS()
BEGIN
DECLARE DROP_SQL VARCHAR(255);
IF EXISTS (SELECT routinename FROM syscat.routines WHERE
routineschema = current_schema AND routinename = 'A' AND routinetype =
'F') THEN
SET DROP_SQL = 'DROP FUNCTION a';
EXECUTE IMMEDIATE DROP_SQL;
ELSEIF EXISTS (SELECT routinename FROM syscat.routines WHERE
routineschema = current_schema AND routinename = 'A' AND routinetype =
'P') THEN
SET DROP_SQL = 'DROP PROCEDURE a';
EXECUTE IMMEDIATE DROP_SQL;
END IF;
END
@
CALL DROP_IFEXISTS
@
DROP PROCEDURE DROP_IFEXISTS
@
CREATE PROCEDURE a() DYNAMIC RESULT SETS 1
BEGIN
DECLARE a_OUTPUT_1_TAB VARCHAR(20);
DECLARE a_OUTPUT_1_SQL VARCHAR(1024);
DECLARE a_OUTPUT_1_CUR CURSOR WITH RETURN TO CALLER FOR
a_OUTPUT_1_SEL;

SET a_OUTPUT_1_TAB = 'a_OUTPUT_1';
SET a_OUTPUT_1_SQL = 'DECLARE GLOBAL TEMPORARY TABLE ' ||
a_OUTPUT_1_TAB || '(a_1 SMALLINT) ON COMMIT PRESERVE ROWS NOT LOGGED
WITH REPLACE';
EXECUTE IMMEDIATE a_OUTPUT_1_SQL;
SET a_OUTPUT_1_SQL = 'INSERT INTO SESSION.' || a_OUTPUT_1_TAB || '
VALUES(1)';
EXECUTE IMMEDIATE a_OUTPUT_1_SQL;
SET a_OUTPUT_1_SQL = 'INSERT INTO SESSION.' || a_OUTPUT_1_TAB || '
VALUES(2)';
EXECUTE IMMEDIATE a_OUTPUT_1_SQL;
SET a_OUTPUT_1_SQL = 'SELECT * FROM SESSION.' || a_OUTPUT_1_TAB;
PREPARE a_OUTPUT_1_SEL FROM a_OUTPUT_1_SQL;
OPEN a_OUTPUT_1_CUR;
END
@
CREATE PROCEDURE DROP_IFEXISTS()
BEGIN
DECLARE DROP_SQL VARCHAR(255);
IF EXISTS (SELECT routinename FROM syscat.routines WHERE
routineschema = current_schema AND routinename = 'B' AND routinetype =
'F') THEN
SET DROP_SQL = 'DROP FUNCTION b';
EXECUTE IMMEDIATE DROP_SQL;
ELSEIF EXISTS (SELECT routinename FROM syscat.routines WHERE
routineschema = current_schema AND routinename = 'B' AND routinetype =
'P') THEN
SET DROP_SQL = 'DROP PROCEDURE b';
EXECUTE IMMEDIATE DROP_SQL;
END IF;
END
@
CALL DROP_IFEXISTS
@
DROP PROCEDURE DROP_IFEXISTS
@
CREATE PROCEDURE b()
BEGIN
DECLARE b SMALLINT;
DECLARE SQLSTATE CHAR(5);
DECLARE a_RESULTS_1 RESULT_SET_LOCATOR VARYING;

CALL a;
ASSOCIATE RESULT SET LOCATORS(a_RESULTS_1) WITH PROCEDURE a;
ALLOCATE a_OUTPUT_CURSOR_1 CURSOR FOR RESULT SET a_RESULTS_1;
FETCH FROM a_OUTPUT_CURSOR_1 INTO b;
WHILE (SQLSTATE = '00000') DO
INSERT INTO SESSION.a VALUES(b);
FETCH FROM a_OUTPUT_CURSOR_1 INTO b;
END WHILE;
CLOSE a_OUTPUT_CURSOR_1;
END
@
CALL b
@
SELECT * FROM SESSION.a
@
DROP TABLE SESSION.a
@
Results:
-------

DB20000I The SQL command completed successfully.
DB20000I The SQL command completed successfully.

Return state = 0

DB20000I The SQL command completed successfully.
DB20000I The SQL command completed successfully.
DB20000I The SQL command completed successfully.

Return state = 0

DB20000I The SQL command completed successfully.
DB20000I The SQL command completed successfully.

SQL0480N The procedure "B" has not yet been called. SQLSTATE=51030

Return state = 0

A
------
1
2

DB20000I The SQL command completed successfully.
----------------------------------------------------------------------------

ANY HINT?............ (using DB2 v8.1.0.64, "s040812", "MI00086",
FixPak 7)
Nov 12 '05 #1
5 12385
Gustavo Randich wrote:
Hello,

I'm writing an automatic SQL parser and translator from Informix to
DB2. Now I'm faced with one of the most difficult things to translate,
the "foreach execute procedure" functionality provided by Informix.
This is the problem: the execution of the translated SQL leaves the
rows in the temp table correctly but raises error SQL0480N. It's very
simple to try it:

------------
Original SQL:
------------

create temp table a(a smallint)
;
drop procedure a
;
create procedure a() returning smallint;
return 1 with resume;
return 2 with resume;
end procedure
;
drop procedure b
;
create procedure b()
define b smallint;
foreach execute procedure a() into b
insert into a values(b);
end foreach;
end procedure
;
execute procedure b()
;
select * from a
;
drop table a
;


Not knowing Informix well enough, I'd say that your procedure "A" is just a
table function, i.e. each call made to the function returns the next row.

In DB2 you could achieve something like it in the following way:

CREATE FUNCTION a()
RETURNS TABLE ( col SMALLINT )
LANGUAGE SQL
RETURN SELECT *
FROM TABLE ( VALUES ( 1 ),
( 2 ) ) AS t
@

Now you can use this function in procedure B:

CREATE PROCEDURE b()
LANGUAGE SQL
BEGIN
FOR fetch AS loop CURSOR FOR SELECT * FROM TABLE ( a() ) AS t
DO
INSERT INTO a VALUES (col);
END FOR;
END
@

In this particular case, I would even further simplify the procedure:

CREATE PROCEDURE b()
LANGUAGE SQL
BEGIN
INSERT INTO a SELECT col FROM TABLE ( a() ) AS t;
END
@

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #2
Knut,

Thanks for the reply. The procedure you wrote has exactly the same
behavior as mine. The table is populated, but I'm still getting the
error "SQL0480N The procedure "B" has not yet been called.
SQLSTATE=51030"; have you tried it?

Knut Stolze wrote:
Not knowing Informix well enough, I'd say that your procedure "A" is just a table function, i.e. each call made to the function returns the next row.
In DB2 you could achieve something like it in the following way:

CREATE FUNCTION a()
RETURNS TABLE ( col SMALLINT )
LANGUAGE SQL
RETURN SELECT *
FROM TABLE ( VALUES ( 1 ),
( 2 ) ) AS t
@

Now you can use this function in procedure B:

CREATE PROCEDURE b()
LANGUAGE SQL
BEGIN
FOR fetch AS loop CURSOR FOR SELECT * FROM TABLE ( a() ) AS t
DO
INSERT INTO a VALUES (col);
END FOR;
END
@

In this particular case, I would even further simplify the procedure:

CREATE PROCEDURE b()
LANGUAGE SQL
BEGIN
INSERT INTO a SELECT col FROM TABLE ( a() ) AS t;
END
@

--
Knut Stolze
Information Integration
IBM Germany / University of Jena


Nov 12 '05 #3
Knut Stolze wrote:
Gustavo Randich wrote:

Hello,

I'm writing an automatic SQL parser and translator from Informix to
DB2. Now I'm faced with one of the most difficult things to translate,
the "foreach execute procedure" functionality provided by Informix.
This is the problem: the execution of the translated SQL leaves the
rows in the temp table correctly but raises error SQL0480N. It's very
simple to try it:

------------
Original SQL:
------------

create temp table a(a smallint)
;
drop procedure a
;
create procedure a() returning smallint;
return 1 with resume;
return 2 with resume;
end procedure
;
drop procedure b
;
create procedure b()
define b smallint;
foreach execute procedure a() into b
insert into a values(b);
end foreach;
end procedure
;
execute procedure b()
;
select * from a
;
drop table a
;

Not knowing Informix well enough, I'd say that your procedure "A" is just a
table function, i.e. each call made to the function returns the next row.

In DB2 you could achieve something like it in the following way:

CREATE FUNCTION a()
RETURNS TABLE ( col SMALLINT )
LANGUAGE SQL
RETURN SELECT *
FROM TABLE ( VALUES ( 1 ),
( 2 ) ) AS t
@

Now you can use this function in procedure B:

CREATE PROCEDURE b()
LANGUAGE SQL
BEGIN
FOR fetch AS loop CURSOR FOR SELECT * FROM TABLE ( a() ) AS t
DO
INSERT INTO a VALUES (col);
END FOR;
END
@

In this particular case, I would even further simplify the procedure:

CREATE PROCEDURE b()
LANGUAGE SQL
BEGIN
INSERT INTO a SELECT col FROM TABLE ( a() ) AS t;
END
@

Alternatively (a bit more dumbed down and less performant) you could
do a CALL. Go through the allocate/associate locator logic
and then fetch from the result set of the procedure in a WHILE loop.

Of cousre the fastest would be:
INSERT INTO T SELECT * FROM TABLE(foo(a)) AS F

Cheers
Serge

Cheers
Serge
Nov 12 '05 #4
gu*************@yahoo.com.ar wrote:
Knut,

Thanks for the reply. The procedure you wrote has exactly the same
behavior as mine. The table is populated, but I'm still getting the
error "SQL0480N The procedure "B" has not yet been called.
SQLSTATE=51030"; have you tried it?


Yes, I have tried it and it did work quite fine. In particular, I didn't
see the SQL0480 that you got.

You might want to set the DIAGLEVEL to 4, run your statements again and see
if there is anything interesting in the db2diag.log.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #5
Knut Stolze <st****@de.ibm.com> wrote in message news:<co**********@fsuj29.rz.uni-jena.de>...
gu*************@yahoo.com.ar wrote:
Knut,

Thanks for the reply. The procedure you wrote has exactly the same
behavior as mine. The table is populated, but I'm still getting the
error "SQL0480N The procedure "B" has not yet been called.
SQLSTATE=51030"; have you tried it?


Yes, I have tried it and it did work quite fine. In particular, I didn't
see the SQL0480 that you got.

You might want to set the DIAGLEVEL to 4, run your statements again and see
if there is anything interesting in the db2diag.log.


Strange thing... no info about this ins db2diag.log; fortunately, the
applications I'm working on execute this SQL via ADO, which doesn't
intercept's the error. Thanks again.
Nov 12 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Luis | last post by:
I'm using a SQL Server 2000 stored procedure similar to the one below to upload data to a database. This data is collected from the user on a number of asp pages and stored in session variables...
32
by: James Curran | last post by:
I'd like to make the following proposal for a new feature for the C# language. I have no connection with the C# team at Microsoft. I'm posting it here to gather input to refine it, in an "open...
4
by: dstorms | last post by:
Hi, I'm trying to create a form with a list box with 2 columns and a button that opens the selected record in the appropriate form. In the sample below, the first column lists the type of equipment...
1
by: indikamaligaspe | last post by:
Hi all, I am trying to get a PL/TCL trigger to update an audit table working. The problem is when I create the trigger on an exiting table, I get the following error "ERROR: can't read...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.