一、存储过程增强
openGauss6.0新版本数据库存储过程增强,游标支持嵌套定义,cursor 定义中可以再定义子 cursor。
(一)应用场景
1.处理复杂的查询逻辑:当需要在查询过程中进行多次筛选或处理时,嵌套游标可以提供更大的灵活性和控制能力。例如,在一个外层游标中处理每一行数据,然后使用内层游标进一步处理这些数据。
2.逐行处理数据:在处理大量数据时,嵌套游标可以逐行读取和处理数据,避免一次性加载所有数据到内存中,从而减少内存消耗和提高处理效率。
3.动态查询:在某些情况下,查询条件需要根据前一个查询的结果动态生成。嵌套游标可以在外层游标中获取某些条件,然后使用这些条件在内层游标中进行进一步的查询。
(二)功能测试
1.创建测试表
source_db=# create table family_tbl(id int, name varchar, job varchar);
CREATE TABLE
source_db=# create table age_tbl(id int, age int);
CREATE TABLE
source_db=# insert into family_tbl values (1, 'yyf', 'IT'),(2, 'jjj', 'NURSE'),(3, 'yyz', 'STUDENT');
INSERT 0 3
source_db=# insert into age_tbl values (1, 32),(2, 31),(3, 3);
INSERT 0 3
2.在存储过程中使用游标嵌套
source_db=# create or replace procedure p1
source_db-# as
source_db$# age_temp int;
source_db$# name_temp varchar;
source_db$# type emp_cur_type is ref cursor;
source_db$# c2 emp_cur_type;
source_db$# cursor c1 is SELECT t.age, CURSOR(SELECT name FROM family_tbl t1 where t1.id = t.id) abc FROM age_tbl t;
source_db$# begin
source_db$# OPEN c1;
source_db$# loop
source_db$# fetch c1 into age_temp, c2;
source_db$# exit when c1%notfound;
source_db$# raise notice 'age : %',age_temp;
source_db$# loop
source_db$# fetch c2 into name_temp;
source_db$# exit when c2%notfound;
source_db$# raise notice 'name : %', name_temp;
source_db$# end loop;
source_db$# close c2;
source_db$# end loop;
source_db$# CLOSE c1;
source_db$# end;
source_db$# /
CREATE PROCEDURE
3.调用存储过程
source_db=# call p1();
NOTICE: age : 32
NOTICE: name : yyf
NOTICE: age : 31
NOTICE: name : jjj
NOTICE: age : 3
NOTICE: name : yyz
p1
----
二、SQL功能增强
(一)管道函数
openGauss6.0版本支持PIPELINED 管道函数,函数可以返回行集合。
1.应用场景
在openGauss数据库中,管道函数是一种特殊的函数,用于流式处理大量数据。管道函数可以分批次处理数据,而不是一次性加载全部数据到内存中,这对于处理大规模数据集非常有用。
2.功能测试
(1)创建管道函数
source_db=# create or replace type MsgType as table of varchar2(4000);
CREATE TYPE
source_db=# create or replace function f_pipeline_test return MsgType
source_db-# PIPELINED as
source_db$# begin
source_db$# for i in 1 .. 10 loop
source_db$# pipe row('Iteration ' || i || ' at ' || CURRENT_TIMESTAMP);
source_db$# pg_sleep(1);
source_db$# end loop;
source_db$# pipe row('All done!');
source_db$# return;
source_db$# end;
source_db$# /
CREATE FUNCTION
(2)调用管道函数
source_db=# select * from table( f_pipeline_test );
f_pipeline_test
-----------------------------------------------
Iteration 1 at 2024-11-13 15:51:10.040849+08
Iteration 2 at 2024-11-13 15:51:10.04128+08
Iteration 3 at 2024-11-13 15:51:11.04244+08
Iteration 4 at 2024-11-13 15:51:12.043706+08
Iteration 5 at 2024-11-13 15:51:13.044874+08
Iteration 6 at 2024-11-13 15:51:14.046069+08
Iteration 7 at 2024-11-13 15:51:15.047488+08
Iteration 8 at 2024-11-13 15:51:16.048629+08
Iteration 9 at 2024-11-13 15:51:17.049801+08
Iteration 10 at 2024-11-13 15:51:18.050931+08
All done!
(11 rows)
(二)行列转换
openGauss6.0版本中,SELECT 语句支持通过 ROTATE 和 NOT ROTATE 子句进行行列转换。
1.应用场景
(1)数据透视:将原始数据按照某一列进行分组,并将其他列的值进行合并,生成透视表。例如,在Oracle中,可以使用PIVOT函数来实现行转列操作,从而生成所需的数据透视表。
(2)数据汇总:将多个行数据按照指定的列进行汇总,生成一条汇总数据。这种操作常用于将某一列的值作为新的列名,并将对应的值填入相应的位置。
(3)数据展示:将多条行数据进行合并,生成一行展示数据。这种操作可以使数据更加紧凑和易于展示。
(4)数据分析:在数据分析中,行转列函数可以用于对数据进行重排或重新组织,例如,通过行列转换函数进行数据透视表操作、数据聚合等。
2.功能测试
(1)创建表t_original_orders
source_db=# create table t_original_orders (id int, year int, order_mode text, order_total int);
(2)向表t_original_orders中插入记录
source_db=# insert into t_original_orders values (1,2020,'direct',5000), (2,2020,'online',1000), (3,2021,'online',1000), (4,2021,'direct',1000), (5,2022,'direct',5000), (6,2020,'direct',500);
INSERT 0 6
source_db=# select * from t_original_orders;
id | year | order_mode | order_total
----+------+------------+-------------
1 | 2020 | direct | 5000
2 | 2020 | online | 1000
3 | 2021 | online | 1000
4 | 2021 | direct | 1000
5 | 2022 | direct | 5000
6 | 2020 | direct | 500
(6 rows)
(3)使用rotate将表t_original_orders中数据行转列输出
source_db=# select * from ( select year, order_mode, order_total from t_original_orders) rotate (sum(order_total) for order_mode in ('direct' as store, 'online' as internet)) order by year;
year | store | internet
------+-------+----------
2020 | 5500 | 1000
2021 | 1000 | 1000
2022 | 5000 |
(4)创建表t_rotate_orders
source_db=# create table t_rotate_orders as (select * from (select year, order_mode, order_total from t_original_orders) as t rotate (sum(order_total) for order_mode in ('direct' as store, 'online' as internet)) order by year);
INSERT 0 3
(5)使用not rotate将表t_rotate_orders中数据列转行输出
source_db=# select * from t_rotate_orders not rotate ( yearly_total for order_mode in ( store as 'direct', internet as 'online'));
year | order_mode | yearly_total
------+------------+--------------
2020 | direct | 5500
2021 | direct | 1000
2022 | direct | 5000
2020 | online | 1000
2021 | online | 1000
(5 rows)