在连接数据库的过程中我们有的时候可能会遇到连接数据库出错、插入数据出错、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() { // 临时变量 char stm[120]; size_t sqlfc, 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; }
执行效果
我们插入了一个已经存在的数据,程序执行后提示的错误如下:
首先是将错误的 sql 语句输出了出来,随后告诉我们是因为 pk_dept 唯一,不能再插入同样的数据。