pname, dept ); } while ( 1 );
EXEC SQL CLOSE c1; (4) CHECKERR (CLOSE CURSOR); EXEC SQL ROLLBACK; CHECKERR (ROLLBACK);
printf( \\nOn second thought -- changes rolled back.\\n ); EXEC SQL CONNECT RESET; CHECKERR (CONNECT RESET); return 0; }
/* end of program : CURSOR.SQC */ 在上面这个程序中,
(1)定义了一个游标,并指明游标的名字为C1,同时给出了相对于游标的查询语句和游标类型(UPDATE)。 (2)打开游标。系统执行查询语句,建立结果表,将游标指针指向第一条记录之前。
(3)FETCH语句将指针的下一条记录取出,将记录中的数据存放在相应的宿主变量中。同时指针下移。 (4)用CLOSE关闭游标。 3.2.4插入、删除和修改操作
DB2中的插入、删除和修改操作同SQL语句中INSERT、DELETE和UPDATE语句类似。只需在相应的SQL语句前加上EXEC SQL即可。请看下面这个例子:
例、将staff表中所有工作为―Mgr‖的职工的工作改变为―clerk‖,并将staff表中所有工作为―sale‖的职工信息删除。最后插入一新行。 #include
EXEC SQL INCLUDE SQLCA; (1)
#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1; int main(int argc, char *argv[]) {
EXEC SQL BEGIN DECLARE SECTION; (2) char statement[256]; char userid[9]; char passwd[19]; char jobUpdate[6];
EXEC SQL END DECLARE SECTION; printf( \\nSample C program: UPDAT \\n); if (argc == 1) {
EXEC SQL CONNECT TO sample; CHECKERR (CONNECT TO SAMPLE); }
else if (argc == 3) { strcpy (userid, argv[1]); strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd; (3) CHECKERR (CONNECT TO SAMPLE); } else {
printf (\\nUSAGE: updat [userid passwd]\\n\\n); return 1; } /* endif */
strcpy (jobUpdate, Clerk);
EXEC SQL UPDATE staff SET job = :jobUpdate WHERE job = Mgr; (4) CHECKERR (UPDATE STAFF);
printf (All Mgr have been demoted to Clerk!\\n ); strcpy (jobUpdate, Sales);
EXEC SQL DELETE FROM staff WHERE job = :jobUpdate; (5) CHECKERR (DELETE FROM STAFF); printf (All Sales people have been deleted!\\n); EXEC SQL INSERT INTO staff
VALUES (999, Testing, 99, :jobUpdate, 0, 0, 0); (6) CHECKERR (INSERT INTO STAFF); printf (New data has been inserted\\n); EXEC SQL ROLLBACK; (7) CHECKERR (ROLLBACK);
printf( On second thought -- changes rolled back.\\n ); EXEC SQL CONNECT RESET; CHECKERR (CONNECT RESET); return 0; }
/* end of program : UPDAT.SQC */ 上述语句:
(1)包含SQLCA结构。该结构用于将SQL语句执行的结果信息返回给应用程序。 (2)宿主变量定义。
(3)连接到DB2的SAMPLE数据库。
(4)UPDATE语句将staff表中所有工作为―Mgr‖的职工的工作改变为―clerk‖。 (5)DELETE语句将staff表中所有工作为―sale‖的职工信息删除。 (6)INSERT语句插入一新行。
指定位置的UPDATE语句和DELETE语句
游标操作除了可以将多行的查询结果返回给应用程序,它还可以与UPDATE语句和DELETE相结合,根据游标当前的位置,对指针所指的这个行数据执行UPDATE操作和DELETE操作。它的语法为: UPDATE…. WHERE CURRENT OF cursor_name
DELETE [FROM] {table_name | view_name} WHERE CURRENT OF cursor_name
请看下面这个例子。这个例子的作用是:将部门大于40的员工的工作改变为―clerk‖,部门小于等于40的员工信息删除。 #include
#include
EXEC SQL INCLUDE SQLCA;
#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1; int main(int argc, char *argv[]) {
EXEC SQL BEGIN DECLARE SECTION; char pname[10]; short dept; char userid[9]; char passwd[19];
EXEC SQL END DECLARE SECTION; printf( Sample C program: OPENFTCH\\n ); if (argc == 1) {
EXEC SQL CONNECT TO sample; CHECKERR (CONNECT TO SAMPLE); }
else if (argc == 3) { strcpy (userid, argv[1]); strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd; CHECKERR (CONNECT TO SAMPLE); } else {
printf (\\nUSAGE: openftch [userid passwd]\\n\\n); return 1; } /* endif */
EXEC SQL DECLARE c1 CURSOR FOR SELECT name, dept FROM staff WHERE job=Mgr FOR UPDATE OF job; EXEC SQL OPEN c1;
CHECKERR (OPEN CURSOR); do {
EXEC SQL FETCH c1 INTO :pname, :dept; if (SQLCODE != 0) break;
if (dept > 40) {
printf( %-10.10s in dept. - will be demoted to Clerk\\n, pname, dept );
EXEC SQL UPDATE staff SET job = Clerk WHERE CURRENT OF c1; CHECKERR (UPDATE STAFF); } else {
printf (%-10.10s in dept. - will be DELETED!\\n,
pname, dept);
EXEC SQL DELETE FROM staff WHERE CURRENT OF c1; CHECKERR (DELETE); } /* endif */ } while ( 1 );
EXEC SQL CLOSE c1;
CHECKERR (CLOSE CURSOR); EXEC SQL ROLLBACK; CHECKERR (ROLLBACK);
printf( \\nOn second thought -- changes rolled back.\\n ); EXEC SQL CONNECT RESET; CHECKERR (CONNECT RESET); return 0; }
/* end of program : OPENFTCH.SQC */
在通过游标进行UPDATE和DELETE操作时,相应的游标在定义时必须加上FOR UPDATE子句。操作时,游标必须打开,而且正指向一行数据。 3.2.5 SQLCA
应用程序执行时,每执行一条SQL语句,就返回一个状态符和一些附加信息。这些信息反映了SQL语句或API的执行情况,它有助于用户分析应用程序的错误所在。这些信息都存放在一个定义在sqlca.h的sqlca结构中。如果一个源文件中后SQL语句,则必须要在源程序中定义一个SQLCA结构,而且名为SQLCA。最简单的定义方法是在源文件中加入一些语句:EXEC SQL INCLUDE sqlca.h 下面,我们首先看看SQLCA的结构: SQL_STRUCTURE sqlca {
_SQLOLDCHAR sqlcaid[8]; /* Eyecatcher = SQLCA */ long sqlcabc; /* SQLCA size in bytes = 136 */ #ifdef DB2_SQL92E
long sqlcade; /* SQL return code */ #else
long sqlcode; /* SQL return code */ #endif
short sqlerrml; /* Length for SQLERRMC */
_SQLOLDCHAR sqlerrmc[70]; /* Error message tokens */ _SQLOLDCHAR sqlerrp[8]; /* Diagnostic information */ long sqlerrd[6]; /* Diagnostic information */ _SQLOLDCHAR sqlwarn[11]; /* Warning flags */ #ifdef DB2_SQL92E
_SQLOLDCHAR sqlstat[5]; /* State corresponding to SQLCODE */ #else
_SQLOLDCHAR sqlstate[5]; /* State corresponding to SQLCODE */ #endif };
结构中各个字段的作用是: lSqlcaid:包含字符串―SQLCA‖。 lSqlcabc:包含SQLCA结构的长度。
lSqlcode:该值反映了SQL语句执行后的状态,0表示SQL执行成功;<0表示SQL语句执行出错;>0反映了一些特殊情况(如:没有查询结果)。不同的数据库产品,该值代表的含义可能不同。 lSqlerrml:sqlerrmc域中数据的实际长度。
lSqlerrmc:由0个或多个字符串组成,它对返回的值给予一个更详细的解释。 lSqlerrp:包含一些对用户没有用的信息。 lSqlwarn:包含了一些警告信息。
lSqlstate:长度为5的字符串。它表示SQL语句执行的结果。它的每一个含义是遵循ANSI/SQL 92标准。各个数据库产品的sqlstate域的含义都是相同的。
为了更方便地读取sqlca中SQL语句执行后的结果或错误,DB2提供了一个函数——sqlaintp,它在sql.h中声明:sqlaintp(msgbuf,bufsize,linesize,sqlcaptr)。其中msgbuf中存放信息;bufsize中存放了msgbuf的长度;linesize中存放了两个执行符之间的字符长度。函数的返回值为正,代表信息的长度;为负代表没有信息返回。
下面这个例子解释了sqlca和sqlaintp的使用方法: int check_error (char eString[], struct sqlca *caPointer) { char eBuffer[1024]; char sBuffer[1024]; short rc, Erc;
/*通过SQLCODE来判断是否出错*/ if (caPointer->sqlcode != 0) { printf (--- error report ---\\n);
printf (ERROR occured : %s.\\nSQLCODE : %ld\\n, eString, caPointer->sqlcode); /* 获取SQLSTATE信息*/
rc = sqlogstt (sBuffer, 1024, 80, caPointer->sqlstate); /*获取调用API的错误信息*/
Erc = sqlaintp (eBuffer, 1024, 80, caPointer); /* Erc中存放了eBuffer 的长度*/ if (Erc > 0) printf (%s, eBuffer);
if (caPointer->sqlcode < 0) { /*错误信息*/ if (rc == 0) {
printf (\\n%s, sBuffer); }
printf (--- end error report ---\\n); return 1; } else {
/* 仅仅是警告信息 */ if (rc == 0) {
printf (\\n%s, sBuffer); }
printf (--- end error report ---\\n);
printf (WARNING - CONTINUING PROGRAM WITH WARNINGS!\\n);