Oracle兼容-存储过程-REF CURSOR, SYS_REFCURSOR


1. 语法

  1. 1. var SYS_REFCURSOR
  2. 2. TYPE type_name IS REF CURSOR
  3. 3. OPEN cursor_name FOR {select_statement | dynamic_string}
  4. 4. FOR rows IN
  5. {
  6. ( select_statement )
  7. }
  8. LOOP statement... END LOOP [label] ;
  9. 5. CREATE [OR REPLACE] sp_name(var_list) RETURN SYS_REFCURSOR AS routine_body
  10. 6. CREATE [OR REPLACE] sp_name(var_list) AS routine_body
  11. 7. cursor1 := cursor2
  12. 8. SELECT cursor1 INTO cursor2

2. 定义和用法

ORACLE 模式下,GreatSQL存储过程/存储函数支持以下几种 REF CURSOR, SYS_REFCURSOR 用法:

    1. 语法1:支持用 var SYS_REFCURSOR 语法来定义 SYS_REFCURSOR
  1. var SYS_REFCURSOR
    1. 语法2:支持用 TYPE ... IS REF CURSOR 语法定义 REF CURSOR
  1. TYPE type_name IS REF CURSOR
    1. 语法3:支持用 OPEN ... FOR 打开 REF CURSOR
  1. OPEN cursor_name FOR {select_statement | dynamic_string}
    1. 语法4:FOR rows IN (select_stmt) LOOP 会隐式创建 REF CURSOR,这里的 rows 不需要提前定义,且只在当前 FOR ... LOOP 语句块中有效。
  1. FOR rows IN
  2. {
  3. ( select_statement )
  4. }
  5. LOOP statement... END LOOP [label] ;

更多关于 FOR rows IN CURSOR 用法参考:Oracle兼容-存储过程-游标(CURSOR)

    1. 语法5:FUNCTION RETURN SYS_REFCURSOR 支持函数返回 REF CURSOR 类型数据。对于 FUNCTION 不支持变量中包含 SYS_REFCURSOR 类型参数。
  1. CREATE [OR REPLACE] FUNCTION sp_name(var_list) RETURN SYS_REFCURSOR AS routine_body
    1. 语法6:支持存储过程的参数带 OUT SYS_REFCURSOR,并支持 REF CURSOR 类型返回结果。
  1. CREATE [OR REPLACE] sp_name(var_list) AS routine_body
    1. 语法7:支持将 REF CURSOR 作为参数来赋值,二者享有共同的 REF CURSOR 状态。cursor1cursor2 都是 REF CURSOR 类型,享有共同的 REF CURSOR 状态。如果其中一个重新 OPEN CURSOR FOR 或者 CLOSE CURSOR,那么会影响所有关联 REF CURSOR。如果只是其中一个被赋值,那么不会影响另外的关联 REF CURSOR,只会影响其他被赋值的 REF CURSOR(详见下方示例12)。
  1. cursor1 := cursor2
    1. 语法8:采用 SELECT cursor1 INTO cursor2 语法就可以进行 REF CURSOR 赋值,二者享有共同的 REF CURSOR 状态。
  1. SELECT cursor1 INTO cursor2

3. Oracle兼容说明

ORACLE 模式下,GreatSQL存储过程/存储函数中 REF CURSOR, SYS_REFCURSOR 用法与Oracle用法基本一致。

GreatSQL在兼容性差异主要有以下几点:

  1. 只支持在存储过程/存储函数内部中使用 SYS_REFCURSOR,也支持作为参数传入和输出。

  2. REF CURSORSYS_REFCURSOR 的参数也作为存储过程/存储函数的参数,因此不能再定义同名参数。

  3. 如果只定义了 REF CURSORSYS_REFCURSOR 而没有定义具体SQL语句,则这个游标无法使用。

  4. 语句 OPEN sp_name FOR 可以用在 LOOP .. END LOOP 语句块里。

  5. 支持在 OPEN sp_name FOR 之后无需先 CLOSE 而可以继续 OPEN sp_name FOR 再次使用,这点和 OPEN sp_name 用法不一样。

  6. 游标 cur1 没有定义的话,cur1%ISOPEN 依然可以被使用而不会报错;而 cur1%FOUND, cur1%NOTFOUND, cur1%ROWCOUNT 则会报错。

  7. 对于 CALL sp1(IN var_name) 中的参数 var_name 只能执行 FETCHCLOSE 操作,不能进行赋值和 OPEN FOR 操作,这点与Oracle行为一致。

  8. 对于 CALL sp1(var_name) 中的 var_name 必须为REF CURSOR类型,否则会报错(详见下方示例11)。

  9. 如果被关联的游标关闭以后,在Oracle中该游标是不能再被打开只能被赋值使用;但在GreatSQL允许再次被打开使用,也可以再被赋值使用,这点二者不一样(详见下方示例13)。

  10. ORACLE模式下,SELECT 结果为 SYS_REFCURSOR 的存储函数结果的输出为 NULL (详见下方示例10)。

4. 示例

修改 sql_generate_invisible_primary_key 选项设定,因为下面案例中创建的表没有显式主键,关闭该选项可以避免自动创建隐式主键 my_row_id,可能会对下面的案例造成影响。

  1. greatsql> SET SESSION sql_generate_invisible_primary_key = 0;

创建测试表并初始化数据

  1. greatsql> CREATE TABLE t1 (a INT NOT NULL, b VARCHAR(20) NOT NULL);
  2. greatsql> INSERT INTO t1 VALUES(1, 'row1'), (2, 'row2'), (3,'row3') ;
    1. 示例1:SYS_REFCURSOR, OPEN CURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> DELIMITER //
  3. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  4. cur1 SYS_REFCURSOR;
  5. sql1 VARCHAR(100);
  6. rtype t1%ROWTYPE;
  7. BEGIN
  8. sql1 := 'SELECT * FROM t1';
  9. OPEN cur1 FOR sql1;
  10. LOOP
  11. FETCH cur1 INTO rtype;
  12. EXIT WHEN cur1%NOTFOUND;
  13. SELECT rtype.a, rtype.b;
  14. END LOOP;
  15. END; //
  16. greatsql> CALL p1() //
  17. +---------+---------+
  18. | rtype.a | rtype.b |
  19. +---------+---------+
  20. | 1 | row1 |
  21. +---------+---------+
  22. 1 row in set (0.00 sec)
  23. +---------+---------+
  24. | rtype.a | rtype.b |
  25. +---------+---------+
  26. | 2 | row2 |
  27. +---------+---------+
  28. 1 row in set (0.00 sec)
  29. +---------+---------+
  30. | rtype.a | rtype.b |
  31. +---------+---------+
  32. | 3 | row3 |
  33. +---------+---------+
  34. 1 row in set (0.00 sec)
  35. Query OK, 0 rows affected (0.00 sec)
    1. 示例2:SYS_REFCURSOR, OPEN CURSOR FOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> DELIMITER //
  3. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  4. cur1 SYS_REFCURSOR;
  5. rtype t1%ROWTYPE;
  6. BEGIN
  7. OPEN cur1 FOR SELECT * FROM t1;
  8. LOOP
  9. FETCH cur1 INTO rtype;
  10. EXIT WHEN cur1%NOTFOUND;
  11. SELECT rtype.a, rtype.b;
  12. END LOOP;
  13. END; //
  14. greatsql> CALL p1() //
  15. +---------+---------+
  16. | rtype.a | rtype.b |
  17. +---------+---------+
  18. | 1 | row1 |
  19. +---------+---------+
  20. 1 row in set (0.00 sec)
  21. +---------+---------+
  22. | rtype.a | rtype.b |
  23. +---------+---------+
  24. | 2 | row2 |
  25. +---------+---------+
  26. 1 row in set (0.00 sec)
  27. +---------+---------+
  28. | rtype.a | rtype.b |
  29. +---------+---------+
  30. | 3 | row3 |
  31. +---------+---------+
  32. 1 row in set (0.00 sec)
  33. Query OK, 0 rows affected (0.00 sec)
    1. 示例3:FOR ident in (SELECT_stmt) LOOP
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> DELIMITER //
  3. CREATE OR REPLACE PROCEDURE p1() AS
  4. BEGIN
  5. --这里的rtype只在当前FOR LOOP内部使用,外面无法使用
  6. FOR rtype in (SELECT * FROM t1) LOOP
  7. SELECT rtype.a, rtype.b;
  8. END LOOP;
  9. END; //
  10. greatsql> CALL p1() //
  11. +-----------+-----------+
  12. | rtype.a | rtype.b |
  13. +-----------+-----------+
  14. | 1 | aa |
  15. +-----------+-----------+
  16. 1 row in set (0.02 sec)
  17. +-----------+-----------+
  18. | rtype.a | rtype.b |
  19. +-----------+-----------+
  20. | 2 | bb |
  21. +-----------+-----------+
  22. 1 row in set (0.02 sec)
  23. +-----------+-----------+
  24. | rtype.a | rtype.b |
  25. +-----------+-----------+
  26. | 3 | cc |
  27. +-----------+-----------+
  28. 1 row in set (0.02 sec)
  29. Query OK, 0 rows affected (0.02 sec)
    1. 示例4:REF CURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> DELIMITER //
  3. CREATE OR REPLACE PROCEDURE p1() AS
  4. TYPE dr_CURSOR IS REF CURSOR;
  5. cur1 dr_CURSOR;
  6. rtype t1%ROWTYPE;
  7. BEGIN
  8. -- 这里可以改写成sql1 := 'SELECT * FROM t1 WHERE a<3';
  9. -- OPEN cur1 FOR sql1;sql1需要提前声明。
  10. OPEN cur1 FOR SELECT * FROM t1 WHERE a<3;
  11. LOOP
  12. FETCH cur1 INTO rtype;
  13. EXIT WHEN cur1%NOTFOUND;
  14. SELECT rtype.a, rtype.b;
  15. END LOOP;
  16. END; //
  17. greatsql> CALL p1() //
  18. +-----------+-----------+
  19. | rtype.a | rtype.b |
  20. +-----------+-----------+
  21. | 1 | aa |
  22. +-----------+-----------+
  23. 1 row in set (0.01 sec)
  24. +-----------+-----------+
  25. | rtype.a | rtype.b |
  26. +-----------+-----------+
  27. | 2 | bb |
  28. +-----------+-----------+
  29. 1 row in set (0.01 sec)
  30. Query OK, 0 rows affected (0.01 sec)
    1. 示例5:duplicate var with declared and FOR LOOP
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> DELIMITER //
  3. use db1;
  4. set sql_mode="oracle";
  5. CREATE TABLE t1 (a INT, b VARCHAR(3));
  6. INSERT INTO t1 VALUES(1,'aa'),(2,'bb'),(3,'cc') ;
  7. DELIMITER //
  8. CREATE OR REPLACE PROCEDURE p1() AS
  9. rtype int;
  10. BEGIN
  11. FOR rtype in (SELECT * FROM t1) LOOP
  12. SELECT rtype.a, rtype.b;
  13. END LOOP;
  14. SELECT rtype;
  15. END; //
  16. > CALL p1() //
    1. 示例6:FUNCTION RETURN SYS_REFCURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE FUNCTION returnaCURSOR RETURN SYS_REFCURSOR
  5. AS
  6. cur1 SYS_REFCURSOR;
  7. BEGIN
  8. OPEN cur1 FOR SELECT * FROM t1 WHERE a < 3;
  9. RETURN cur1;
  10. END; //
  11. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  12. a INT;
  13. b VARCHAR(20);
  14. c SYS_REFCURSOR;
  15. BEGIN
  16. c := returnaCURSOR();
  17. LOOP
  18. FETCH c INTO a, b;
  19. EXIT WHEN c%NOTFOUND;
  20. SELECT a, b;
  21. END LOOP;
  22. CLOSE c;
  23. END; //
  24. greatsql> CALL p1() //
  25. +------+------+
  26. | a | b |
  27. +------+------+
  28. | 1 | row1 |
  29. +------+------+
  30. 1 row in set (0.00 sec)
  31. +------+------+
  32. | a | b |
  33. +------+------+
  34. | 2 | row2 |
  35. +------+------+
  36. 1 row in set (0.00 sec)
  37. Query OK, 0 rows affected (0.00 sec)
    1. 示例7:PROCEDURE WITH OUT SYS_REFCURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE PROCEDURE sp_return(ref_rs OUT SYS_REFCURSOR)
  5. IS
  6. sql1 VARCHAR(100);
  7. BEGIN
  8. sql1 := 'SELECT a, b FROM t1 WHERE a > 2';
  9. OPEN ref_rs FOR sql1;
  10. END; //
  11. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  12. a INT;
  13. b VARCHAR(20);
  14. c SYS_REFCURSOR;
  15. BEGIN
  16. CALL sp_return(c);
  17. LOOP
  18. FETCH c INTO a, b;
  19. EXIT WHEN c%NOTFOUND;
  20. SELECT a, b;
  21. END LOOP;
  22. CLOSE c;
  23. END; //
  24. greatsql> CALL p1() //
  25. +------+------+
  26. | a | b |
  27. +------+------+
  28. | 3 | row3 |
  29. +------+------+
  30. 1 row in set (0.00 sec)
  31. Query OK, 0 rows affected (0.00 sec)
    1. 示例8:SET REF CURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE FUNCTION return_cur RETURN SYS_REFCURSOR
  5. AS
  6. cur1 SYS_REFCURSOR;
  7. BEGIN
  8. OPEN cur1 FOR SELECT * FROM t1 WHERE a < 3;
  9. RETURN cur1;
  10. END; //
  11. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  12. cur1 SYS_REFCURSOR;
  13. cur2 SYS_REFCURSOR;
  14. a INT;
  15. b VARCHAR(20);
  16. BEGIN
  17. cur1 := return_cur();
  18. cur2 := cur1;
  19. LOOP
  20. FETCH cur2 INTO a, b;
  21. EXIT WHEN cur2%NOTFOUND;
  22. SELECT a, b;
  23. END LOOP;
  24. CLOSE cur2;
  25. END; //
  26. greatsql> CALL p1() //
  27. +------+------+
  28. | a | b |
  29. +------+------+
  30. | 1 | row1 |
  31. +------+------+
  32. 1 row in set (0.00 sec)
  33. +------+------+
  34. | a | b |
  35. +------+------+
  36. | 2 | row2 |
  37. +------+------+
  38. 1 row in set (0.00 sec)
  39. Query OK, 0 rows affected (0.00 sec)
    1. 示例9:SELECT REF CURSOR INTO REF CURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE FUNCTION return_cur RETURN SYS_REFCURSOR
  5. AS
  6. cur1 SYS_REFCURSOR;
  7. BEGIN
  8. OPEN cur1 FOR SELECT * FROM t1 WHERE a < 3;
  9. RETURN cur1;
  10. END; //
  11. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  12. cur1 SYS_REFCURSOR;
  13. cur2 SYS_REFCURSOR;
  14. a INT;
  15. b VARCHAR(20);
  16. BEGIN
  17. cur1 := return_cur();
  18. SELECT cur1 INTO cur2;
  19. LOOP
  20. FETCH cur2 INTO a, b;
  21. EXIT WHEN cur2%NOTFOUND;
  22. SELECT a, b;
  23. END LOOP;
  24. CLOSE cur2;
  25. END; //
  26. greatsql> CALL p1() //
  27. +------+------+
  28. | a | b |
  29. +------+------+
  30. | 1 | row1 |
  31. +------+------+
  32. 1 row in set (0.00 sec)
  33. +------+------+
  34. | a | b |
  35. +------+------+
  36. | 2 | row2 |
  37. +------+------+
  38. 1 row in set (0.00 sec)
  39. Query OK, 0 rows affected (0.00 sec)
    1. 示例10:SELECT SYS_REFCURSOR FUNCTION
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE FUNCTION return_cur RETURN SYS_REFCURSOR
  5. AS
  6. cur1 SYS_REFCURSOR;
  7. BEGIN
  8. OPEN cur1 FOR SELECT 1, 'row1';
  9. RETURN cur1;
  10. END; //
  11. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  12. type dr_CURSOR IS REF CURSOR;
  13. cur1 dr_CURSOR;
  14. BEGIN
  15. SELECT return_cur() FROM t1;
  16. END; //
  17. greatsql> CALL p1() //
  18. ERROR 1235 (42000): This version of MySQL doesn't yet support 'REF CURSOR used in table'
    1. 示例11:参数返回
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE PROCEDURE sp_return(ref_rs OUT SYS_REFCURSOR) IS
  5. sql1 VARCHAR(100);
  6. BEGIN
  7. sql1 := 'SELECT a, b FROM t1 WHERE a > 2';
  8. OPEN ref_rs FOR sql1;
  9. END; //
  10. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  11. a INT;
  12. BEGIN
  13. CALL sp_return(a);
  14. END; //
  15. greatsql> CALL p1() //
  16. ERROR 7553 (HY000): inconsistent datatypes: udt type and non udt type
    1. 示例12:OPEN FORCLOSE 以及赋值对其他 REF CURSOR 的影响
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. -- 1OPEN FOR的影响范围
  5. greatsql> CREATE OR REPLACE FUNCTION return_cur RETURN SYS_REFCURSOR
  6. AS
  7. cur1 SYS_REFCURSOR;
  8. BEGIN
  9. OPEN cur1 FOR SELECT * FROM t1 WHERE a < 3;
  10. RETURN cur1;
  11. END; //
  12. greatsql> CREATE OR REPLACE PROCEDURE p1() IS
  13. v_a INT;
  14. v_b VARCHAR(30);
  15. cur1 SYS_REFCURSOR;
  16. cur2 SYS_REFCURSOR;
  17. BEGIN
  18. cur1 := return_cur();
  19. SELECT cur1 INTO cur2 FROM DUAL;
  20. OPEN cur2 FOR SELECT * FROM t1 WHERE a = 1;
  21. LOOP
  22. FETCH cur1 INTO v_a, v_b;
  23. EXIT WHEN cur1%NOTFOUND;
  24. SELECT v_a, v_b;
  25. END LOOP;
  26. CLOSE cur2;
  27. END; //
  28. -- OPEN FOR以后影响了所有关联过的REF CURSOR
  29. greatsql> CALL p1() //
  30. +------+------+
  31. | v_a | v_b |
  32. +------+------+
  33. | 1 | row1 |
  34. +------+------+
  35. 1 row in set (0.00 sec)
  36. Query OK, 0 rows affected (0.00 sec)
  37. -- 2CLOSE的影响范围
  38. -- 略过FUNCTION return_cur()的创建过程,复用上例结果
  39. greatsql> CREATE OR REPLACE PROCEDURE p1() IS
  40. a INT;
  41. b VARCHAR(30);
  42. cur1 SYS_REFCURSOR;
  43. cur2 SYS_REFCURSOR;
  44. BEGIN
  45. cur1 := return_cur();
  46. SELECT cur1 INTO cur2 FROM DUAL;
  47. CLOSE cur2; -- 在打开游标cur1之前关闭cur2,则cur1受到影响,如果放在FETCH cur1之后就可以
  48. FETCH cur1 INTO a, b;
  49. END; //
  50. -- CLOSE以后影响了所有关联REF CURSOR
  51. greatsql> CALL p1() //
  52. ERROR 1324 (42000): Undefined CURSOR: cur1
  53. -- 3、单纯set的影响范围
  54. CREATE OR REPLACE FUNCTION return_cur1 RETURN SYS_REFCURSOR
  55. AS
  56. cur1 SYS_REFCURSOR;
  57. BEGIN
  58. OPEN cur1 FOR SELECT * FROM t1 WHERE a = 2;
  59. RETURN cur1;
  60. END; //
  61. CREATE OR REPLACE PROCEDURE p1() IS
  62. v_a INT;
  63. v_b VARCHAR(30);
  64. cur1 SYS_REFCURSOR;
  65. cur2 SYS_REFCURSOR;
  66. cur3 SYS_REFCURSOR;
  67. BEGIN
  68. cur1 := return_cur();
  69. SELECT cur1 INTO cur2 FROM DUAL;
  70. cur3 := cur2;
  71. cur1 := return_cur1();
  72. LOOP
  73. FETCH cur3 INTO v_a, v_b;
  74. EXIT WHEN cur3%NOTFOUND;
  75. SELECT v_a, v_b;
  76. END LOOP;
  77. LOOP
  78. FETCH cur1 INTO v_a, v_b;
  79. EXIT WHEN cur1%NOTFOUND;
  80. SELECT v_a, v_b;
  81. END LOOP;
  82. END; //
  83. -- 从结果可以看到,最初的cur1被改变后,只影响了自己,没有影响被它赋值的cur2cur3
  84. greatsql> CALL p1() //
  85. +------+------+
  86. | v_a | v_b |
  87. +------+------+
  88. | 1 | row1 |
  89. +------+------+
  90. 1 row in set (0.00 sec)
  91. +------+------+
  92. | v_a | v_b |
  93. +------+------+
  94. | 2 | row2 |
  95. +------+------+
  96. 1 row in set (0.00 sec)
  97. +------+------+
  98. | v_a | v_b |
  99. +------+------+
  100. | 2 | row2 |
  101. +------+------+
  102. 1 row in set (0.00 sec)
  103. Query OK, 0 rows affected (0.00 sec)
    1. 示例13:CLOSE REF CURSOR 对关联游标的影响
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE FUNCTION return_cur RETURN SYS_REFCURSOR
  5. AS
  6. cur1 SYS_REFCURSOR;
  7. BEGIN
  8. OPEN cur1 FOR SELECT * FROM t1 WHERE a < 3;
  9. RETURN cur1;
  10. END; //
  11. greatsql> CREATE OR REPLACE PROCEDURE p1() IS
  12. v_a INT;
  13. v_b VARCHAR(30);
  14. cur1 SYS_REFCURSOR;
  15. cur2 SYS_REFCURSOR;
  16. BEGIN
  17. cur1 := return_cur();
  18. SELECT cur1 INTO cur2 FROM DUAL;
  19. CLOSE cur2;
  20. -- GreatSQL中这里再次被OPEN是允许的,但在Oracle中会报告invalid CURSOR错误
  21. OPEN cur1 FOR SELECT * FROM t1 WHERE a = 1;
  22. LOOP
  23. FETCH cur1 INTO v_a, v_b;
  24. EXIT WHEN cur1%NOTFOUND;
  25. SELECT v_a, v_b;
  26. END LOOP;
  27. END; //
  28. greatsql> CALL p1() //
  29. +------+------+
  30. | v_a | v_b |
  31. +------+------+
  32. | 1 | row1 |
  33. +------+------+
  34. 1 row in set (0.00 sec)
  35. Query OK, 0 rows affected (0.00 sec)
    1. 示例14:in SYS_REFCURSOR
  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> SET udt_format_result = 'DBA';
  3. greatsql> DELIMITER //
  4. greatsql> CREATE OR REPLACE PROCEDURE sp_return(ref_rs in SYS_REFCURSOR) IS
  5. sql1 VARCHAR(100);
  6. v_a INT;
  7. v_b VARCHAR(30);
  8. BEGIN
  9. FETCH ref_rs INTO v_a, v_b;
  10. SELECT v_a, v_b;
  11. END //
  12. greatsql> CREATE OR REPLACE PROCEDURE p1() AS
  13. cur1 SYS_REFCURSOR;
  14. cur2 SYS_REFCURSOR;
  15. v_a INT;
  16. v_b VARCHAR(20);
  17. BEGIN
  18. OPEN cur1 FOR SELECT * FROM t1;
  19. CALL sp_return(cur1);
  20. SELECT 'AFTER CALL sp_return';
  21. LOOP
  22. FETCH cur1 INTO v_a, v_b;
  23. EXIT WHEN cur1%NOTFOUND;
  24. SELECT v_a, v_b;
  25. END LOOP;
  26. CLOSE cur1;
  27. END //
  28. greatsql> CALL p1() //
  29. +------+------+
  30. | v_a | v_b |
  31. +------+------+
  32. | 1 | row1 |
  33. +------+------+
  34. 1 row in set (0.00 sec)
  35. +----------------------+
  36. | AFTER CALL sp_return |
  37. +----------------------+
  38. | AFTER CALL sp_return |
  39. +----------------------+
  40. 1 row in set (0.00 sec)
  41. +------+------+
  42. | v_a | v_b |
  43. +------+------+
  44. | 2 | row2 |
  45. +------+------+
  46. 1 row in set (0.00 sec)
  47. +------+------+
  48. | v_a | v_b |
  49. +------+------+
  50. | 3 | row3 |
  51. +------+------+
  52. 1 row in set (0.00 sec)
  53. Query OK, 0 rows affected (0.00 sec)

问题反馈

联系我们

扫码关注微信公众号

greatsql-wx