Details
-
New Feature
-
Status: Stalled (View Workflow)
-
Critical
-
Resolution: Unresolved
-
Q4/2025 Server Development
Description
Currently prepared statements can only be executed and only a single row may be fetched. This is a severe limitation, in particular when it comes to stored procedures. This limits the support for Dynamic SQL we have and makes migration from, say, Oracle, real difficult. Oracle has support for cursors on Dynamic SQL.
Standard SQL syntax
Let's support the SQL standard syntax for <dynamic declare cursor>.
The SQL Standard assumes that:
- A cursor first is declared with the FOR clause, which binds the cursor to a prepared statement
- Then the prepared statement gets prepared
- Then the cursor is ready to be opened and fetched using the usual syntax:
DECLARE cursor_name FOR prepared_statement_name; -- <dynamic declare cursor> |
PREPARE prepared_statement_name FROM 'SELECT 1,2'; -- Placeholders are also possible |
OPEN cursor_name; -- USING clause is also possible |
Example:
CREATE OR REPLACE TABLE t1 (id INT, c1 VARCHAR(10)); |
INSERT INTO t1 VALUES (10,'c10'),(11,'c11'),(12,'c12'); |
|
DELIMITER $$
|
CREATE OR REPLACE PROCEDURE p1(tab VARCHAR(64), id INTEGER) |
BEGIN
|
DECLARE no_data BOOL DEFAULT FALSE; |
DECLARE v_c1 VARCHAR(100); |
DECLARE v_id INT; |
DECLARE c1 CURSOR FOR s1; |
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_data = TRUE; |
|
PREPARE s1 FROM CONCAT('SELECT id, c1 FROM ', tab, ' WHERE id >= ?'); |
OPEN c1 USING id; |
fetch_loop: LOOP
|
FETCH c1 INTO v_id, v_c1; |
IF no_data THEN |
LEAVE fetch_loop;
|
END IF; |
SELECT v_id, v_c1; |
END LOOP; |
CLOSE c1; |
END; |
$$
|
DELIMITER ;
|
CALL p1('t1',11); |
ROW TYPE OF won't be supported:
As the cursor structure is needed to be known at sp_rcontext creation time, ROW TYPE declarations won't be supported for dynamic cursors:
CREATE OR REPLACE TABLE t1 (a INT); |
INSERT INTO t1 VALUES (1),(2),(3); |
DELIMITER $$
|
CREATE OR REPLACE PROCEDURE p1() |
BEGIN
|
DECLARE v TEXT; |
DECLARE c CURSOR FOR stmt; |
BEGIN |
DECLARE r ROW TYPE OF c; -- This is wrong |
END; |
END; |
$$
|
DELIMITER ;
|
CALL p1;
|
Cursor FOR-loops won't be supported:
CREATE OR REPLACE TABLE t1 (a INT); |
INSERT INTO t1 VALUES (1),(2),(3); |
|
DELIMITER $$
|
CREATE OR REPLACE PROCEDURE p1() |
BEGIN
|
DECLARE c1 CURSOR FOR stmt; |
PREPARE stmt FROM 'SELECT a FROM t1'; |
FOR r IN c1 |
DO
|
INSERT INTO t2 VALUES(r.a); |
END FOR; |
END; |
$$
|
DELIMITER ;
|
CALL p1;
|
SYS_REFCURSORs should be supported:
CREATE OR REPLACE PROCEDURE p1(dynamic_sql VARCHAR) AS |
v1 INT; |
v2 VARCHAR(256); |
c SYS_REFCURSOR;
|
BEGIN
|
OPEN c FOR dynamic_sql; |
FETCH c INTO v1, v2; |
DBMS_OUTPUT.PUT_LINE(v1 || ' ' || v2); |
CLOSE c; |
END; |
/
|
CALL p1('SELECT 123, ''v123'' FROM DUAL'); |
123 v123
|
Attachments
Issue Links
- is part of
-
MDEV-35973 Oracle Compatibility Project 1 for 2025
-
- Stalled
-
- relates to
-
MDEV-10152 Add support for TYPE .. IS REF CURSOR
-
- Open
-
-
MDEV-20034 Add support for the pre-defined weak SYS_REFCURSOR
-
- Closed
-
-
MDEV-19635 System package SYS.DBMS_SQL
-
- Open
-
- links to