使用美元符号($)表示每个声明。 在声明本身中,您必须指定以下信息: 主机变量的名称 主机变量的数据类型 主机变量的初始值(可选) 主机变量的范围(由程序中放置的声明决定) 主机变量名称 主机变量的名称必须符合 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 编程指南 南大通用数据技术股份有限公司 - 13 -
GBase 8s ESQL/C 声明语句的放置位置决定了变量的范围如下: 如果声明语句在程序块中,则该变量是程序块的本地变量。 只有在此程序块中的语句才能访问此变量。 如果声明语句在程序块之外,那么该变量是模块化的。 在声明之后发生的所有程序都可以访问此变量。 在代码内声明的主变量是该块的本地变量。可以使用一对花括号({ })定义一个代码 块。 例如:下图中的主变量 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 语法声明主机变量
GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 14 -
EXEC SQL BEGIN DECLARE SECTION; char *hostvar; /* pointer to a character */ int hostint; /* integer */ double hostdbl; /* double */ char hostarr[80]; /* character array */ struct { int svar1; int svar2;
子句的 FETCH 语句或带有 VALUES 子句的 INSERT 语句)。 下面的 INSERT 语句在其 VALUES 子句中指定整个 cust_rec 结构: 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;
GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 20 -
short *s; EXEC SQL END DECLARE SECTION;
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 样式的原型函数声明中的参数声明为主变量。还可以将所有参数放入
GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 21 -
EXEC SQL 声明部分中的原型函数声明,即使某些参数不能用作主机变量。下图显示了函 数指针 f 可以包含在 EXEC SQL 声明部分中,即使它不是有效的主机变量并且不能作为 主机变量使用。 图: 使用 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; ⋮
- 135 - Public Sub CreateGBaseCommand(gsConnection As GBaseConnection, _ gsSelectQuery As String, gsParamArray() As GBaseParameter) Dim gsCommand As New GBaseCommand(gsSelectQuery, gsConnection) gsCommand.CommandText = "SELECT id, name FROM gstable" _ &" WHEREage=?age" gsCommand.UpdatedRowSource = UpdateRowSource.Both gsCommand.Parameters.Add(gsParamArray) Dim j As Integer For j = 0 To gsCommand.Parameters.Count - 1 gsCommand.Parameters.Add(gsParamArray(j)) Next j Dim gsMessage As String = "" Dim i As Integer For i = 0 To gsCommand.Parameters.Count - 1 gsMessage += gsCommand.Parameters(i).ToString() & ControlChars.Cr Next i Console.WriteLine(gsMessage) End Sub
[C#] public void CreateGBaseCommand(GBaseConnection gsConnection, string gsSelectQuery,GBaseParameter[] gsParamArray) { GBaseCommand gsCommand = new GBaseCommand(gsSelectQuery, gsConnection); gsCommand.CommandText = "SELECT id, name FROM gstable WHERE age=?age"; gsCommand.Parameters.Add(gsParamArray); for (int j=0; j{ gsCommand.Parameters.Add(gsParamArray[j]) ; } string gsMessage = ""; for (int i = 0; i < gsCommand.Parameters.Count; i++)