一个游标必须首先定义, 才能使用它。语法为: EXEC SQL DECLARE 〈游标名〉CORSOR FOR SELECT 〈列〉 FROM 〈表〉 例如: EXEC SQL DECLARE CSOR, CURSOR FOR SELECT ENAME , JOB, SAL FROM EMP WHERE DEPTNO=:DEPTNO; 当赋给一个与查询相关联的游标CURSOR之后, 当SELECT查询EMP时可从数据库中返回多行,这些行就是CURSOR的一个活动区域。 注意: 定义游标必须在对游标操作之前完成; PRO*C不能引用没有定义的游标; 游标定义后,其作用范围是整个程序。所以对一个程序来讲, 同时定义两个相同的游标是错误的。
B. 打开游标 打开游标的OPEN语句主要用来输入主变量的内容,这些主要是WHERE中使用的主变量。打开游标的语句是:EXEC SQL OPEN 〈游标名〉 当打开游标后,可以从相关的查询中取出多于一行的结果。所有满足查询标准的行组成一集合,叫做“游标活动集”。通过取操作,活动集中的每一行或每一组是一个一个返回的,查询完成后, 游标就可关闭了。如图所示: 定义游标:DECLARE
开始查询:SELECT打开游标:OPEN
从活动集取数据:FETCH
查询完成
关闭游标:CLOSE
注意:1)游标处于活动集的第一行前面; 2)若改变了输入主变量就必须重新打开游标。
C. 取数据 从活动集中取出一行或一组把结果送到输出主变量中的过程叫取数据。输出主变量的定义在取数据语句中。取数据的语句如下: EXEC SQL FETCH〈游标名〉INTO:主变量1,主变量2,…… FETCH的工作过程如图所示:
查询结果查询结果
……
如图所示的查询结果指满足查询条件的查询结果。使用FETCH应注意以下几点: 游标必须先定义再打开。 只有在游标打开之后才能取数据,即执行FETCH语句。 FETCH语句每执行一次,从当前行或当前组取数据一次,下一行或下一组向上移一次。游标每次所指的行或组都为当前行或当前组,而FETCH每次都是取游标所指定的行或组的数据。 当游标活动集空之后,ORCLE返回一个SQLCA。SQLCA(=1403)。 若希望此游标再操作, 必须先关闭再打开它。 在C程序中可以开辟一个内存空间,来存放操作结果,这样就能利用开辟的空间来灵活操纵查询的结果。
D.关闭游标 取完活动集中所有行后,必须关闭游标,以释放与该游标有关的资源。 关闭游标的格式为: EXEC SQL CLOSE 游标名; 例如: EXEC SQL CLOSE C1; ORACLE V5.0版支持SQL格式“CURRENT OF CURSOR”。这条语句将指向一个游标中最新取出的行, 以用于修改和删除操作。该语句必须有取操作之后使用,它等同存储一个ROWID,并使用它。
(4).举例 EXEC SQL DECLARE SALESPEOPLE CURSOR FOR SELECT SSNO, NAME, SALARY FROM EMPLOYEE WHERE DNAME=‘Sales’; EXEC SQL OPEN SALESPEOPLE; EXEC SQL FETCH SALESPEOPLE INTO :SS,:NAME,:SAL; EXEC SQL CLOSE SALESPEOPLE;
(5)SQL嵌套的方法及应用 嵌入SQL与交互式SQL在形式上有如下差别: 在SQL语句前增加前缀“EXEC SQL”, 这一小小的差别其目的是在于预编译时容易识别出来, 以便把每一条SQL作为一条高级语言来处理。 每一SQL语句分为说明性语句和可执行语句两大类。可执行语句又分为数据定义、数据控制、数据操纵、数据检索四大类。 可执行性SQL语句写在高级语言的可执行处;说明性SQL语句写在高级语言的说明性的地方。 例如:在PRO*C程序中建立一个名为BOOK的表结构,过程如下: #include〈stdio.h〉 EXEC SQL BEGIN DECLARE SECTION; VARCHAR uid[20], pwd[20]; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; Main() { /*login database*/ strcpy(uid.arr,’wu’); uid.len=strlen(uid,arr); strcpy(pwd.arr,’wu’); pwd.len=strlen(pwd.arr); EXEC SQL CONNECT:uid IDENTIFEED BY:pwd; EXEC SQL CREATE TABLE book ( acqnum number, copies number , price number); EXEC SQL COMMIT WORK RELEASE; EXIT; PRO*C可非常简便灵活地访问ORCLE数据库中的数据,同时又具有C语言高速的特点,因而可完成一些ORACLE产品不能完成的任务,例如以下一个固定的特殊格式输出结果。 SQL嵌套源程序示例 #unclude<stdio.h> typedef char asciz[20]; EXEC SQL BEGIN DECLARE SECTION; EXEC SQL TYPE asciz IS STRING (20) REFERENCE; asciz username; asciz password; asciz emp_name(5); int emp_number(5a); float salary[5]; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE sqlca; Void print_rows(); Void sqlerror(); Main() { int num_ret; strcpy(username,”SCOTT’); strcpy(password, “TYGER”); EXEC SQL WHENEVER SQLERROR DO sqlerror(); EXEC SQL CONNECT:username IDENTIFIED BY:password; Print (“\nConnected to ORACLE as user:%s\n”, username); EXEC SQL DECLARE c1 CURSOR FOR SELECT EMPNO , ENAME , SAL FROM EMP; EXEC SQL OPEN c1; Num_ret = 0; For(;;) { EXEC SQL WHENEVER NOT FOUND DO break; EXEC SQL FETCH c1 INTO : emp_number , :emp_name , :salary; Print_rows (sqlca.sqlerrd[2] – num_ret); Num_ret=sqlca.sqlerrd[2]; } if ((sqlca.sqlerrd[2] – num_ret)>0); print _rows(sqlca.sqlerrd[2] –num_ret); EXEC SQL CLOSE c1; Printf(“\Have a good day.\n”); EXEC SQL COMMIT WORK RELEASE; }
void print_rows(n); int n; { int i; printf(“\nNumber Employee Salary\n”); printf(“------------------------------\n”); for (i=0;i<n; i++ ) printf(“% - 9d%- 8s%9.2f\n”,emp-number[i], emp---name[i],salary[i]; } void sqlerror() { EXEC SQL WHENEVER SQLERROR CONTINUE; Printf(“\noracle error detected:\n”); Printf(‘\n%.70s\n”, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; Exit(1); }
(6) 错误检测和恢复 在使用SQL语句和PRO*C对数据库进行操作时,常常有字段空值,无条件删除,无行返回,数据溢出和截断等现象发生,这种现象可以用SQLCA和指示器变量来检测。
1 SQLCA的结构 在PRO*C程序中SQLCA结构如下: STRUCT SQLCA{ Char sqlcaid[8]; Long sqlabc; Long sqlcode; STRUCT{ Unsigned sqlerrm1; Char sqlerrmc[10]; }sqlerrm; Char sqlerrp[8]; Long sqlerrd[6]; Char sqlwarn[8]; Char sqlext[8]; } 其中: SQLCA.sqlerrm.sqlerrmc:带有SQLCA。SQLCODE的错误正文。 SQLCA.sqlerrd:当前ORACLE的状态,只有SQLCA.SQLERRD[2]有意义,表示DML语句处理的行数。 SQLCA.sqlwarn:提供可能遇到的条件信息。
在每执行一个SQL语句后,ORACLE就把返回结果放入SQLCA中,但说明语句除外。 用SQLCA可以查看SQL语句的执行结果。往往有三种结果: =0:执行成功; SQLCA.SQLCODE= >0:执行成功的状态值; <0:失败,不允许继续执行。
2 指示器变量 指示器变量有时也称指示变量.指示变量与一个主变量相关联,指出主变量的返回情况. =0:返回值不为空, 未被截断,值放在主变量中; 返回值= >0:返回值为空, 忽略主变量的值; <0:主变量长度不够就被截断。 使用指示变量要注意: 在WHERE子句中不能用指示变量。用NULL属性来测试空值。 例如下列子句: SELECT… FROM… WHERE ENAME IS NULL; 是正确的,而 WHERE ENAME=:PEME:PEME1 是错误的。 指示变量在插入空值之前为—1 可输出空值。
3 WHENEVER语句 WHENEVER是说明语句,不返回SQLCODE, 只是根据SQLCA中的返回码指定相关的措施。格式为 EXEC SQL WHENEVER [SQLERROR|SQLWARNING|NOTFORUND] [STOP|CONTINUE|GOTO<标号>]; 其中 (1)[STOP|CONTINUE|GOT<标号>]的缺省值为CONTINUE。 (2)SQLERROR:SQLCA.SQLCODE<0; (3)SQLWARNIGN:SQLCA.SQLWARN[0]=“W”; (4)NOTFOUND:SQLCA.SQLCODE=1403; 下面给出一段程序来说明WHENEVER的用法: EXEC SQL BEGIN DEELARE SECTION; VARCHAR UID[20]; VARCHAR PASW[20]; …… EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; Main() { …… EXEC SQL WHENEVER SQLERROR GOTO ERR; EXEC SQL CONNECT:UID/:PWD; …… EXEC SQL DECLARE CSOR1 CURSOR FOR SELECT 〈字段〉 FORM〈表〉 EXEC SQL OPEN CSOR1; SQL …… EXEC SQL WHENEVER NOT FOUND GOTO good; For(;;) EXEC SQL FETCH CSOR, INTO…… Good: …… printf(“\n查询结束\n”); EXEC SQL CLOSE C1; EXEC SQL WHENEVER SQLERROR CONTINUE. EXEC SQL COMMIT WORK RELEASE: Exit(); Printf(“\n%70s|n”, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE: Exit(1); }
(7) 动态定义语句 SQL语句分动态定义语句和静态定义语句两种: 静态定义语句:SQL语句事先编入PRO*C中,在经过预编译器编译之后形成目标程序*。BOJ,然后执行目标程序预即可。 动态定义语句:有些语句不能事先嵌入到PRO*C程序中,要根据程序运行情况,用户自己从输入设备上(如终端上)实时输入即将执行的SQL语句。 动态定义语句有: EXECUTE IMMEDIATE; PREPARE 与EXECUTE; PREPARE与FETCH 和 OPEN ; BIND与DEFINE DESCRIPTOR。
EXECUTE IMMEDIATE语句 此语句表示立即执行, 并且只向SQLCA返回执行结果,无其它信息。例如: EXEC SQL BEGIN DECLARE SECTION; VARCHAR abcd[89]; VARCHAR deay[20]; EXEC SQL END DECLARE SECTION; /** 输出字符串到abcd **/ EXEC SQL EXECUTE IMMEDIATE :abcd; 注意: EXECUTE IMMEDIATE只能运行带一个参数的动态语句。其中,abcd是参数,不是关键字。 EXECUTE IMMEDIATE使用的先决条件是:SQL语句不能包含主变量;SQL语句不能是查询语句。 可用任何主变量作为EXECUTE IMMEDIATE的参数;也可用字符串作为主变量。
PREPARE与EXECUTE语句 此语句表示“预编译/执行”。此语句能够预编译一次而执行多次。语法为: EXEC SQL PREPARE 〈语句名〉FROM:主变量; EXEC SQL EXECUTE〈语句名〉[USING:替换主变量]; PREPARE语句做两件事: 预编译SQL语句; 给出SQL语句的语句名。 注意: SQL语句不能是查询语句; PREPARE和EXECUTE可包含主变量; PREPARE不能多次执行。 例如:<example.pc> #define USERNAME “SCOTT” #define PASSWORD “TIGER” #include <stdio.h> EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION; Char * username=USERNAME; Char * password=PASSWORD; VARCHAR sqlstmt[80]; Int emp_number; VARCHAR emp_name[15]; VARCHAR job[50]; EXEC SQL END DECLARE SECTION; Main() { EXEC SQL WHENEVER SQLERROR GOTO :sqlerror; EXEC SQL CONNECT :username IDENTIFIED BY :password; Sqlstmt.len=sprintf(sqlstmt.arr,”INSERT INTO EMP (EMPNO,ENAME,JOB,SAL) VALUES(:V1,:V2,:V3,:V4)”); Puts(sqlstmt.arr); EXEC SQL PREPARE S FROM :sqlstmt; For(;;) { printf(“\nenter employee number:”); scanf(“%d”,&emp_number); if (emp_number==0) break; printf(“\nenter employee name:”); scanf(“%s”,&emp_name.arr); emp_name.len=strlen(emp_name.arr); printf(“\nenter employee job:”); scanf(“%s”,job.arr); job.len=strlen(job.arr); printf(“\nenter employee salary:”); scanf(“%f”,&salary); } EXEC SQL EXECUTE S USING :emp_number,:emp_name,:job,:salary; }
FETCH语句和OPEN语句 FETCH语句和OPEN语句这组动态语句是对游标进行操作的,
上一页 [1] [2] [3] [4] [5] [6] [7] [8] 下一页 没有相关教程
|