返回首页

gbase数据、南大通用产品文档:GBase8sGBASEDBTOPCACHE 环境变量

更新日期:2024年09月11日

GBASEDBTOPCACHE 环境变量可对客户机应用程序的登台区域 Blob 空间指定内存高速
缓存的大小。

kilobytes 指定您为光学内存高速缓存设置的值。
通过指定内存高速缓存的大小 (KB) 来设置 GBASEDBTOPCACHE 环境变量。指定
大小必须等于或小于系统范围的配置参数 OPCACHEMAX 的大小。
如果未设置 GBASEDBTOPCACHE,那么缺省高速缓存大小为 128 千字节或在配置
参数 OPCACHEMAX 中指定的大小。OPCACHEMAX 的缺省值是 0。如果将
GBASEDBTOPCACHE 设置为值 0,那么 Optical Subsystem 不使用高速缓存。

要执行的最简单的动态 SQL 的类型,是您知道其下列项:
要执行的 SQL 语句的结构,包括比如语句类型以及语句的语法这样的信息
在 GBase 8s ESQL/C 程序与数据库服务器之间传递的任何数据的数目及数据类型
执行非 SELECT 语句
术语非 SELECT 语句指的是可被准备的任何 SQL 语句,除了 SELECT 和
EXECUTE FUNCTION 之外。此术语包括 EXECUTE PROCEDURE 语句。

重要: INSERT 语句是对非 SELECT 语句的规则的一个例外。如果 INSERT 插入
单个行,则请使用 PREPARE 和 EXECUTE 来执行它。然而,如果该 INSERT 与插入游
标相关联,则您必须声明该插入游标。

您可以下列方式执行非 SELECT 语句:

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

如果多次执行该语句,则请使用 PREPARE 和 EXECUTE 语句。
如果仅执行该语句一次,则请使用 EXECUTE IMMEDIATE 语句。此语句对它可执
行的语句没有限制。
PREPARE 和 EXECUTE 语句
PREPARE 和 EXECUTE 语句允许您将非 SELECT 语句的执行分为两个步骤:
PREPARE 将语句字符串发送至数据库服务器,其解析该语句,并分配给它语句标识
符。
EXECUTE 执行由语句标识符指示的准备好的语句。

对于需要多次执行的语句,这两个步骤的处理是有用的。当您仅解析该语句一次时,
请减少在客户机应用程序与数据库服务器之间的流量。

例如,您可编写通用目的的删除程序,对任何表操作。此程序会采取下列步骤:
提示用户表的名称和 WHERE 子句的文本,并将该信息放置在诸如 tabname 和
search_condition 这样的 C 变量内。tabname 和 search_condition 变量不需要作为主变
量,因为它们在实际的 SQL 语句中出现。
通过连接下列四个组件来创建文本字符串:DELETE FROM、tabname、WHERE 和
search_condition。在此示例中,主变量中的字符串称为 stmt_buf:
sprintf(stmt_buf, "DELETE FROM %s WHERE %s",
tabname, search_condition);

准备整个语句。下列 PREPARE 语句对 stmt_buf 中的字符串操作,并创建称为 d_id
的语句标识符:
EXEC SQL prepare d_id from :stmt_buf;

执行该语句。下列 EXECUTE 语句执行 DELETE:
EXEC SQL execute d_id;

如果您不需要再次执行该语句,请释放该语句标识符结构使用的资源。此示例会使用
下列 FREE 语句:
EXEC SQL free d_id;

如果非 SELECT 语句包含输入参数,
则您必须使用 EXECUTE 语句的 USING 子句。


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


通常使用 EXECUTE 语句来执行非 SELECT 语句。对于 SELECT 或 EXECUTE
FUNCTION 语句,您可使用带有 INTO 子句的 EXECUTE,只要这些语句仅返回一组值
(一行)。然而,请不要使用 EXECUTE 语句,对于:
与插入游标相关联的 INSERT...VALUES 语句。
游标函数(返回多组值的用户定义的函数)的 EXECUTE FUNCTION 语句。
EXECUTE IMMEDIATE 语句
并非准备语句然后执行它,而是您可以 EXECUTE IMMEDIATE 语句在同一步骤中
准备并执行该语句。EXECUTE IMMEDIATE 语句还在完成时释放语句标识符资源。

例如,对于在前一部分中使用的 DELETE 语句,您可以下列语句替代
PREPARE-EXECUTE 语句序列:
EXEC SQL execute immediate :stmt_buf;

如果语句字符串包含输入参数,
则您不可使用 EXECUTE IMMEDIATE。
SQL 还对您
可以 EXECUTE IMMEDIATE 的执行有限制。
执行 SELECT 语句
您可以下列方式执行 SELECT 语句:
如果 SELECT 语句仅返回一行,则请使用 PREPARE 和 EXECUTE INTO。此类
SELECT 常常称为单个的 SELECT。
如果 SELECT 语句返回多行,则您必须使用游标管理语句。
PREPARE 和 EXECUTE INTO 语句
您可以 EXECUTE 语句执行的唯一的准备好的 SELECT 语句是单个 SELECT。
您的
GBase 8s ESQL/C 程序必须采取下列行动:
声明主变量来接收数据库服务器返回的值。
对于准备好的 SELECT 语句,这些值为选择列表列。

组装并准备该语句。
准备好的 SELECT 语句可在 WHERE 子句中包含输入参数。

以 EXECUTE...INTO 语句执行准备好的选择,带有 INTO 关键字之后的主变量。
如果 SELECT 语句包含输入参数,则请包括 EXECUTE 的 USING 子句。

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


提示: 要执行单个的 SELECT,与使用 DECLARE、OPEN 和 FETCH 语句相比,
EXECUTE...INTO 语句更高效。

以 EXECUTE 语句的 INTO 子句,您仍可使用下列特性:
您可将指示符变量与接收选择列表列值的主变量相关联。
请使用后跟指示符主变量的名称的 INDICATOR 关键字,如下:
EXEC SQL prepare sel1 from
'select fname, lname from customer where customer_num = 123';
EXEC SQL execute sel1 into :fname INDICATOR :fname_ind,
:lname INDICATOR :lname_ind;

您可指定输入参数值。
请包括 EXECUTE 的 USING 子句,如下:
EXEC SQL prepare sel2 from
'select fname, lname from customer where customer_num = ?';
EXEC SQL execute sel2 into :fname, :lname using :cust_num;

重要: 当您使用 EXECUTE INTO 语句时,请确保该 SELECT 语句为单个的
SELECT。如果该 SELECT 返回多行,则您收到运行时刻错误。如果您尝试执行(以
DECLARE)声明了的准备好的语句,则也生成错误。

您不需要准备单个的 SELECT。如果您不需要准备好的语句的益处,您可直接将单个
的 SELECT 语句嵌入在您的 GBase 8s ESQL/C 程序中,如下列示例所示:
EXEC SQL select order_date from orders where order_num = 1004;

下图展示如何执行 items_pct() SPL 函数(如 图 1所示)。由于此函数返回
单个的十进制值,因此,EXECUTE...INTO 语句可执行它。
EXEC SQL prepare exfunc_id from
'execute function items_pct(\"HSK\")';
EXEC SQL execute exfunc_id into :manuf_dec;

您可使用例程参数的主变量,但不可使用例程名称。例如,如果 manu_code 变量保
存值 "HSK",则下列 EXECUTE 语句替代准备好的语句中的输入参数,来执行与前面的
代码段中 EXECUTE 一样的任务。

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

EXEC SQL prepare exfunc_id from
'execute function items_pict(?)';
EXEC SQL execute exfunc_id into :manuf_dec using :manu_code;

如果您不知道选择列表列或函数返回值的数目或数据类型,则您必须使用动态管理结
构,
而不是随同 EXECUTE...INTO 语句的主变量。
动态管理结构在运行时刻定义选择列表
列。
声明选择游标
要执行返回多行的 SELECT 语句,您必须声明选择游标。选择游标使得 GBase 8s
ESQL/C 应用程序能够处理查询返回的多行。

您的 GBase 8s ESQL/C 程序必须采取下列行动来使用选择游标:
声明主变量来接收数据库服务器返回的值。
对于准备好的 SELECT 语句,这些值为选择列表列。对于准备好的 EXECUTE
FUNCTION 语句,这些值为用户定义的函数的返回值。

组装并准备该语句。
准备好的 SELECT 语句可在 WHERE 子句中包含输入参数。准备好的 EXECUTE
FUNCTION 语句可包含输入参数作为函数参数。

声明选择游标。
DECLARE 语句将准备好的 SELECT 语句与选择游标相关联。

执行该查询。
OPEN 语句将它的 USING 子句指定的任何输入参数发送至数据库服务器,
并告诉数
据库服务器执行该 SELECT 语句。

从选择游标检索值的行。
FETCH 接收与查询标准相匹配的一行数据。

限制:
请不要在与游标相关联的 SELECT 语句与从该游标检索数据的 FETCH 语句
中同时使用 INTO 子句。GBase 8s ESQL/C 预处理器或可执行的程序不可生成此情况的错
误。然而,同时在两个语句中使用 INTO 子句可生成不可预料的结果。

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

lvarptr.ec 程序
lvarptr.ec 示例程序使用 lvarchar 指针,如下
/*
**
** Sample use of LVARCHAR to fetch collections in ESQL/C.
**
** Statically determined collection types.
*/

#include

static void print_lvarchar_ptr(
const char *tag,
EXEC SQL BEGIN DECLARE SECTION;
parameter lvarchar **lv
EXEC SQL END DECLARE SECTION;
)
{
char *data;

data = ifx_var_getdata(lv);
if (data == 0)
data = "<>";
printf("%s: %s\n", tag, data);
}

static void process_stmt(char *stmt)
{
EXEC SQL BEGIN DECLARE SECTION;
lvarchar *lv1;
lvarchar *lv2;
lvarchar *lv3;
mint seq;

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

char *stmt1 = stmt;
EXEC SQL END DECLARE SECTION;

printf("SQL: %s\n", stmt);

EXEC SQL WHENEVER ERROR STOP;
EXEC SQL PREPARE p_collect FROM :stmt1;
EXEC SQL DECLARE c_collect CURSOR FOR p_collect;
EXEC SQL OPEN c_collect;

ifx_var_flag(&lv1, 1);
ifx_var_flag(&lv2, 1);
ifx_var_flag(&lv3, 1);

while (sqlca.sqlcode == 0)
{
EXEC SQL FETCH c_collect INTO :seq, :lv1, :lv2, :lv3;
if (sqlca.sqlcode == 0)
{
printf("Sequence: %d\n", seq);
print_lvarchar_ptr("LVARCHAR 1", &lv1);
print_lvarchar_ptr("LVARCHAR 2", &lv2);
print_lvarchar_ptr("LVARCHAR 3", &lv3);
ifx_var_dealloc(&lv1);
ifx_var_dealloc(&lv2);
ifx_var_dealloc(&lv3);
}
}

EXEC SQL CLOSE c_collect;
EXEC SQL FREE c_collect;
EXEC SQL FREE p_collect;
}

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


mint main(int argc, char **argv)
{
EXEC SQL BEGIN DECLARE SECTION;
char *dbase = "stores7";
char *stmt1 =
"INSERT INTO t_collections VALUES(0, "
"'LIST{-1,0,-2,3,0,0,32767,249}', 'SET{-1,0,-2,3}', "
"'MULTISET{-1,0,0,-2,3,0}') ";
char *data;
EXEC SQL END DECLARE SECTION;

if (argc > 1)
dbase = argv[1];
EXEC SQL WHENEVER ERROR STOP;
printf("Connect to %s\n", dbase);
EXEC SQL CONNECT TO :dbase;

EXEC SQL CREATE TEMP TABLE t_collections
(
seq serial not null,
l1 list (integer not null),
s1 set (integer not null),
m1 multiset(integer not null)
);

EXEC SQL EXECUTE IMMEDIATE :stmt1;
EXEC SQL EXECUTE IMMEDIATE :stmt1;
EXEC SQL EXECUTE IMMEDIATE :stmt1;

process_stmt("SELECT seq, l1, s1, m1 FROM t_collections");

puts("OK");

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

return 0;
}
执行 GBase 8s 中的用户定义的例程
在 GBase 8s 中,用户定义的例程是执行用户定义的任务的语句的集合。过程是可接
受参数但不返回任何值的例程。函数是可接受参数并返回值的例程。

下表总结用户定义的例程的 SQL 语句。
表 7. 用户定义的例程的 SQL 语句
任务
过程
函数
创建并注册例程
CREATE
PROCEDURE
CREATE FUNCTION
执行例程
EXECUTE
PROCEDURE
EXECUTE
FUNCTION
删除例程
DROP PROCEDURE
DROP FUNCTION

对于用户定义的例程,GBase 8s 支持几种语言:
以诸如 C 这样的外部语言编写的外部例程。
在外部过程不返回值时,外部函数可返回一个值。

SPL 例程是以“存储过程语言”(SPL)编写的。
在 SPL 过程不返回任何值时,SPL 函数可返回一个或多个值。

提示: 在较早版本的 GBase 8s 产品中,使用术语存储过程同时表示 SPL 过程和
SPL 函数。
即,
存储过程可包括 RETURN 语句来返回值。
为了与较早的产品相兼容,
GBase
8s 继续支持以 EXECUTE PROCEDURE 语句来执行 SPL 函数。
然而,
对于新的 SPL 例
程,推荐您对于过程仅使用 EXECUTE PROCEDURE,而对于函数仅使用 EXECUTE
FUNCTION。

对于它的参数,用户定义的例程可使用输入函数。然而,对于它的例程名称,它不可
使用输入参数。
用户定义的过程
如果您在编译时刻知道用户定义的过程(外部的或 SPL)的名称,则请以 EXECUTE
PROCEDURE 语句执行用户定义的过程。下列 EXECUTE PROCEDURE 语句执行名为
revise_stats() 的用户定义的过程:

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

EXEC SQL execute procedure revise_stats("customer");

如果您直到运行时刻才知道用户定义的过程的名称,则您必须动态地执行该过程。要
动态地执行用户定义的过程,您可使用:
PREPARE 和 EXECUTE 语句
EXECUTE IMMEDIATE 语句
用户定义的函数
如果您在编译时刻知道用户定义的函数的名称,则请以 EXECUTE FUNCTION
语句执行用户定义的(外部的或 SPL)函数。在 EXECUTE
FUNCTION 的 INTO 子
句中,请您罗列保存一个或多个返回值的主变量。下列 EXECUTE FUNCTION 语
句执行名为 items_pct() 的用户定义的函数(图 1对其定义):
EXEC SQL execute function items_pct(\"HSK\")
into :manuf_percent;

如果您直到运行时刻才知道用户定义的函数的名称,则您必须动态地执行
该函数。用户定义的函数的动态执行类似于 SELECT 语句的动态执行(处理未
知的选择列表)。SELECT 和用户定义的函数都将值返回至 GBase
8s
ESQL/C 程
序。

请以 EXECUTE FUNCTION 语句执行用户定义的函数。您可以下列两种方式执行
EXECUTE FUNCTION 语句:
如果用户定义的函数仅返回一行,则请使用 PREPARE 和 EXECUTE INTO 来执行
EXECUTE FUNCTION 语句。此类用户定义的函数常常称为非游标函数。
如果用户定义的函数返回多行,则您必须声明函数游标来执行该 EXECUTE
FUNCTION 语句。
此类用户定义的函数常常称为游标函数。以 SPL(和 SPL 函数)编写的游标函数在
它的 RETURN 语句中有 WITH RESUME 子句。
以诸如 C 这样的外部语言编写的游标函
数是迭代函数。

提示: 如果您不知道返回值的数据类型,则您必须使用动态管理结构来保存该值。

非游标函数

您可使用 PREPARE 和 EXECUTE 语句来执行用户定义的非游标函数。非游标函数
仅返回一行值。


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

您的 GBase 8s ESQL/C 程序必须采取下列行动:
声明主变量来接收数据库服务器返回的值。
对于准备好的 EXECUTE FUNCTION 语句,这些值是用户定义的函数的返回值。

组装并准备该语句。
准备好的 EXECUTE FUNCTION 语句可包含输入参数作为函数参数。

以 EXECUTE...INTO 语句执行准备好的用户定义的函数,随同 INTO 关键字之后的
主变量。
如果 EXECUTE FUNCTION 包含数据参数,请包括 EXECUTE 的 USING 子句。

重要: 要执行非游标函数,与 DECLARE、OPEN 和 FETCH 语句相比,
EXECUTE...INTO 更高效。然而,您常常不知道返回的行数。当您不使用游标来执行返回
多行的游标函数时,GBase 8s ESQL/C 生成运行时刻错误。因此,总是将用户定义的函数
与游标相关联是一个好做法。

大多数外部函数仅可返回一行数据和仅单个值。
例如,
下列代码段执行名为 stnd_dev()
的外部函数:
strcpy(func_name, "stnd_dev(ship_date)");
sprintf(exfunc_stmt, "%s %s %s",
"execute function",
func_name);
EXEC SQL prepare exfunc_id from :exfunc_stmt;
EXEC SQL execute exfunc_id into :ret_val;

要返回多个值,外部函数必须返回复合的数据类型,比如集合或 row 类型。

SPL 函数可返回一个或多个值。如果 SPL 函数的 RETURN 语句不包含 WITH
RESUME 关键字,则该函数仅返回一行。要动态地执行 SPL 函数,请准备该 EXECUTE
FUNCTION,并以 EXECUTE...INTO 语句执行它。

函数游标


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

要执行其用户定义的函数返回多行的 EXECUTE FUNCTION 语句,您必须声明函数
游标。函数游标使得 GBase 8s ESQL/C 应用程序能够处理用户定义的函数返回的多个行。


您的 GBase 8s ESQL/C 程序必须采取下列行动来使用函数游标:
声明主变量来接收用户定义的函数返回的值。
组装并准备该语句。
准备好的 EXECUTE FUNCTION 语句可包含输入参数作为函数参数。

声明函数游标。
DECLARE 语句将准备好的 EXECUTE FUNCTION 语句与函数游标相关联。

执行用户定义的函数。
OPEN 语句将它的 USING 子句指定的任何输入参数发送至数据库服务器,
并告诉数
据库服务器执行该 EXECUTE FUNCTION 语句。

从函数游标检索值的行。
FETCH 语句检索用户定义的函数返回的一行值。

仅为迭代函数的外部函数可返回多行数据。

如果 SPL 函数的 RETURN 语句包含 WITH RESUME 关键字,则该函数可返回多
行。您必须将这样的 SPL 函数与函数游标相关联。要动态地执行该 SPL 函数,请将
EXECUTE FUNCTION 语句与游标相关联,使用 OPEN 语句来执行该函数,并使用
FETCH...INTO 语句来将行从游标检索至主变量内。
执行带有输入参数的语句
输入参数是 SQL 语句中的占位符,指示在运行时刻提供的实际的值。由于数据库服
务器对应用程序中声明的变量一无所知,因此,您不可在动态 SQL 语句的文本中罗列主
变量名称。反而,您可在表达式为有效的语句内的任何地方,以问号(?)指示输入参数,
其作为占位符。您不可使用输入参数来代表诸如数据库名称、表名称或列名称这样的标识
符。

包含输入参数的 SQL 语句称为参数化的语句。对于参数化的 SQL 语句,您的程序
必须将下列关于其输入参数的信息提供给数据库服务器:

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

您的程序必须使用问号
(?)
作为该语句的文本中的占位符,
来指示期望输入参数的位
置。例如,下列 DELETE 语句包含两个输入参数:
EXEC SQL prepare dlt_stmt from
'delete from orders where customer_num = ? \
and order_date > ?';
为 customer_num 列的值定义第一个输入参数,为 order_date 列的值定义第二个。


当以 USING 子句执行该语句时,您的程序必须为输入参数指定该值。要执行前面步
骤中的 DELETE 语句,您可使用下列语句:
EXEC SQL execute dlt_stmt using :cust_num, :ord_date;

在运行时刻您用于提供带有值的输入参数的语句,
依赖于您执行的 SQL 语句的类型,
如下:
对于带有输入参数的非 SELECT 语句(诸如 UPDATE、INSERT、DELETE 或
EXECUTE PROCEDURE),EXECUTE...USING 语句执行该语句,并提供输入参数值。
对于与游标相关联的 SELECT 语句,或对于游标函数(EXECUTE FUNCTION),
OPEN...USING 语句执行该语句,并提供输入参数值。
对于单个 SELECT 语句,或对于非游标函数(EXECUTE FUNCTION),
EXECUTE...INTO...USING 语句执行该语句,并提供输入参数值。

当该语句执行时,您可罗列主变量或文字值来替代 USING 子句中的每一输入参数。
该值必须与相关联的输入参数在数目和数据类型上相兼容。主变量还必须大到足以保存该
数据。

重要:
要以 USING 子句使用主变量,
您必须知道 SQL 语句中参数的数目及其数据
类型。在运行时刻,如果您不知道输入参数的数目和数据类型,则您必须以 USING 子句
使用动态管理结构。
EXECUTE USING 语句
你可以 EXECUTE...USING 语句执行参数化的非 SELECT 语句(包含输入参数的非
SELECT)。

下列语句是参数化的非 SELECT 语句:
在 WHERE 子句中带有输入参数的 DELETE 或 UPDATE 语句
在 SET 子句中带有输入参数的 UPDATE 语句

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

在 VALUES 子句中带有输入参数的 INSERT 语句
带有其函数参数的输入参数的 EXECUTE PROCEDURE 语句

提示: 对于用户定义的过程,您不可使用输入参数作为过程名称。

例如,在其 WHERE 子句中,下列 UPDATE 语句需要两个参数:
EXEC SQL prepare upd_id from
'update orders set paid_date = NULL \
where order_date > ? and customer_num = ?';

USING 子句罗列保存参数数据的主变量的名称。如果在 hvar1 和 hvar2 中存储输
入变量值,则您的程序可以下列语句执行此 UPDATE:
EXEC SQL execute upd_id using :hvar1, :hvar2;

当在编译时刻知道参数的类型和数目时,下列步骤描述如何处理参数化的 UPDATE
或 DELETE:
为在该准备好的语句中的每一输入参数声明主变量。
1. 为该语句组装该字符串,为每一输入参数带有问号(?)占位符。一
旦您已组装了该字符串,就请准备它。要获取关于这些步骤的更多
信息,
给与每一输入参数相关联的主变量指定一个值。
(该应用程序可以交互地获取这些值。


以 EXECUTE...USING 语句执行该 UPDATE 或 DELETE 语句。您必须罗列在
USING 子句中包含输入参数值的主变量。
可选地,使用 FREE 语句来释放随同准备好的语句分配了的资源。

重要: 在编译时刻,如果您不知道准备好的语句中的输入参数的数目和数据类型,
请不要以 USING 子句使用主变量。反而,请使用动态管理结构来指定输入参数值。
OPEN USING 语句
您可以 OPEN...USING 语句执行下列语句:
返回一行或多行的参数化的 SELECT 语句(在其 WHERE 子句中包含输入参数的
SELECT 语句)
参数化的 EXECUTE FUNCTION 语句(对于其参数包含输入参数的游标函数)


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

提示: 对于用户定义的函数,您不可使用输入参数作为函数名称。

例如,
下列 SELECT 语句是在其 WHERE 子句中需要两个参数的参数化的 SELECT:

EXEC SQL prepare slct_id from
'select from orders where customer_num = ? and order_date > ?';
EXEC SQL declare slct_cursor cursor for slct_id;

如果 cust_num 和 ord_date 主变量包含输入参数值,则下列 OPEN 语句已这些输
入参数执行该 SELECT:
EXEC SQL open slct_id using :cust_num, :ord_date;

在编译时刻,
仅当您知道 SELECT 语句的 WHERE 子句中的输入参数的类型和数目
时,请使用 USING host_var 子句。
demo2.ec 样例程序
demo2.ec 样例程序展示如何处理在其 WHERE 子句中有输入参数的动态 SELECT
语句。

demo2.ec 程序使用主变量来保存 SELECT 语句的输入参数的值。它还使用主变量来
保存从数据库返回的列值。

. #include
2. EXEC SQL define FNAME_LEN 15;
3. EXEC SQL define LNAME_LEN 15;
4. main()
5. {
6. EXEC SQL BEGIN DECLARE SECTION;
7. char demoquery[80];
8. char queryvalue[2];
9. char fname[ FNAME_LEN + 1 ];
10. char lname[ LNAME_LEN + 1 ];
11. EXEC SQL END DECLARE SECTION;
12. printf("DEMO2 Sample ESQL program running.\n\n");
13. EXEC SQL connect to'stores7';

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

14. /* The next three lines have hard-wired the query. This
15. * information could have been entered from the terminal
16. * and placed into the demoquery string
17. */
18. sprintf(demoquery, "%s %s",
19. "select fname, lname from customer",
20. "where lname > ? ");
21. EXEC SQL prepare demo2id from :demoquery;

行 9 和 10

这些行为 SELECT 语句的 WHERE 子句中的参数声明主变量(fname),并为
SELECT 语句返回的值声明主变量(fname 和 lname)。

行 14 - 21

这些行为该语句组装字符串(在 demoquery 中),并准备它作为 demo2id 语句标识
符。问号(?)指示在该 WHERE 子句中的输入参数。

. EXEC SQL declare demo2cursor cursor for demo2id;
23. /* The next line has hard-wired the value for the parameter.
24. * This information could also have been entered from the
* terminal
25. * and placed into the queryvalue string.
26. */
27. sprintf(queryvalue, "C");
28. EXEC SQL open demo2cursor using :queryvalue;
29. for (;;)
30. {
31. EXEC SQL fetch demo2cursor into :fname, :lname;
32. if (strncmp(SQLSTATE, "00", 2) != 0)
33. break;
34. /* Print out the returned values */

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

35. printf("Column: fname\tValue: %s\n", fname);
36. printf("Column: lname\tValue: %s\n", lname);
37. printf("\n");
38. }

行 22

此行为准备好的语句标识符 demo2id 声明 demo2cursor 游标。所有非单个 SELECT
语句都必须有声明了的游标。

行 23 - 27

queryvalue 主变量是 SELECT 语句的输入参数。
它包含值 C。
在交互的应用程序中,
可能会从用户处获取此值。

行 28

当数据库服务器打开 demo2cursor 游标时,它执行该 SELECT 语句。因为 SELECT
语句的 WHERE 子句包含输入参数(行 20 和 21),因此,OPEN 语句包括 USING 子
句来在 queryvalue 中指定输入参数值。

行 29 - 38

为从数据库访存的每一行执行此 for 循环。FETCH 语句(行 31)包括 INTO 子句
来为列值指定 fname 和 lname 主变量。在此 FETCH 语句执行之后,在这些主变量中存
储该列值。

. if (strncmp(SQLSTATE, "02", 2) != 0)
40. printf("SQLSTATE after fetch is %s\n", SQLSTATE);
41. EXEC SQL close demo2cursor;
42. EXEC SQL free demo2cursor;
43. EXEC SQL free demo2id;
44. EXEC SQL disconnect current;

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

45. printf("\nProgram Over.\n");
46. }

行 39 和 40

在 for 循环外部,该程序再次测试 SQLSTATE 变量,以便它可在成功的执行、运行
时刻错误或警告事件中通知用户(类代码不等于 "02")。

行 41

在访存所有行之后,CLOSE 语句关闭 demo2cursor 游标。

行 42 和 43

这些 FREE 语句为准备好的语句(行 42)和数据库游标(行 43)释放分配的资源。
一旦已释放了游标或准备好的语句,在该程序中就不可再次使用它。

即使MOT 完全兼容ACID,GBase 8c 并非支持所有的隔离级别。下表介绍了各隔离级
别,以及MOT 支持和不支持的内容。
表13- 3 隔离级别
隔离级别
说明
READ UNCOMMITTED
MOT 不支持
READ COMMITTED
MOT 支持
READ COMMITTED(读已提交)隔离级别保证任何正在读取
的数据在上一次读取时都已提交。它只是限制读者看到任何中
间数据、未提交数据或脏读。数据被读取后可以自由更改,因
此,读已提交隔离级别并不保证事务再次读取时能找到相同的
数据。
SNAPSHOT
MOT 不支持
SNAPSHOT(快照)隔离级别提供与SERIALIZABLE(可序列
化)相同的保证,同时支持并发事务修改数据。相反,它迫使
每个读者看到自己的世界版本(自己的快照)。不阻止并发更
新使得编程非常容易,且可扩展性很强。然而,在许多实现中,
这种隔离级别需要更高的服务器资源。
REPEATABLE READ
MOT 支持
REPEATABLE READ(可重复读)是一个更高的隔离级别,除
了READ COMMITTED 隔离级别的保证之外,
它还保证任何读
取的数据都不能更改。如果一个事务再次读取相同的数据,它
将找出该数据,不做更改,并且保证它可读取。
乐观模型使得并发事务能更新该事务读取的行。在提交时,该

GBase 8c V5 开发者手册
南大通用数据技术股份有限公司
484
事务将验证REPEATABLE READ 隔离级别是否被违反。若违
反,则回滚该事务,必须重试。
SERIALIZABLE
MOT 不支持
SERIALIZABLE(可序列化)隔离提供了更强的保证。除了
REPEATABLE READ 隔离级别保证的所有内容外,
它还保证后
续读取不会看到新数据。
它之所以被命名为SERIALIZABLE,是因为隔离非常严格,几
乎有点像事务串行运行,而不是并行运行。
下表显示了不同隔离级别启用的并发副作用。
表13- 4 隔离级别启用的并发副作用
隔离级别
说明
不可重复读
幻读
READ
UNCOMMITTED



READ COMMITTED



REPEATABLE
READ



SNAPSHOT



SERIALIZABLE