金仓数据库KingbaseES PLSQL 游标变量基础
关键字:
KingbaseES、PLSQL、游标变量、人大金仓、KingbaseES
为什么要有游标变量?
在KingbaseES中,已经提供了普通游标(包括显式游标和隐式游标)的功能,通过该功能,用户可以在PLSQL的代码块中操作一个查询结果集中的多条数据。那么为什么还要有游标变量呢?要回答这个问题,我们首先要知道普通游标的局限性和缺点,无论是显式游标还是隐式游标,它们都是静态的,比如说,当你定义了一个显式游标c1,这个c1就跟一个查询结果集绑定了,在c1的整个生命周期中,它只能操作跟它绑定的这个查询结果集中的数据,这样的话,每有一个查询结果集,就要定义一个与之相关的显式游标,这种做法缺乏灵活性。因此,游标变量就应运而生了。
游标变量的优点
- 跟静态游标(为了跟动态的游标变量作对比,我们将显式游标和隐式游标统称为静态游标)不同的是,游标变量具有动态性,一个游标变量在它的生命周期内可以指向不同的查询结果集,并且还可以作为参数传递,返回值返回。这也就意味着它可以在不同的PLSQL程序间,甚至是客户端和服务器的PLSQL程序间传递查询的结果集,这为PLSQL程序编写提供了很大的灵活性。可以将静态游标理解为程序中的一个const常量,一经定义之后,不能再改变,而游标变量就是一个程序中的普通变量,可以给它赋不同的值,也可以将它作为函数的参数,或者返回值。
- 游标变量也继承了静态游标的完整功能。我们可以在游标变量中进行OPEN、CLOSE和FETCH,也可以为游标变量引用标准的游标属性:%ISOPEN、%FOUND、%NOTFOUND和%ROWCOUNT等。
游标变量基础用法
下面,将介绍一些游标变量的基础用法,也就是继承于静态游标的功能部分。
- 创建游标变量数据类型:跟其他的变量类似,任何一个游标变量都属于一个特定的数据类型,在使用游标变量之前,必须先定义一个游标变量的数据类型。在KingbaseES中,也将游标变量的数据类型称为REF CURSOR类型。创建游标变量类型的语法如下:
TYPE cursor_type_name IS REF CURSOR [ RETURN return_type ];
其中,cursor_type_name是游标变量类型的名称,return_type是游标类型返回的数据格式,其余的都是语法中的关键字。return_type可以是对标准的游标RETURN子句有效的任何数据类型,也可以是通过%ROWTYPE属性定义的;RETURN return_type是可省略的,如果在定义了时指明了返回的return_type,那就是强游标类型,否则就是弱游标类型。
TYPE strong_type IS REF CURSOR RETURN strong%ROWTYPE; --强游标类型
TYPE weak_type IS REF CURSOR; --弱游标类型
KingbaseES提供了系统预定义的弱游标类型,命名为SYS_REFCURSOR。因此,当我们要定义一个弱游标变量时,无需再定义自己的弱游标类型,只需使用系统预定义的就行:
DECLARE
my_cursor SYS_REFCURSOR;
- 声明游标变量:当创建了一个游标变量的数据类型后,就可以声明与之相对应的游标变量了,声明游标变量的语法是:
cursor_name cursor_type_name;
其中,cursor_type_name是之前已经创建的游标变量的数据类型,cursor_name是游标变量的名称。这里我们要注意区分声明游标变量和创建实际的游标对象之间的差异,声明游标变量并不会创建一个游标对象,我们必须使用OPEN FOR语句来创建实际的游标对象并将其分配给声明过的游标变量。
- 从游标变量中提取数据:跟静态游标类似,我们可以使用游标变量来从一个查询结果集中提取数据,在提取数据之前要先使用OPEN FOR语句将某个查询结果集和声明的游标变量进行绑定,然后使用FETCH语句来提取数据,最后使用CLOSE语句关闭游标变量。这里我们通过一个简单的案例来说明具体的用法。
/创建一个临时存储学生信息的表stu_temp/
DROP TABLE IF EXISTS stu_temp;
CREATE TABLE stu_temp(id INT, name VARCHAR(10));
/向表中插入一些数据/
insert into stu_temp values (1001, 'xs');
insert into stu_temp values (1002, 'xd');
insert into stu_temp values (1003, 'xc');
\set SQLTERM /
DECLARE
/创建游标变量数据类型stu_cursor/
TYPE stu_cursor IS REF CURSOR RETURN stu_temp%ROWTYPE;
/声明一个stu_cursor类型的强游标变量strong_cur/
strong_cur stu_cursor;
v_id stu_temp.id%TYPE;
v_name stu_temp.name%TYPE;
BEGIN
/使用OPEN..FOR语句打开游标变量,并让其指向一个特定的查询结果集/
OPEN strong_cur FOR
SELECT id, name FROM stu_temp
WHERE id > 1000;
LOOP
/使用FETCH语句提取数据/
FETCH strong_cur INTO v_id, v_name;
/为游标变量引用游标属性%NOTFOUND/
EXIT WHEN strong_cur%NOTFOUND;
RAISE NOTICE 'v_id: %, v_name: %', v_id, v_name;
END LOOP;
/关闭游标变量/
CLOSE strong_cur;
END;
/
程序运行结果: