嵌套SQL语句访问DB2中SQLCA的调用技巧(一)

2015-07-24 06:31:51 · 作者: · 浏览: 6
在IBM的关系型数据库产品DB2中,使用SQL Communication Area(SQLCA)将程序中嵌套的SQL语句运行情况返回给程序。在程序中有针对性地对SQLCA实施调用,可对程序中各类SQL语句的执行结果实施控制,从而避免程序的意外终止。同时,也可以提高运行效率,减小系统开销和处理时间。本文将对此作一简要介绍。
SQLCA的结构
SQLCA的结构定义如下:
struc sqlca
{ unsigned char sqlcaid[8];
long sqlabc;
long sqlcode;
short sqlerrml;
unsigned char sqlerrnmc[10];
unsigned char sqlerrp[8];
long sqlerrd[6];
unsigned char sqlwarn[21];
unsigned char sqlstate[5]; }
结构中各个域各有不同的含义和用途,部分域的功能和用途将在以下各小节中做详细探讨,其它一些域的含义如下:
sqlcaid: 标识性域,包含字符串“sqlca”.
Sqlabc: 包含sqlca结构的长度。
Sqlerrml: 包含sqlerrmc域中数据的实际长度。
Sqlerrmc: 由0或多个字串组成,它对返回的值给以一个更详细的解释。如返回的代码表示表没找到,则此域中包含未找到的表名。
Sqlerrp: 包含一些对用户无用的论断信息。
Sqlstate: 长度为5的字符串,它指示SQL语句的查询结果。与sqlca不同的是,它遵循ANSI/ISOSQL92的标准,所以,尽管不同数据库产品的sqlca结构中sqlcode域的含义不同,但sqlstate域的含义是相同的。
调用方法
DB2通过一个函数:sqlaintp,可以方便地读取sqlca中SQL语句执行后的结果和错误。此函数定义在sql.h中,可通过下述语句实现对其定义:
EXEC SQL INCLUDE sqlca.h
Sqlaintp函数格式如下:
int sqlaintp
( char *buffer
short buffer_size
short line_width
struct sqlca *sqlca )
其中, buffer为存放了sqlca信息的缓冲区;buffer_size中存放了buffer的长度;line_width存放了两个执行符之间的字符长度。函数返回值为正时代表sqlca信息的长度,为负时代表没有sqlca信息返回。一般来讲,sqlca信息都可存放在长度为512个字节的缓冲区中。
为了处理各种错误情况,DB2提供了WHENEVER语句。其具体使用方法如下:
(1) EXEC SQL WHENEVER SQLERROR action SQLCODE<0时,执行action.
(2) EXEC SQL WHENEVER SQLWARNING action SQLCODE>;0但不为100且SQLWARN[0]=W时时,执行action.
(3) EXEC SQL WHENEVER NOT FOUND action SQLCODE=100时,执行action.
其中action有两种可能:
CONTINUE:继续执行程序中的另一条命令。
GO TO label:转到label指定的语句开始。
值得注意的是,WHENEVER语句的作用范围到下一个WHENEVER时终止。
对SQLCODE的调用
在对SQLCA的调用中,最常见的就是通过访问SQLCODE来实现的。很多程序员甚至在每条SQL语句执行完毕后都设置检查SQLCODE返回值的代码,以对程序的运行进行监控。当返回值为+0的时,表明SQL语句执行成功;返回值为+100时,表明满足检索条件的记录没找到。一般来说,负的SQLCODE返回负值意味着SQL语句执行失败,程序员可在程序中实现根据不同的SQLCODE返回值,采取不同的程序流程以实现错误控制。例如,当SQLCODE的返回值为-911时, 表明系统检测到了死锁(Dead Lock),程序员可针对这种情况采取以下两种处置方法:
(1)设置循环,反复执行查询请求并检测SQLCODE,直至返回值为+0(执行成功)。
(2)设置一个计数器,执行查询请求到一定次数后终止程序或向用户发出警报。
值得注意的是,为了保证数据的完整性,有时需要针对返回的错误类型对数据库进行回滚(ROLLBACK)操作,且回滚的起点不一定是未执行成功的SQL语句导致系统所处于的状态。回滚的起点与SQL语句的嵌套类型(动态,静态,复合式)以及错误类型都有关系。尤其是后者,因为有些错误类型会导致系统作一个隐式的回滚(例如SQLCODE -911),从而使回滚的起点判断更为复杂。
尽管多数情况下我们希望SQL语句执行成功,但有些时候,通过一个故意“制造”的负的SQLCODE返回值,可以使程序中的逻辑判断更为简洁,还可在较大程度上降低系统开销。我们可以设想这样一种情况:邮电局有两种话费收据,一种是针对只安有一部电话的用户的,另一种是针对安有多部电话的用户的,两种话费收据上的项目个不相同,需要不同的子程序进行处理。在话费收据处理程序中,首先根据每一个用户唯一的ID号检索对应的电话号码,并设置计数器对检索到的记录数(安装电话数)进行统计,当某用户ID仅对应一条电话号码记录时,调用单机用户话费收据处理程序对相应用户的话费数据进行处理;当某用户ID仅对应多条电话号码记录时,调用多机用户话费收据处理程序对相应用户的话费数据进行处理。无论何种情况,都需对用户的数据重新进行读取方可进行下一步处理。也就是说,需要对一个用户的电话数据进行两次读取才能完成相应的数据处理。这无疑会极大的增加系统处理时间。通过对SQLCODE的调用,可以使这种情况得以显著改善。首先,针对每一个用户的ID作一个SELECT操作,然后检查SQLCODE返回值,当返回值为+0时,表明该用户只安装了一部电话;当返回值为-811时,表明该用户安装了不止一部电话。可由此判断应由那种程序来处理用户话费信息。采用这种解决方案,只对用户的数据读取一次就可完成用户的话费处理,几乎减少了一半的系统处理时间。与其它诸如改变表的结构等方法,此种方法对系统的改动最小,并且简便易行,效果明显。
在对数据库访问的程序中,程序通常要求实现如下功能:更新数据库中的某一条记录,当这条记录不存在时创建相应的记录。比较常见的做法是,先进行一次SELECT查询,当SQLCODE返回+0时,表明此条记录已存在,然后再重读此记录对其进行UPDATE操作;当SQLCODE返回+100时,表明相应记录不存在,接下来再进行INSTER操作。另一种实现方岸根据数据访问的特点,当对数据的更新多于新值插入时,直接进行UPDATE操作,当SQLCODE返回+0时更新成功,反之,返回+100时,需对其进行INSERT操作;当新值插入要多余于更新操作时,首先进行INSERT操作,SQLCODE值为+0时插入成功,否则返回-803,表明原记录已存在,需要进行UPDATE操作。显而易见,多数情况下,第二种方法只需对数据进行一次操作即可,从而提高系统的处理效率。
对SQLWARN的调用
尽管程序员通常总是忽略SQL的警告错误,但适当的使用可以帮助程序检测到各种潜在的错误,并且可以使 编程更加简洁。因此,此类警告信息亦应受到程序