Oracle兼容-存储过程-GOTO
1. 语法
1. GOTO label
label后面的语句块支持以下几种用法:
1. {
2. sp_proc_stmt_statement
3. | exit [label]/exit [label] when
4. | leave label
5. | iterate label
6. | goto label
7. | open cursor
8. | fetch cursor
9. | close cursor
10. | return
11. | if elsif
12. | case when
13. | forall loop
14. | declare body begin .. end
15. | sp_labeled_control
16. }
18. sp_proc_stmt_statement:
19. {
20. DDL_statement ...
21. DML_statement ...
22. SHOW_statement ...
23. }
25. sp_labeled_control:
26. {
27. for_loop_stmt
28. | while loop
29. | loop end loop
30. | repeat until
31. }
2. 定义和用法
GreatSQL的存储过程中支持用 label 标记位置,并用 GOTO label 跳到指定标记位置。
注意:谨慎使 GOTO 语法,容易造成死循环。
3. Oracle兼容说明
GreatSQL的存储过程中支持用 label 标记位置,并用 GOTO label 跳到指定标记位置。该用法如下所述:
- 如果
GOTO语句退出游标FOR LOOP循环语句块,则游标将会被关闭。 - 不能利用
GOTO语句将控制转移到IF / CASE / LOOP等语句或子块中。 - 不能利用
GOTO语句将控制从一个IF语句子句转移到另一个,或从一个CASE WHEN子句转移到另一个。 - 不能利用
GOTO语句将控制转移出子程序。 - 不能利用
GOTO语句将控制转移到异常处理程序中。 - 不能利用
GOTO语句将控制从异常处理程序转移回当前块(但它可以将控制从异常处理程序转移到封闭块)。 - 可以利用
GOTO可以跳转到除了以上提到的几种情况之外的任何地方,GreatSQL原生的LEAVE label只能在LOOP和BEGIN END模块内使用。 - 只支持单个label标记,不支持多个label同时标记位置。如下例所示:
1. <<label1>>
2. <<label12>> -- 不支持同时标记位置,二者必须删掉一个
3. a := b;
- 支持在
EVENT / TRIGGER / PACKAGE / 匿名块内使用GOTO语法。如果在EVENT / TRIGGER中因逻辑错误可能造成死循环,会造成系统资源浪费,应该谨慎使用。
4. 示例
-
- 示例1:往前跳转
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. greatsql> CREATE OR REPLACE PROCEDURE goto_sp1(v_str IN OUT VARCHAR)
5. AS
6. BEGIN
7. v_str := 'label1';
9. GOTO label1;
11. <<label1>>
12. -- 又立即跳转到label2,即RETURN完成
13. GOTO label2;
14. v_str := 'label2';
16. <<label2>>
17. RETURN;
18. END; //
20. greatsql> CALL goto_sp1(@v_str) //
21. Query OK, 0 rows affected (0.00 sec)
23. greatsql> SELECT @v_str //
24. +--------+
25. | @v_str |
26. +--------+
27. | label1 |
28. +--------+
29. 1 row in set (0.00 sec)
-
- 示例2:往回跳转
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. greatsql> CREATE OR REPLACE PROCEDURE goto_sp2(v_str IN OUT VARCHAR)
5. AS
6. BEGIN
7. v_str := 'label1';
9. <<label1>>
10. IF (v_str = 'label2') THEN
11. RETURN;
12. END IF;
14. v_str := 'label2';
15. GOTO label1;
16. END; //
18. greatsql> CALL goto_sp2(@v_str) //
20. greatsql> SELECT @v_str //
21. +--------+
22. | @v_str |
23. +--------+
24. | label2 |
25. +--------+
26. 1 row in set (0.00 sec)
-
- 示例3:支持条件判断处理
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. greatsql> CREATE OR REPLACE PROCEDURE goto_sp3(n INT, ret OUT VARCHAR)
5. AS
6. a INT;
7. BEGIN
8. <<label1>>
9. BEGIN
10. SELECT a INTO a FROM information_schema.TABLES LIMIT n;
11. EXCEPTION
12. WHEN TOO_MANY_ROWS THEN
13. BEGIN
14. ret := ret||'--- too_many_rows cought 1 ---';
15. GOTO label2;
16. END;
17. WHEN NO_DATA_FOUND THEN
18. BEGIN
19. ret := ret||'--- no_data_found cought 1 ---';
20. n := 2;
21. SELECT a INTO a FROM information_schema.TABLES LIMIT n;
22. EXCEPTION
23. WHEN TOO_MANY_ROWS THEN
24. BEGIN
25. ret := ret||'--- too_many_rows cought 2 ---';
26. GOTO label1;
27. END;
28. WHEN NO_DATA_FOUND THEN ret := '--- no_data_found cought 2 ---';
29. END;
30. END;
32. SET ret := ret||' error ';
33. <<label2>>
34. RETURN;
35. END; //
37. greatsql> CALL goto_sp3(0, @ret) //
38. Query OK, 0 rows affected (0.00 sec)
40. greatsql> SELECT @ret //
41. +--------------------------------------------------------------------------------------------+
42. | @ret |
43. +--------------------------------------------------------------------------------------------+
44. | --- no_data_found cought 1 ------ too_many_rows cought 2 ------ too_many_rows cought 1 --- |
45. +--------------------------------------------------------------------------------------------+
46. 1 row in set (0.00 sec)
48. greatsql> CALL goto_sp3(0, @ret) //
49. Query OK, 0 rows affected (0.00 sec)
51. greatsql> SELECT @ret //
52. +--------------------------------------------------------------------------------------------+
53. | @ret |
54. +--------------------------------------------------------------------------------------------+
55. | --- no_data_found cought 1 ------ too_many_rows cought 2 ------ too_many_rows cought 1 --- |
56. +--------------------------------------------------------------------------------------------+
57. 1 row in set (0.00 sec)
59. greatsql> CALL goto_sp3(3, @ret) //
60. Query OK, 0 rows affected (0.00 sec)
62. greatsql> SELECT @ret //
63. +--------------------------------+
64. | @ret |
65. +--------------------------------+
66. | --- too_many_rows cought 1 --- |
67. +--------------------------------+
68. 1 row in set (0.00 sec)
70. greatsql> CALL goto_sp3(1, @ret) //
71. Query OK, 1 row affected (0.00 sec)
73. greatsql> SELECT @ret //
74. +---------+
75. | @ret |
76. +---------+
77. | error |
78. +---------+
79. 1 row in set (0.00 sec)
-
- 示例4:不能跳转到
CASE WHEN语句块
- 示例4:不能跳转到
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. greatsql> CREATE OR REPLACE PROCEDURE goto_sp4()
5. AS
6. a INT;
7. BEGIN
8. GOTO label1;
9. case 1
10. WHEN 1 THEN
11. <<label1>>
12. a := 2;
13. WHEN 2 THEN
14. a := 1;
15. END CASE;
16. RETURN;
17. END; //
18. ERROR 1308 (42000): GOTO with no matching label: label1
-
- 示例5:不能跳转到另一个
CASE WHEN语句块
- 示例5:不能跳转到另一个
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. greatsql> CREATE OR REPLACE PROCEDURE goto_sp5()
5. AS
6. a INT;
7. BEGIN
8. CASE 1
9. WHEN 1 THEN
10. <<label1>>
11. a := 2;
12. WHEN 2 THEN
13. a := 1;
14. GOTO label1;
15. end case;
16. RETURN;
17. END; //
18. ERROR 1308 (42000): GOTO with no matching label: label1
问题反馈
联系我们
扫码关注微信公众号

