指示变量¶
对于任何一个主变量,都可以定义一个相应的指示变量。在SQL语句每使用一次主变量,都会在和该主变量相关的指示变量中存入结果代码。所以,指示变量能够监测主变量。
对于输入主变量,相应的指示变量可以赋值为NULL。对于输出主变量,相应的指示变量值可以用来监测返回结果,如是否为空,字段值是否被截断等。指示变量必须是整型变量,而且和主变量一样,也需要在DECLARE区间声明。
对于输入主变量对应的指示变量,该指示变量的含义如下表所示:
表 -3
| 值 | 含义 |
|---|---|
| >=0 | 神通数据库将把主变量的值赋给相应列 |
| -1 | 神通数据库将赋NULL值给相应列,无论主变量的值是什么 |
对于输出主变量对应的指示变量,该指示变量的含义如下表所示:
表 -4
| 值 | 含义 |
|---|---|
| =0 | 操作成功 |
| -1 | 对应的输出主变量返回NULL |
| >0 | 在取回值时,如果字符串被截断,此时指示变量中存放截断前字符串的实际长度 |
注解
指示变量必须定义为整型数。用在SQL语句中时,必须在变量名字前加冒号(:),并且紧跟在所对应的主变量的后面或者用INDICATOR关键字与主变量隔开。
插入空值
可以用指示变量插入空值。在INSERT语句之前,对于每个希望插入空值的列, 设置它们相关的主变量为-1,如下例所示:
ind_name = -1;
EXEC SQL INSERT INTO employee(empnum, empname)
VALUES (:hnum, :hname:ind_name);
指示变量ind_name为-1,表明正在插入的这个元组的empname列为NULL值。
也可以把NULL硬编码到应用程序代码中去,如下所示:
EXEC SQL INSERT INTO employee(empnum, empname)
VALUES (:hnum, NULL);
这样的书写方式就不太灵活,但是它的可读性更强。 通常,是否插入NULL可能依赖于一定的条件,如下所示:
printf(" 请输入员工的级别(grade):\n");
scanf("%s", hgrade);
if (hgrade == 0)
ind_grade = -1;
else
ind_grade = 0;
EXEC SQL INSERT INTO employee (empnum, grade)
VALUES(:hnum, :hgrade:ind_grade);
返回空值
可以用指示变量检测是否返回空值,如下例所示:
EXEC SQL SELECT empname, grade, city
INTO :hname, :hgrade, :hcity :ind_city
FROM employee
WHERE empnum = :hnum;
If (ind_city == -1)
printf("该员工所在的城市未知. \n");
else
printf("该员工来自于 %s.\n", hcity);
获取空值
如果把一个NULL值SELECT或者FETCH到一个没有相关指示变量的主变量中去,那么,用户通过查看SQLSTATE变量就可以得到相应的错误状态为:22002。这个错误状态表明结果表中有NULL值,但是,用户没有指定相应的指示变量。在出现这个错误状态时,用户必须为结果表中为空值的列使用指示变量;或者对SELECT或者FETCH的表进行处理,消除空值。总之,不能让结果表有空值和是空值的列没有对应一个指示变量这两个情况一起发生。
关于SQLSTATE请参见 错误处理 和附录C 附录C. SQLSTATE列表 。
检测空值
用户可以在WHERE子句中使用指示变量检测空值,如下所示:
EXEC SQL SELECT empname, grade
INTO :hname, :hgrade
FROM employee
WHERE :hcity INDICATOR :ind_city IS NULL;
注解
不能使用关系操作符来比较是否等于NULL。如果grade列含有一个或者多个NULL, 那么下面示例中的SELECT语句将不能成功执行:
EXEC SQL SELECT empname, grade
INTO :hname, :hgrade
FROM employee
WHERE grade = :hgrade;
下面这个例子说明了在列值可能为NULL的情况下如何正确比较值是否相等:
EXEC SQL SELECT empname, grade
INTO :hname, :hgrade
FROM employee
WHERE (grade = :hgrade ) OR
((grade IS NULL) AND (:hgrade INDICATOR :ind_grade IS NULL));
字符串截断
如果用户SELECT或者FETCH一个被截断的列值到一个主变量中, 而且该主变量没有关联一个指示变量,那么,将产生一个警告。 此时,用户可以定义并且读取SQLSTATE变量,得到值01004; 也可以通过调用系统提供的sqlprint()打印出警告信息。如下例所示:
EXEC SQL BEGIN DECLARE SECTION;
Char hcity[2]; --定义一个小字符数组,它无法存放一个完整的用户名
EXEC SQL END DECLARE SECTION;
Char SQLSTATE[6];
EXEC SQL SELECT city
INTO :hcity
FROM branch
WHERE brchnum = '571';
printf("SQLSTATE = %s\n", SQLSTATE);
sqlprint();
在表中确实存在brchnum为'571'而且city列值的字符个数大于等于2的城市名的情况下, 执行该语句将输出:
SQLSTATE = 01004
String right truncation in line ***