主机变量的声明部分可出现在通常可以声明 C 变量的任何地方,包括 C 函数的参数声明部分。C 语言变量有其常规作用域(在定义它们的块中可用)。但是,因为 SQL 预处理器不扫描 C 代码,所以它与 C 语言块无关。
就 SQL 预处理器而言,主机变量在其声明之后的源模块中都是全局已知的。主机变量不得同名。此规则的唯一例外情况是当两个主机变量类型(包括任何必需的长度)相同时,它们可以同名。
最好是每个主机变量都具有唯一名称。
因为 SQL 预处理器不能分析 C 代码,因此它假定所有主机变量(不管它们是在哪里声明的)在其声明之后都是全局已知的。
// Example demonstrating poor coding EXEC SQL BEGIN DECLARE SECTION; long emp_id; EXEC SQL END DECLARE SECTION; long getManagerID( void ) { EXEC SQL BEGIN DECLARE SECTION; long manager_id = 0; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT manager_id INTO :manager_id FROM employee WHERE emp_number = :emp_id; return( manager_number ); } void setManagerID( long manager_id ) { EXEC SQL UPDATE employee SET manager_number = :manager_id WHERE emp_number = :emp_id; } |
虽然以上代码可以使用,但它却容易造成混淆,因为 SQL 预处理器在处理 setManagerID 中的语句时,要依赖于 getManagerID 内部的声明。此段代码应按如下所示重写:
// Rewritten example #if 0 // Declarations for the SQL preprocessor EXEC SQL BEGIN DECLARE SECTION; long emp_id; long manager_id; EXEC SQL END DECLARE SECTION; #endif long getManagerID( long emp_id ) { long manager_id = 0; EXEC SQL SELECT manager_id INTO :manager_id FROM employee WHERE emp_number = :emp_id; return( manager_number ); } void setManagerID( long emp_id, long manager_id ) { EXEC SQL UPDATE employee SET manager_number = :manager_id WHERE emp_number = :emp_id; } |
SQL 预处理器会看到在 #if 指令中包含的主机变量声明,因为它将忽略这些指令。另一方面,它忽略过程中的声明,因为它们不在 DECLARE SECTION 内部。相反,C 编译器会忽略 #if 指令内部的声明,并使用过程内部的声明。
这些声明能够正常工作,仅仅是因为将同名的变量声明为完全相同的类型。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |