在连接数据库的过程中我们有的时候可能会遇到连接数据库出错、插入数据出错、sql语句写错等等情况,除了这些,我们还会在插入和读取数据时会遇到处理 null 值的问题,以下代码演示了如何对 sql 执行出错进行处理,并执行了一个 null 值插入的操作,中间引入了指示变量的概念,就是专门为了处理 null 值而存在的,注意在插入数据时,指示变量是紧随宿主变量的(:loc:loc_ind)。后面我们将介绍 select 查询出来的 null 值该如何处理。


代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include “sqlca.h”

// 拓展 sqlgls 函数作用域
extern sqlgls(char * , size_t *, size_t * );

EXEC SQL BEGIN DECLARE SECTION;

char *serversid = “scott/tiger@orcl”;

// 宿主变量,c与sql的一种数据类型的桥梁
int deptno;
char dname[20];
char loc[10];

// loc 的指示变量,唯一的作用就是用来处理null值
short loc_ind;

EXEC SQL END DECLARE SECTION;

void sqlerr()
{
// 临时变量
charstm[120];
size_tsqlfc, stmlen=120;
unsigned int ret = 0;

// 让下一次出现错误时不再跳转到函数中,而是继续下一步(CONTINUE)
// 防止处理函数中有执行错误再次调用处理函数而导致的递归
EXEC SQL WHENEVER SQLERROR CONTINUE;

// 获取错误的sql语句
ret = sqlgls(stm, &stmlen, &sqlfc);
// c语言使用printf可以用 %.*s 的方式来打印两个衔接的变量
printf(“%.*s\n”, stmlen, stm);
// sqlca.sqlerrm.sqlerrml 为错误编号长度
// sqlca.sqlerrm.sqlerrmc 为错误内容
printf(“%.*s\n”, sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);

// 执行回滚并释放连接
EXEC SQL ROLLBACK WORK RELEASE;
exit(1);
}

int main(int argc, char* argv[])
{
int ret = 0;

// 开启错误处理机制,指定错误处理函数为 sqlerr
EXEC SQL WHENEVER SQLERROR DO sqlerr();

// 连接 oracle 服务器
EXEC SQL CONNECT :serversid;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf(“connect oracle error… code = %d\n”, ret);
return ret;
}

// 插入一个已经存在的 deptno ,会导致出错
deptno = 60;
strcpy(dname, “dengjia”);
strcpy(loc, “hello”);
// 如果希望将 loc 插入时置为 null,那么就把指示变量 loc_ind 设置为 -1
loc_ind = -1;
// 插入数据时,注意指示变量的用法
EXEC SQL insert into dept(deptno, dname, loc) values(:deptno, :dname, :loc:loc_ind);
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf(“insert into error… code = %d\n”, ret);
return ret;
}

EXEC SQL commit release;

return 0;
}

执行效果

我们插入了一个已经存在的数据,程序执行后提示的错误如下: 2015-07-24_165554 首先是将错误的 sql 语句输出了出来,随后告诉我们是因为 pk_dept 唯一,不能再插入同样的数据。