关闭

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

1064人阅读 评论(0) 收藏 举报
分类:
在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的警告错误,但适当的使用可以帮助程序检测到各种潜在的错误,并且可以使编程更加简洁。因此,此类警告信息亦应受到程序员的重视。
   警告信息在SQLCA中有两种表示方法。每一个除了+100以外的SQLCODE正返回值都代表一定的警告信息;同时,SQLCA中的SQLWARN[n](n=1,2,3,4,5,6或A)返回值也代表着相应的警告信息。当系统发现警告错误时,系统会以这两种方式通知程序。此时,查询可能会返回一些结果,但此时的结果极有可能是错误或不完整的。当SQLWARN[O]=W时,DB2提供了帮助用户判断具体警告类型的信息,其相应值及含义如下表:


SQLCA值        返回值        警告内容
SQLWARN[1]        W        序主变量长度不够而发生截取
SQLWARN[2]        W        字段功能处理的数据中有空(NULL)值
SQLWARN[3]        W        返回字段个数大于程序定义的序主变量个数
SQLWARN[4]        W        在UPDATE或DELETE操作中未指定WHERE条件
SQLWARN[6]        W        对时间数据进行数学运算后进行修正
SQLWARN[A]        W        转换出错
       假设某学校要计算某一学期各班,各科,个人的平均成绩。其中,个人平均成绩=(个人总分)/(本学期所学科目数)。由于工作人员疏忽,误将某一同学的学期学习科目输为0。在使用嵌套SQL语句的程序对相关数据进行处理时,SQLCODE返回值为-802(除数为零)导致程序终止运行。尽管用户知道可能是某一项数据错误,但无法知道具体是哪一项数据错误。对于一个拥有较多数据的学校来说,查找起来是非常费事的。通过下述办法可以很好的解决这一问题:在定义代表计算结果的序主变量的同时,为其指定一个可以为空的指示变量,如 :AVGRD :IND代表序主变量为AVGRD,指示变量为IND。此时发生被零除错误时,指示变量值被设为-2,同时SQLCODE返回值为+802警告信息。程序捕捉到此信息时,可向用户提供相应的信息,帮助用户确定出错数据位置。
   当SQLWARN[O]的值为W时,表明系统检测到警告错误。此时系统提供的警告信息也可被程序员所利用。比如:当程序把一个表中的某一字符型字段值传入一个比其长度要短的序主变量中时,发生字符截取。尽管此时SQLCODE会返回+0,但程序获取的数据是不完整的。通过为序主变量指定一个指示变量,发生同样错误时,SQLWARN[O]和SQLWARN[1]的返回值都为W,同时,指示变量被赋给了字段中数据的实际长度。此种方法甚至可以用来判断表中字段中字符串数据的实际长度。
对SQLERRD数组的调用
    SQLERRD是SQLCA中代表SQL查询运行结果的一个数组。数组中的不同元素有不同的含义。其中较常用的是SQLERRD[3]。它将返回程序中上一次INSERT,UPDATE或DELETE操作所影响到的记录数。否则,程序需要借助一定的循环来统计被以上操作影响到的记录数。但值得注意的是,在执行DELETE操作时,如果相关字段的删除类型被设为CASCADE而导致被删除其它记录数不会被包含在内;同时,如果在DELETE语句中未指定WHERE条件,则SQLERRD[3]的返回值为-1。以上两点在使用此数组时应予以注意。SQLERRD中各元素的含义以及其对于复合式SQL语句,连接方法的不同含义如下:
SQLERRD元素        表示意义        复合式SQL语句        连接方式
SQLERRD[2]        保存当前SQL语句处理的行数。但若当前SQL失败, 则无定义; 若在数组操作中出错, 则停于出错行, 这时给出成功处理的行数; OPEN 执行后, 清为0, FECTH 后增值(原有值+上本次fetch的行数); EXECUTE、INSERT、UPDATE、SELETE和SELECT后, 为成功处理的行数。
SQLERRD[3]        返回的记录数(估计)及INSERT/UPDATE或DELETE操作所影响到的记录数(不包含因限制条件而影响到的记录)           总语句数         0:由底层客户机的一段式提交委托确认1:一段式提交2:一段式只读提交3:两段式提交
SQLERRD[4]        指出语句中出错的位移, 首字符位移为0。
SQLERRD[5]        INSERT/UPDATE或DELETE操作所影响到的记录数(包含因限制条件而影响到的记录)        因限制条件而影响到的记录数        无

常用:SQLERRD[2]  ,如:#define SQLROWS sqlca.sqlerrd[2]


    DB2支持多种高级语言(包括当前极为流行的C和C++等)通过嵌套SQL语句对其上的数据进行访问。同时,由于对多种嵌套(动态,静态,复合式)方式的支持,更加增强了访问的灵活性。通过在程序中调用SQLCA,可对程序中嵌套的SQL语句的执行结果进行控制,增强了程序的可靠性,防止程序意外终止;也可使程序的编写更加简洁,提高程序的运行效率,缩短系统的处理时间。
1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:194329次
    • 积分:3861
    • 等级:
    • 排名:第8519名
    • 原创:172篇
    • 转载:10篇
    • 译文:2篇
    • 评论:26条
    友情链接
    博客专栏