返回首页

gbase数据、南大通用产品文档:GBase8s处理未知的返回值

更新日期:2024年09月11日

此部分描述如何使用系统描述符区域来保存动态地执行的用户定义的函数返回的值。


要使用系统描述符区域来处理未知的函数返回值:

组装并准备 EXECUTE FUNCTION 语句。
EXECUTE FUNCTION 语句不可包括 INTO 子句。

以 ALLOCATE DESCRIPTOR 语句分配系统描述符区域。

以 DESCRIBE...USING SQL DESCRIPTOR 语句来确定返回的一个值(或多个值)的
数目和数据类型。
DESCRIBE...USING SQL DESCRIPTOR 语句为用户定义的函数返回的每一值填充项
描述符。

在 DESCRIBE 语句之后,
对于 SQ_EXECPROC 定义了的常量,
您可测试 SQLCODE
变量(sqlca.sqlcode),来检查准备好的 EXECUTE FUNCTION 语句。
在 sqlstype.h 头文件中定义此常量。

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 526 -

执行 EXECUTE FUNCTION 语句,并将返回值存储在系统描述符区域中。
您用来执行用户定义的函数的语句,依赖于该函数是非游标函数,还是游标函数。后
面的部分讨论如何执行每一类函数。

以 DEALLOCATE DESCRIPTOR 语句释放系统描述符区域。
执行非游标函数
非游标函数仅将一行返回值返回给应用程序。请使用 EXECUTE...INTO SQL
DESCRIPTOR 语句来执行该函数,并将返回的一个值或多个值保存在系统描述符区域中。


未显式地定义作为迭代函数的外部函数,仅返回单行数据。因此,您可使用
EXECUTE...INTO SQL DESCRIPTOR 来动态地执行最外部的函数。
此单行数据仅由一个值
组成,因为外部函数仅可返回单个值。系统描述符区域仅包含带有单个返回值的一个项描
述符。

其 RETURN 语句不包括 WITH RESUME 关键字的 SPL 函数,仅返回单行数据。
因此,您可使用 EXECUTE...INTO SQL DESCRIPTOR 来动态地执行大多数 SPL 函数。
SPL 函数可一次返回一个或多个值,因此,系统描述符区域包含一个或多个项描述符。

重要:
由于您通常不知道用户定义的函数返回的行数,
因此,
不可保证仅返回一行。
如果您不使用游标来执行游标函数,则 GBase 8s ESQL/C 生成运行时刻错误。因此,总是
将用户定义的函数与函数游标相关联,是一种好的做法。

下列程序片段动态地执行名为 items_pct 的 SPL 函数。
此 SPL 函数计算给定的生产
商代表的项占 items 表中所有项的总价的百分比。对于选中的生产商,它接受一个参数
manu_code 值,且它返回该百分比作为十进制值。下图展示 items_pct SPL 函数。

图 4. items_pct SPL 函数的代码

create function items_pct(mac char(3)) returning decimal;
define tp money;
define mc_tot money;
define pct decimal;
let tp = (select sum(total_price) from items);

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 527 -
let mc_tot = (select sum(total_price) from items
where manu_code = mac);
let pct = mc_tot / tp;
return pct;
end function;
执行 SPL 函数的样例程序
该样例程序片段使用系统描述符区域来动态地执行 SPL 函数,该函数返回多组返回
值。

=================================================================
======
1. #include
2. #include
3. EXEC SQL include sqltypes;
4. EXEC SQL include sqlstype;
5. EXEC SQL include decimal;
6. EXEC SQL include datetime;
7. extern char statement[80];
8. main()
9. {
10. EXEC SQL BEGIN DECLARE SECTION;
11. int sp_cnt, desc_count;
12. char dyn_stmnt[80], rout_name[30];
13. EXEC SQL END DECLARE SECTION;
14. int whenexp_chk();
15. printf("Sample ESQL program to execute an SPL function
running.\n\n");
16. EXEC SQL whenever sqlerror call whenexp_chk;
17. EXEC SQL connect to 'stores7';
18. printf("Connected to stores7 database.\n");
19. /* These next five lines hard-wire the execute function
20. * statement. This information could have been entered
21. * by the user and placed into the string dyn_stmnt.

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 528 -
22. */
23. stcopy("items_pct(\"HSK\")", rout_name);
24. sprintf(dyn_stmnt, "%s %s",
25. "execute function", rout_name);

=====================================================================
==

19 - 25 行

对 sprintf() 的调用(24 行)为 EXECUTE FUNCTION 语句组装字符串,该语句执
行 items_pct() SPL 函数。


=================================================================
======
26. EXEC SQL prepare spid from :dyn_stmnt;
27. EXEC SQL allocate descriptor 'spdesc';
28. EXEC SQL describe spid using sql descriptor 'spdesc';
29. if(SQLCODE != SQ_EXECPROC)
30. {
31. printf("\nPrepared statement is not EXECUTE FUNCTION.\n");
32. exit();
33. }

=====================================================================
==

26 行

然后,PREPARE 语句为 EXECUTE FUNCTION 语句创建 spid 语句标识符。

27 行


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 529 -
ALLOCATE DESCRIPTOR 语句分配 spdesc 系统描述符区域。

28 - 33 行

DESCRIBE 语句确定 items_pct SPL 函数返回的值的数目和数据类型。此
DESCRIBE 包括 USING SQL DESCRIPTOR 子句来指定 spdesc 系统描述符区域作为这
些描述的位置。

在 28 行,该程序对照 sqlstype.h 文件中定义的常量值,检测 SQLCODE 变量
(sqlca.sqlcode)的值,来验证是否准备好了 EXECUTE FUNCTION 语句。

=================================================================
======
34. EXEC SQL get descriptor 'spdesc' :sp_cnt = COUNT;
35. if(sp_cnt == 0)
36. {
37. sprintf(dyn_stmnt, "%s %s", "execute procedure", rout_name);
38. EXEC SQL prepare spid from :dyn_stmnt;
39. EXEC SQL execute spid;
40. }
41. else
42. {
43. EXEC SQL declare sp_curs cursor for spid;
44. EXEC SQL open sp_curs;
45. while(getrow("spdesc"))
46. disp_data(:sp_cnt, "spdesc");
47. EXEC SQL close sp_curs;
48. EXEC SQL free sp_curs;
49. }

=====================================================================
==

34 - 40 行

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 530 -

要获得主变量中返回值的数目,
GET DESCRIPTOR 语句将 COUNT 字段的值检索至
主变量内。当您需要确定该 SPL 例程返回了多少个值时,此值是有用的。如果 SPL 例程
未返回值,即,COUNT 的值为零,则该 SPL 例程为过程,不是函数。因此,该程序准备
EXECUTE PROCEDURE 语句(38 行),然后使用 EXECUTE 语句(39 行)来执行该
过程。EXECUTE 语句不需要使用系统描述符区域,因为该 SPL 过程没有任何返回值。

41 - 49 行

如果 SPL 例程确实返回值,即,如果 COUNT 的值大于零,则程序为准备好的 SPL
函数声明并打开 sp_curs 游标。

对于由该 SPL 函数返回的每一组值,执行 while 循环(45 和 46 行)。此循环调
用 getrow() 函数来将一组值访存至 spdesc 系统描述符区域。
然后,
它调用 disp_data() 函
数来显示返回的值。

在返回了所有组的返回值之后,CLOSE 语句(47 行)关闭 sp_curs 游标,且 FREE
语句(48 行)释放分配给该游标的资源。

=================================================================
======
50. EXEC SQL free spid;
51. EXEC SQL deallocate descriptor 'spdesc';
52. EXEC SQL disconnect current;
53. }

=====================================================================
==

50 和 51 行

此 FREE 语句释放为准备好的语句分配的资源。
DEALLOCATE
DESCRIPTOR 语
句释放分配给 spdesc 系统描述符区域的内存。
执行游标函数
游标函数可将一行或多行返回值返回给应用程序。要执行游标函数,您必须将
EXECUTE FUNCTION 语句与函数游标相关联,
并使用 FETCH...INTO SQL DESCRIPTOR

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 531 -
语句来保存系统描述符区域中的一个或多个返回值。

要使用系统描述符区域来保存游标函数返回值:
为用户定义的函数声明函数游标。
使用 DECLARE 语句来将 EXECUTE FUNCTION 语句与函数游标相关联。

使用 OPEN 语句来执行该函数,并打开游标。
使用 FETCH...USING SQL DESCRIPTOR 语句来将返回值从游标检索至系统描述符
区域内。

使用 GET DESCRIPTOR 语句来将返回值从系统描述符区域检索至主变量内。
每一项描述符的 DATA 字段都包含返回值。

以 DEALLOCATE DESCRIPTOR 语句释放系统描述符区域。

仅定义作为迭代函数的外部函数可返回多行数据。因此,您必须定义函数游标来动态
地执行迭代函数。每一行数据仅由一个值组成,因为外部函数仅可返回单个值。对于每一
行,系统描述符区域仅包含一个带有单个返回值的项描述符。

其 RETURN 语句包括 WITH RESUME 关键字的 SPL 函数可返回一行或多行数据。
因此,
您必须定义函数游标来动态地执行这些 SPL 函数。
每一行数据都由一个或多个值组
成,因为 SPL 函数一次可返回一个或多个值。
对于每一行,系统描述符区域包含每一返回
值的项描述符。

API)
随同 admin() 或 task() 函数,使用 onmode 和 c 参数来强制检查点。

GBase 8s 管理员参考
南大通用数据技术股份有限公司 - 758 -

语法

用法
这个函数强制检查点,清空缓冲区到磁盘。如果逻辑日志中的最近检查点阻止释放逻辑日
志文件(状态 U-B-L),则您可使用 c 选项来强制检查点。
使用 block 参数来阻止数据库服务器处理任何事务。使用这个选项在 GBase
8s 上执行外
部备份。 当数据库服务器被阻塞时,用户不可访问它,除了处于 read-only 模式。直到
解除数据库服务器阻塞,事务才可完成。
使用 hard 参数来强制阻塞的检查点。这是缺省值。
使用 norm 参数来强制未阻塞的检查点。
使用 unblock 参数来解除数据库服务器阻塞。当解除数据库服务器阻塞时,数据事务和正
常的数据库服务器操作可重新开始。请您在 GBase
8s 上完成外部备份之后使用这个选项。

这个函数等同于 onmode -c 命令。
示例
下列示例启动阻塞的检查点:
EXECUTE FUNCTION task("onmode","c","hard");

取值:[0|1]
默认值:0
说明:consumer 消费数据量统计校验
设置此参数=1 表示让kafka consumer 统计每次提交涉及的每个表
的数据量(Insert、Delete、Update),得到预期的影响行数,随后在下发数据给单
机执行的时候,统计每个分片的实际影响行数,最后用预期影响行数与实际影响行
数做比较,如果发现不符,则报错,并放弃本次提交。该参数仅适用于oracle 源
表有主键的情况(需要数据唯一性)。参数默认为0,表示不使能check,最大值
为1。
修改方式:
可使用set 语句修改值也可在配置文件中修改值。
适用于session、
global
范围均可。