在 GBase 8s ESQL/C 应用程序中,SQL 语句可以引用主变量的内容。主变量是 GBase 8s ESQL/C 程序变量, 它用于在 GBase 8s ESQL/C 程序和数据库服务器之间传输信 息。 可以使用 GBase 8s ESQL/C 表达式中的主变量,方法与使用文字值相同,但不能使 用它们: 在已准备好的语句中 在存储过程中 在检查约束中 在视图中 在触发器中 作为字符串连接操作的一部分 要在 SQL 语句中使用主变量: 在 C 程序中声明主变量。 给主变量指定值。 在嵌入式 SQL 语句中指定主变量。 声明主机变量 在 GBase 8s ESQL/C 程序中可以使用该变量之前,必须定义主机变量所需的数据存 储。要为变量指定一个标识符并将其与数据类型相关联,然后再声明此变量。 在 GBase 8s ESQL/C 程序中将主变量声明为 C 变量,使用与 C 变量相同的基本语 法。 要标识该变量为主机变量,必须使用以下方式之一声明它: 将声明放置在 ESQL 声明段中: EXEC SQL BEGIN DECLARE SECTION; -- 将主机变量声明放置于此处 EXEC SQL END DECLARE SECTION; 确定使用分号结束 EXEC SQL BEGIN DECLARE SECTION 和 EXEC SQL END DECLARE SECTION 。 使用 EXEC SQL BEGIN DECLARE SECTION 和 EXEC SQL END DECLARE SECTION 关键字符合 ANSI 标准。 使用美元符号($)表示每个声明。 在声明本身中,您必须指定以下信息: GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 12 - 主机变量的名称 主机变量的数据类型 主机变量的初始值(可选) 主机变量的范围(由程序中放置的声明决定) 主机变量名称 主机变量的名称必须符合 C 语言的命名规范。 此外, 必须遵循 C 编译器施加的任何 限制。 通常情况下,C 变量必须以一个字母或下划线开头,并且可以包含字母和数字以及下 划线。 重要: GBase 8s ESQL/C 产品中使用的许多变量名称以下划线开始。要避免与内部 GBase 8s ESQL/C 变量名称的冲突,请避免变量名称的第一个字符使用下划线。 C 变量名称是区分大小写的,因此变量 hostvar 和 HostVar 是不同的。 如果您的客户端语言环境支持非 ASCII 字符,那么可以在 GBase 8s ESQL/C 中使用 非 ASCII (非英语)字符。 提示: 好的编程习惯需要您为主机变量名称创建一个命名规范。 主机变量数据类型 因为主机变量是 C 变量,您必须在声明它时给它指定一个 C 数据类型。否则,当您 在 SQL 语句中使用主机变量时,必须将它与 SQL 数据类型关联起来。 可以声明主机变量为许多更复杂的 C 数据类型,例如指针、结构、typedef 表达式 和函数参数。 初始主机变量值 可以使用 GBase 8s ESQL/C 声明具有正常 C 初始化表达式的主机变量。 以下示例显示有效的 C 初始值: EXEC SQL BEGIN DECLARE SECTION; int varname = 12; long cust_nos[8] = {0,0,0,0,0,0,0,9999}; char descr[100] = "Steel eyelets; Nylon cording."; EXEC SQL END DECLARE SECTION; GBase 8s ESQL/C 预处理器不会检查有效 C 语法的初始化表达式;它将其复制 到 C 源文件中。C 编译器诊断任何错误。 主机变量的范围 主机变量的引用的范围或范围是可以访问主变量的程序的一部分。 GBase 8s ESQL/C 声明语句的放置位置决定了变量的范围如下: 如果声明语句在程序块中,则该变量是程序块的本地变量。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 13 - 只有在此程序块中的语句才能访问此变量。 如果声明语句在程序块之外,那么该变量是模块化的。 在声明之后发生的所有程序都可以访问此变量。 在代码内声明的主变量是该块的本地变量。可以使用一对花括号({ })定义一个代码 块。 例如:下图中的主变量 blk_int 仅在大括号之间的代码块中有效,而 p_int 在块内 部和外部都有效。 图: 在代码块内部和外部声明主变量 EXEC SQL BEGIN DECLARE SECTION; int p_int; EXEC SQL END DECLARE SECTION; ⋮ EXEC SQL select customer_num into :p_int from customer where lname = "Miller"; ⋮ { EXEC SQL BEGIN DECLARE SECTION; int blk_int; EXEC SQL END DECLARE SECTION; blk_int = p_int; ⋮ EXEC SQL select customer_num into :blk_int from customer where lname = "Miller"; ⋮ } 可以嵌套块至 16 层。全局层是第一层。 以下 C 规则也适用于 GBase 8s ESQL/C 主变量的范围: 主变量是一个自动变量,除非您将其明确定义为外部或静态变量或者在任何函数外 部定义它。 函数声明的主变量是此函数的局部变量,并在函数外面屏蔽具有相同名称的定义。 不能在同一代码块中多次定义主变量。 主机变量声明示例 下图显示了如何使用 EXEC SQL 语法声明主机变量的一个示例: 图: 使用 EXEC SQL 语法声明主机变量 EXEC SQL BEGIN DECLARE SECTION; char *hostvar; /* pointer to a character */ int hostint; /* integer */ GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 14 - double hostdbl; /* double */ char hostarr[80]; /* character array */ struct { int svar1; int svar2; ⋮ } hoststruct; /* structure */ EXEC SQL END DECLARE SECTION; 下图显示了如何使用美元符号($)声明主机变量: 图: 使用美元符号($)声明主机变量 $char *hostvar; $int hostint; $double hostdbl; $char hostarr[80]; $struct { int svar1; int svar2; ⋮ } hoststruct; 主机变量信息 可以使用主变量包含下列种类的信息: SQL 标识符 SQL 标识符包括部分数据库的名称例如:表、列、索引和视图。 数据 数据是数据库服务器从数据库中获取或存储的信息。该信息可以包括空值。空值 表示列或变量的值是未知的。 主变量可以在语法允许的情况下显示在 SQL 语句中。但是,必须在主变量名称前面 加上一个符号以区分它和常规 C 变量。 SQL 标识符 SQL 标识符是数据库对象的名称。 以下对象是 SQL 标识符的示例: 数据库模式的一部分,例如:表、列、视图、索引、同义词以及存储过程名称。 动态 GBase 8s ESQL/C 结构,例如游标和语句 ID。 根据语法允许, 可以在嵌入式 SQL 语句中使用主机变量来保存 SQL 标识符的名称。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 15 - 长标识符 GBase 8s 允许长度为 128 个字符的标识符,长度可达到 32 个字符的用户名。 数据库服务器使用以下两个标准来确定客户端程序是否可以接收长标识符: 客户端程序的内部版本号 IFX_LONGID 环境变量的设置 如果将 IFX_LONGID 环境变量设置为 0 (零), 那么数据库服务器将此客户端视为 它不能处理长标识符。 如果 IFX_LONGID 设置为 1 (一) 并且客户端版本是最新版本, 那么数据库服务器将客户端视为能够接收长标识符。如果未设置 IFX_LONGID,则将其视 为设置为 1 。 重要: 如果在客户端的环境中设置了 IFX_LONGID,那么它仅对此客户端生效。 如果在数据库服务器的环境中设置了 IFX_LONGID 环境变量,那么它对所有的客户端 生效。 满足以下条件的客户端程序可以使用长标识符和长用户名,而无需重新编译: 它使用高于 9.20 版本的 ESQL/C 编译 它使用共享库(即,程序编译时没有 -static 选项) 如果数据库服务器删除长标识符或长用户名,那么将 SQLSTATE 变量设置为 '01004',并将 SQL 通信区域中(sqlca)sqlwarn1 标记设置为 'W'。 分隔标识符 如果标识符的名称不符合命名规范,那么您必须使用分隔标识符。分隔标识符是使 用双引号(" ")括起的 SQL 标识符。 当使用双引号分隔标识符时,您符合 ANSI 标准;单引号(' ')分隔字符串。 当程序必须指定一些语法上无效的标识符名称时,使用分隔标识符。可能无效的标识 符包括: 与 SQL 保留字相同的标识符。 有关 SQL 保留字的列表,请参 GBase 8s SQL 指南:语法中标识符的描述。 不含有字母字符的标识符。 要使用分隔标识符,您必须编译并运行 GBase 8s ESQL/C 程序,并设置 DELIMIDENT 。您可以在以下任一阶段设置 DELIMIDENT : 在编译时,GBase 8s ESQL/C 预处理器允许在标识符有效的 SQL 语法的区域中引用 字符串。 在运行时,数据库服务器接受在标识符有效的动态 SQL 语句中引用字符串。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 16 - 数据库实用程序(例如 dbexport)和 DB-Access 也支持分隔标识符。 重要: 当使用 DELIMIDENT 环境变量时,您可以不再使用双引号来分隔字符串。 如果您要指示引用字符串,那么使用单引号 (' ')括起此文本。 分隔标识符区分大小写。所有您放置在引号中的数据库对象名称会保留其大小写。请 牢记 GBase 8s ESQL/C 限制标识符名称的最大长度为 128 个字符。 以下限制应用于分隔标识符T: 不能对数据库名称使用分隔标识符。 不能对存储标识符、实例以及 dbspace 的名称使用分隔标识符。 DELIMIDENT 环境变量仅适用于数据库标识符。 分隔标识符的示例 下图显示了一个分隔标识符,用于指定游标名称和语句 ID 中不具有字母的字符。 图: 对游标名称使用分隔标识符 EXEC SQL BEGIN DECLARE SECTION; char curname1[10]; char stmtname[10]; EXEC SQL END DECLARE SECTION; stcopy("%#!", curname1); stcopy("(_=", stmtname); EXEC SQL prepare :stmtname from 'select customer_num from customer'; EXEC SQL declare :curname1 cursor for $stmtname; EXEC SQL open :curname; 在上图中, 还可以直接在 SQL 语句中列出游标名称或语句 ID。 例如, 以下 PREPARE 语句也有效(设置了 DELIMIDENT ): EXEC SQL prepare "%#!" from 'select customer_num from customer'; 如果设置了 DELIMIDENT,那么 PREPARE 语句之前的 SELECT 再出发必须用引 号括起,以便预处理器将其视为字符串。如果将此语句用双引号括起,那么预处理器将其 视为标识符。 要声明包含双引号的游标名称,您必须在分隔标识符字符串中使用转义字符。例如: 要使用字符串 "abc" 作为游标名称,必须转义游标名称中第一个引号: EXEC SQL BEGIN DECLARE SECTION; char curname2[10]; char stmtname[10]; EXEC SQL END DECLARE SECTION; stcopy("\"abc\"", curname2); EXEC SQL declare :curname2 cursor for :stmtname; GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 17 - 在前面的示例中,游标名称需要以下几个转义字符: 反斜杠(\)是 C 转义字符。您需要它转义双引号。 若没有转义字符,那么 C 编译器将此双引号解释为字符串的末尾。 游标名称必须包含两个双引号。 第一个双引号转义双引号,第二个双引号是字符双引号。ANSI 标准表明您不能使用 反斜杠转义引号。必须在游标名称中使用另一个引号转义此双引号。 下表显示了包含已经处理过的游标名称的字符串。 表 1. 处理后的转义游标名称字符串 处理器 处理后 ESQL/C 预处理器 \"\"abc C 编译器 ""abc 符合 ANSI 的数据库服务器 "abc 主机变量中的空值 空值表示未知或不可用的值。该值区别于任何给出的数据类型的合法值。 空值的表示取决于计算机和数据类型。通常,该表示法不对应与 C 数据类型的合法 值。不要尝试对包含空值的主机变量执行计算或其它操作。 因此,程序必须具有识别空值的一些方法。要处理空值,GBase 8s ESQL/C 提供了以 下功能: risnull() 和 rsetnull() 库函数用于测试主变量是否包含空值, 是否将主变量设置为空值。 指示变量是特殊的 GBase 8s ESQL/C 变量,它可以容纳允许为空值的数据库列值的 主机变量。 指示变量的值显示关联的主机变量是否包含空值。 在符合 ANSI 的数据库中, 在 INSERT 语句或任何 SQL 语句的 WHERE 子句中的 主机变量必须为空终止。 数据结构中的主机变量 GBase 8s ESQL/C 支持在下列数据结构中使用主机变量: 数组 C 结构(struct) C typedef 语句 指针 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 18 - 函数参数 主机变量的数组 GBase 8s ESQL/C 支持主机变量的数组的声明。当声明此数组时必须提供整数值作为 数组的大小。主机变量的数组可以是一维或二维。 可以在 GBase 8s ESQL/C 语句中使用数组的元素。例如:如果您提供以下声明: EXEC SQL BEGIN DECLARE SECTION; long customer_nos[10]; EXEC SQL END DECLARE SECTION; 您可以使用以下语法: for (i=0; i<10; i++) { EXEC SQL fetch customer_cursor into :customer_nos[i]; ⋮ } 如果数组是 CHAR 类型,那么也可以在某些 SQL 语句中单独使用数组名称。 将 C 结构作为主机变量 GBase 8s ESQL/C 支持将 C 结构(struct)声明为主机变量。可以使用 GBase 8s ESQL/C 语句中的结构组件。 以下 cust_rec 变量的定义,用于 stores7 数据库中 customer 表的前三列的主机 变量: EXEC SQL BEGIN DECLARE SECTION; struct customer_t { int c_no; char fname[32]; char lname[32]; } cust_rec; EXEC SQL END DECLARE SECTION; 以下 INSERT 语句在其 VALUES 子句中指 cust_rec 主变量的组件: EXEC SQL insert into customer (customer_num, fname, lname) values (:cust_rec.c_no, :cust_rec.fname, :cust_rec.lname); 如果 SQL 语句需要单个主机变量,您必须使用结构名称来指定主机变量。 GBase 8s 在 UPDATE 语句的 SET 子句中需要组件名称。 在允许主机变量的 SQL 语句中,可以指定 C 结构的名称并且 GBase 8s ESQL/C 将 结构变量的名称扩展到每个组件元素。 可以将语法与 SQL 语句配合使用 (例如: 带有 INTO 子句的 FETCH 语句或带有 VALUES 子句的 INSERT 语句)。 下面的 INSERT 语句在其 VALUES 子句中指定整个 cust_rec 结构: GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 19 - EXEC SQL insert into customer (customer_num, fname, lname) values (:cust_rec); 该插入操作执行与指定 cust_rec 结构的各个组件名称的插入操作相同。 使用 C typedef 语句作为主机变量 GBase 8s ESQL/C 支持 C typedef 语句并允许在主机变量的类型声明中使用 typedef 名称。 例如,以下代码创建 smallint 类型为短整型,serial 类型为长整型。然后声明 row_nums 变量为 serial 变量的数组,变量 counter 为 smallint 。 EXEC SQL BEGIN DECLARE SECTION; typedef short smallint; typedef long serial; serial row_nums [MAXROWS]; smallint counter; EXEC SQL END DECLARE SECTION; 不能使用将多维数组或联合或函数指针命名的 typedef 语句作为主变量的类型。 使用指针作为主机变量 如果程序使用指针将数据输入到 SQL 语句,那么您可以使用指针作为主机变量。 例如,下图显示了如何将游标和语句相关联并将值插入到表中。 图: 声明字符指针以输入数据 EXEC SQL BEGIN DECLARE SECTION; char *s; char *i; EXEC SQL END DECLARE SECTION; /* Code to allocate space for two pointers not shown */ s = "select * from cust_calls"; i = "NS"; ⋮ EXEC SQL prepare x from :s; EXEC SQL insert into state values (:i, 'New State'); 下图显示了如何使用整数指针将数据输入到 INSERT 语句中。 图: 声明整数指针以输入数据 EXEC SQL BEGIN DECLARE SECTION; short *i; int *o; short *s; EXEC SQL END DECLARE SECTION; GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 20 - short i_num = 3; int o_num = 1002; short s_num = 8; i = &i_num; o = &o_num; s = &s_num; EXEC SQL connect to 'stores7'; EXEC SQL insert into items values (:*i, :*o, :*s, 'ANZ', 5, 125.00); EXEC SQL disconnect current; 如果使用的主机变量是指向 char 的指针,以接收来自 SELECT 语句的数据,那么 您会接收到一个编译警告并且结可能会截断结果。 函数参数作为主机变量 可以使用主机变量作为函数的参数。您必须在主机变量的名称的前面加上 parameter 关键字以声明它为一个函数参数。 例如,下图显示了一个具有 Kernighan 和 Ritchie-Style 原型声明的代码片段,有三 个参数其中两个是主机变量。 图: 使用 EXEC SQL 将主机变量声明为 Kernighan 和 Ritchie-Style 函数声明的参数 f(s, id, s_size) EXEC SQL BEGIN DECLARE SECTION; PARAMETER char s[20]; PARAMETER int id; EXEC SQL END DECLARE SECTION; int s_size; { select fname into :s from customer where customer_num = :id; ⋮ } 还可以使用美元符号($)声明参数主机变量。例如:下图显示了图 1中的函数头, 它使用美元符号($)。 图: 使用美元符号($)将主机变量声明为函数的参数 f(s, id, s_size) $parameter char s[20]; $parameter int id; int s_size; 可以将 ANSI 样式的原型函数声明中的参数声明为主变量。还可以将所有参数放入 EXEC SQL 声明部分中的原型函数声明,即使某些参数不能用作主机变量。下图显示了函 数指针 f 可以包含在 EXEC SQL 声明部分中,即使它不是有效的主机变量并且不能作为 主机变量使用。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 21 - 图: 使用 EXEC SQL 将主机变量声明为 ANSI 样式函数声明的参数 int * foo( EXEC SQL BEGIN DECLARE SECTION; PARAMETER char s[20], PARAMETER int id, PARAMETER int (*f) (double) EXEC SQL END DECLARE SECTION; ) { select fname into :s from customer where customer_num = :id; ⋮ } 允许在 EXEC SQL 声明段中包含函数参数的功能符合与在 EXEC SQL 声明段中允 许使用任何有效的 C 声明语法的要求,来为 C 和 GBase 8s ESQL/C 源文件使用注释头 文件。 重要: 如果您想要定义 ANSI 样式参数的 GBase 8s ESQL/C 主机变量, 那么必须使 用 EXEC SQL BEGIN DECLARE SECTION 和 EXEC SQL END DECLARE SECTION 语 法。不能使用 $BEGIN DECLARE 和 $END DECLARE 语法。因为以美元符号($)开头 的 SQL 语句必须以分号结尾。 但是, ANSI 语法要求参数列表中的每个参数不能以分号结 束符结束,但是可以用逗号(,)分隔符。 下列限制应用于使用主机变量作为函数参数: 不能在 C 代码块中声明参数变量。 不能在不是函数头部分的主机变量的声明中使用 parameter 关键字。如果这样做, 您将收到不可预知的结果。 Windows 环境中的主机变量 本节描述了有关 Windows™ 环境特有的 GBase 8s ESQL/C 主机变量: 如何使用非 ANSI 存储类修饰符声明主变量 如何声明全局 GBase 8s ESQL/C 变量 使用非 ANSI 存储类修饰符声明主变量 ANSI C 标准为变量声明定义了一组存储类修饰符。Windows™ 环境中的 C 编译器 通常支持非 ANSI 存储类修饰符。为了在 GBase 8s ESQL/C 主机变量声明中为这些非 ANSI 存储类说明符提供支持,GBase 8s ESQL/C 预处理器支持 ANSI 语法的形式,如图 所示。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 22 - Declaration 元素 意义 限制 语法 modifier name 要传递给 C 编译进行翻 译的的文本。 该文本通常是存储类修 饰符的名称。 该修饰符必须对 C 编译 器有效或者是您的程序 中定义的名称。 请参阅 C 编译器文档。 variable name ESQL/C 主机变量的标 识符名称 无 请参阅声明主机变量。 variable type ESQL/C 主机变量的数 据类型 该类型必须是有效的 C 或 ESQL/C 数据类型。 请参阅声明主机变量。 例如: Microsoft™ Visual C++ 编译器支持 declspec 编译器伪指令以使您能能声明扩 展的存储类属性。该编译器伪指令具有以下语法: __declspec(attribute) var_type var_name; 在此示例中, attribute 是受支持的关键字 (例如 thread 、 dllimport 或 dllexport) , var_type 是变量的数据类型,var_name 是变量名称。 为了使您能够将 GBase 8s ESQL/C 主机变量声明为扩展存储类变量,GBase 8s ESQL/C 预处理器支持具有以下语法的 declspec 伪指令: @("__declspec(attribute)") var_type var_name; 在此示例中,attribute 、var_type 和 var_name 与上一个示例的中相同。您可能 会发现为 declspec 语法声明宏定义很方便。以下示例将 threadCount 声明为线程扩展 存储类的实例特定整数变量: #define DLLTHREAD __declspec(thread) ⋮ EXEC SQL BEGIN DECLARE SECTION; @("DLLTHREAD") int threadCount; EXEC SQL END DECLARE SECTION; GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 23 - 本示例创建了 DLLTHREAD 宏以简化线程扩展存储类属性的声明。您可以声明类似 的宏来简化要导出(导入)动态链接库(DLL)的变量的声明,如下所示: #define DLLEXPORT __declspec(dllexport); ⋮ EXEC SQL BEGIN DECLARE SECTION; @("DLLEXPORT") int winHdl; EXEC SQL END DECLARE SECTION; 指示变量 当 SQL 语句返回值时,它将返回指定列的主机变量。在某些情况下,可以将指示变 量与主机变量相关联, 以获取有关返回值的其它信息。 如果指定指示变量, GBase 8s ESQL/C 将其返回给主机变量。 指示变量为以下情况提供了附加信息: 如果主机变量与数据库列相关联或者与允许空值的聚集函数相关联, 则指示变量 可以指定该值是否为空。 如果主机变量是字符数组并且列值被传输截断, 那么指示变量可以指定返回值的 大小。 以下主题描述如何声明指示变量并将它与主机变量关联,以及 GBase 8s ESQL/C 如 何设置指示变量以指定前述的两个条件。 声明指示变量 可以与主机变量相同的方式声明指示变量, 如下所示, 在 BEGIN DECLARE SECTION 和 END DECLARE SECTION 语句之间: EXEC SQL BEGIN DECLARE SECTION; -- put indicator variable declarations here EXEC SQL END DECLARE SECTION; 指示变量可以是除 DATETIME 或 INTERVAL 外的任何数据类型。通常,将指示变 量声明为整数。例如:假如您的程序声明了名为 name 的主机变量。可以声明名为 nameind 的 short 整型指示变量 ,如下所示: EXEC SQL BEGIN DECLARE SECTION; char name[16]; short nameind; EXEC SQL END DECLARE SECTION; 如果客户机语言环境支持非 ASCII 字符,那么您可以在 GBase 8s ESQL/C 指示变量 名称中使用非 ASCII(非英语)字符。 将指示变量与主机变量相关联 可以使用以下两种方式之一将指示变量与其主变量相关联: 在指示变量之间加上冒号(:)前缀,将关键字 INDICATOR 放置在主变量名和指示 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 24 - 变量名之间,如下所示: :hostvar INDICATOR :indvar 在主变量名和指示变量之间放置一个分隔符号。下列分隔符号有效: 冒号(:) :hostvar:indvar 美元符号($) $hostvar$indvar 可以使用美元符号($) 代替冒号(:) ,但是冒号使代码更容易阅读。 主变量和指示变量之间可以有一个或多个空白字符。例如:以下两种格式都可以在 hostvar 主机变量上指定指示变量 hostvarind: $hostvar:hostvarind $hostvar :hostvarind 指示空值 当 GBase 8s ESQL/C 语句对主机变量返回空值时,该值可能不是有意义的 C 值。您 的程序可以采取以下操作之一: 如果您已经为此主变量定义了指示变量,那么 GBase 8s ESQL/C 将此指示变量 设置为 -1。 您的程序可以检查到此指示变量的值为 -1。 如果未定义指示变量,那么 GBase 8s ESQL/C 运行时的行为取决于编译程序的 方式: ₒ 如果使用 -icheck 预处理器选项编译查程序,那么当数据库服务器返 回空值时 GBase 8s ESQL/C 生成错误并将 sqlca.sqlcode 设置为负 数。 ₒ 如果没有使用 -icheck 选项编译程序,那么当数据库服务器返回空值 时 GBase 8s ESQL/C 不会产生错误。 在这种情况下, 可以使用 risnull() 函数测试空值的主变量。 如果返回主变量的值不为空,那么 GBase 8s ESQL/C 将指示变量设置为 0 。如果 SQL 操作失败, 那么指示变量的值无意义。 因此, 请在检查主机变量的空值之前检查 SQL 语句的输出结果。 INSERT 语句的 NULL 关键字允许您向表的行插入空值。 作为 INSERT 语句的替代 方法,可以使用带有主机变量的负指示变量。 如果您想要在指示符设置为空(-1)时插入变量,那么指示值优先于变量值。在这种 情况下,插入的值将为 NULL,而不是主机变量的值。 当您将聚集函数的值的返回到主机变量中时,请记住,当数据库服务器在空表上执行 聚集函数时,聚集操作的结果为空值。此规则的唯一例外是 COUNT(*) 聚集函数,它在 此情况下返回 0 。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 25 - 重要: 如果您激活数据库服务器的 DATASKIP 功能, 那么如果所有分片离线或者所 有联机的分片是空时,聚集函数也返回空。 指示截断值 当 SQL 语句将空值返回到主机变量字符数组中时,它可能截断该值以适应该变量。 如果您为此主机变量定义了指示变量,那么 GBase 8s ESQL/C: 将 SQLSTATE 变量设置为 "01004" 以表示截断的发生。 GBase 8s ESQL/C 还将 sqlca.sqlwarn 结构的 sqlwarn1 设置为 W。 将关联的指示变量设置为等于截断前 SQL 主机变量的大小(以字节为单位)。 如果未定义指示变量,那么 GBase 8s ESQL/C 仍会设置 SQLSTATE 和 sqlca.sqlwarn 表示截断。但是,您的程序无法确定多少数据被截断。 如果数据库服务器返回未截断的值或空值,那么 GBase 8s ESQL/C 将指示变量设置 为 0 。 使用指示变量的示例 图 1 和 图 2中的代码段显示了如何指示变量和主机变量的示例。这两个示例都使 用指示变量执行以下任务: 确定字符数组中是否发生截断 如果在 customer 表中定义长度超过 15 个字符的 lname,那么 nameind 包含 lname 列的实际长度。name 主机变量包含 lname 值的前 15 个字符。 (字符串 name 必须以空字符结尾。)如果具有 customer_num = 105 代表的公司的姓氏短于 15 个字 符,那么 GBase 8s ESQL/C 仅截断尾随的空格。 检查空值 如果 company 对同一客户具有空值,那么 compind 具有一个负值。不能预测该 字符数组 comp 的内容。 0下图显示了 SQL 语句使用 EXEC SQL 语法的 GBase 8s ESQL/C 程序。 图: 使用带有 EXEC SQL 和冒号(:)的指示变量 EXEC SQL BEGIN DECLARE SECTION; char name[16]; char comp[20]; short nameind; short compind; EXEC SQL END DECLARE SECTION; ⋮ EXEC SQL select lname, company into :name INDICATOR :nameind, :comp INDICATOR :compind from customer GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 26 - where customer_num = 105; 图 1使用 INDICATOR 关键字将主变量和指示变量关联。此方法使用 ANSI 标准编 译。 下图显示了使用美元符号($)格式的 SQL 语句的 GBase 8s ESQL/C 程序示例。 图: 使用带美元符号($)的指示变量 $char name[16]; $char comp[20]; $short nameind; $short compind; ⋮ $select lname, company into $name$nameind, $comp$compind from customer where customer_num = 105;