Oracle兼容-存储过程-BULK COLLECT
1. 语法
1. [SELECT|FETCH] .. BULK COLLECT INTO
2. 定义和用法
GreatSQL存储过程中支持用 SELECT|FETCH .. BULK COLLECT INTO 获取多行数据。该用法如下所述:
-
- 支持用
SELECT .. BULK COLLECT INTO语法取表中多行数据,并赋值给TABLE类型变量。
- 支持用
-
- 支持用
FETCH .. BULK COLLECT INTO .. LIMIT n语法取游标中的多行数据,并赋值给TABLE类型变量。
- 支持用
3. Oracle兼容说明
在 ORACLE 模式下,GreatSQL存储过程支持 [SELECT|FETCH] .. BULK COLLECT INTO 用法。该用法如下所述:
- 在
[SELECT|FETCH] .. BULK COLLECT INTO var中的变量var只支持一层表类型,比如var,不支持a.b.var这种变量类型。 - 在
FETCH .. BULK COLLECT INTO var中如果不加LIMIT n子句,则默认一次性最多读取@@select_bulk_into_batch行数据,其可选范围 [1, 65535],默认值为 10000。如果制定了LIMIT n子句,但n > @@select_bulk_into_batch时,会提示错误:ER_WRONG_BATCH_FOR_BULK_INTO,这是为了保证不发生内存溢出。 - 新增系统选项
select_bulk_into_batch使用说明:
| 参数 | 说明 |
|---|---|
| 参数名称 | select_bulk_into_batch |
| 参数解释 | FETCH .. BULK COLLECT INTO var 时一次性最多读取的行数限制 |
| 参数类型 | INT |
| 参数取值范围(行) | [1, 65535] |
| 默认值(行) | 10000 |
| 建议最佳数值(行) | 1000 |
| 使用示例 | SET @@select_bulk_into_batch = n; SHOW VARIABLES LIKE ‘select_bulk_into_batch’; |
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') ;
4. greatsql> CREATE TABLE t2 (a INT NOT NULL, b VARCHAR(20) NOT NULL);
-
- 示例1:
SELECT BULK COLLECT
- 示例1:
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. CREATE OR REPLACE PROCEDURE bulk_sp1() AS
5. TYPE udtt IS TABLE OF t1%ROWTYPE INDEX BY BINARY_INTEGER;
6. udtt_t1 udtt;
7. BEGIN
8. SELECT * BULK COLLECT INTO udtt_t1 FROM t1;
9. FOR i IN udtt_t1.FIRST .. udtt_t1.LAST LOOP
10. SELECT udtt_t1(i).a, udtt_t1(i).b;
11. END LOOP;
12. END; //
14. greatsql> CALL bulk_sp1() //
15. +--------------+--------------+
16. | udtt_t1(i).a | udtt_t1(i).b |
17. +--------------+--------------+
18. | 1 | row1 |
19. +--------------+--------------+
20. 1 row in set (0.00 sec)
22. +--------------+--------------+
23. | udtt_t1(i).a | udtt_t1(i).b |
24. +--------------+--------------+
25. | 2 | row2 |
26. +--------------+--------------+
27. 1 row in set (0.00 sec)
29. +--------------+--------------+
30. | udtt_t1(i).a | udtt_t1(i).b |
31. +--------------+--------------+
32. | 3 | row3 |
33. +--------------+--------------+
34. 1 row in set (0.00 sec)
36. Query OK, 0 rows affected (0.00 sec)
-
- 示例2:
FETCH BULK COLLECT
- 示例2:
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> DELIMITER //
4. greatsql> CREATE OR REPLACE PROCEDURE bulk_sp2(v_a INT) AS
5. TYPE t1_record IS RECORD(
6. id INT := 1,
7. name_d VARCHAR(20)
8. );
9. TYPE t1_list IS TABLE OF t1_record INDEX BY BINARY_INTEGER;
10. t1_record_val t1_list;
12. CURSOR c(v_a INT) IS SELECT a, b FROM t1 WHERE a = v_a;
13. BEGIN
14. OPEN c(v_a);
16. -- 这里实际只获取到两行数据,而LIMIT限定为3,不会报错
17. FETCH c BULK COLLECT INTO t1_record_val LIMIT 3;
19. -- 目前FORALL后面只支持INSERT操作
20. FORALL i IN t1_record_val.FIRST .. t1_record_val.LAST
21. INSERT INTO t2 VALUES t1_record_val(i);
23. CLOSE c;
24. END; //
26. greatsql> CALL bulk_sp2(1) //
27. Query OK, 1 row affected (0.00 sec)
29. greatsql> SELECT * FROM t2 //
30. +---+------+
31. | a | b |
32. +---+------+
33. | 1 | row1 |
34. +---+------+
35. 1 row in set (0.01 sec)
-
- 示例3:
FETCH BULK COLLECT INTO batch
- 示例3:
1. greatsql> SET sql_mode = ORACLE;
2. greatsql> SET select_bulk_into_batch = 5;
3. greatsql> DELIMITER //
5. greatsql> CREATE OR REPLACE PROCEDURE bulk_sp3() AS
6. CURSOR cur1 IS SELECT * FROM t1;
7. TYPE udtt IS TABLE OF t1%ROWTYPE INDEX BY BINARY_INTEGER;
8. udtt_t1 udtt;
9. v_i INT := 0;
10. BEGIN
11. OPEN cur1;
12. LOOP
13. SELECT v_i;
15. -- 因为fetch只会执行2次,因此第三次就可以退出了。
16. EXIT WHEN v_i % @@select_bulk_into_batch > 1;
18. FETCH cur1 BULK COLLECT INTO udtt_t1;
20. FOR i IN udtt_t1.FIRST .. udtt_t1.LAST LOOP
21. SELECT udtt_t1(i).a, udtt_t1(i).b;
23. END LOOP;
25. v_i := v_i + 1;
26. END LOOP;
27. CLOSE cur1;
28. END; //
30. greatsql> CALL bulk_sp3() //
31. +------+
32. | v_i |
33. +------+
34. | 0 |
35. +------+
36. 1 row in set (0.00 sec)
38. +--------------+--------------+
39. | udtt_t1(i).a | udtt_t1(i).b |
40. +--------------+--------------+
41. | 1 | row1 |
42. +--------------+--------------+
43. 1 row in set (0.00 sec)
45. +--------------+--------------+
46. | udtt_t1(i).a | udtt_t1(i).b |
47. +--------------+--------------+
48. | 2 | row2 |
49. +--------------+--------------+
50. 1 row in set (0.00 sec)
52. +--------------+--------------+
53. | udtt_t1(i).a | udtt_t1(i).b |
54. +--------------+--------------+
55. | 3 | row3 |
56. +--------------+--------------+
57. 1 row in set (0.00 sec)
59. +------+
60. | v_i |
61. +------+
62. | 1 |
63. +------+
64. 1 row in set (0.00 sec)
66. +------+
67. | v_i |
68. +------+
69. | 2 |
70. +------+
71. 1 row in set (0.00 sec)
73. Query OK, 0 rows affected (0.00 sec)
更多关联用法:
问题反馈
联系我们
扫码关注微信公众号

