Pro*C的使用

hb205

贡献于2011-09-01

字数:16503 关键词: Oracle 数据库服务器

Pro * C 的使用 一 Pro*C 程序概述 ORACLE支持几种高级语言中内嵌入SQL语句,或ORACLE库函数调用来访问数据库。它们是C,COBOL,Ada,PASCAL,PL/I等,这些语言称之为宿主语言,用它们开发的程序就称为PRO* 程序,如PRO*C,PRO*COBOL等。 PRO*C在ORACLE的客户端软件中有,安装oracle时选上即可。 1. 什么是Pro*C/C++ 通过在过程化编程语言C/C++中嵌入SQL语句而开发出的应用程序。 2. 简要说明: 在通用编程语言中使用的SQL称为嵌入式SQL.目的是Pro*C/C++将使 C/C++成为访问数据库的工具. 在ORACLE数据库管理和系统中, 有三种访问数据库的方法; (1) 用SQL*Plus, 它有SQL命令以交互的应用程序访问数据库; (2)用第四代语言应用开发工具开发的应用程序访问数据库,这些工具有SQL*Froms,QL*Reportwriter,SQL*Menu等; (3) 利用在第三代语言内嵌入的SQL语言或ORACLE库函数调用来访问。 Pro*C就属于第三种开发工具之一, 它把过程化语言C和非过程化语言SQL最完善地结合起来,具有完备的过程处理能力,又能完成任何数据库的处理品任务,使用户可以通过编程完成各种类型的报表。 在Pro*C程序中可以嵌入SQL语言,利用这些SQL语言可以完成动态地建立、修改和删除数据库中的表,也可以查询、插入、修改和删除数据库表中的行, 还可以实现事务的提交和回滚。 在Pro*C程序中还可以嵌入PL/SQL块, 以改进应用程序的性能, 特别是在网络环境下,可以减少网络传输和处理的总开销。 3. Pro*C的程序结构图 通俗来说,Pro*C程序实际是内嵌有SQL语句或PL/SQL块的C程序, 因此它的组成很类似C程序。 但因为它内嵌有SQL语句或PL/SQL块, 所以它 还含有与之不同的成份。为了让大家对Pro*C有个感性的认识, 特将二者差别比较如下: 4. Pro*C的程序处理过程 二.Pro*C程序的组成结构 每一个Pro*C程序都包括两部分:(1)应用程序首部;(2)应用程序体 应用程序首部定义了ORACLE数据库的有关变量,为在C语言中操纵ORACLE数据库做好了准备。应用程序体基本上由Pro*C的SQL语句调用组成。主要指查询SELECT、INSERT、UPDATE、DELETE等语句。 应用程序的组成结构如图所示: 描述部分 SQL通信区 应用程序体 应用程序首部 EXEC SQL BEGIN DECLARE SECTION (SQL变量的定义) EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLLA; EXEC SQL CONNECT :username IDENTIFIED BY :passwd USING :dbname SQL 语句及游标的使用 1. 应用程序首部 应用程序的首部就是Pro*C的开始部分。它包括以下三部分: l C变量描述部分; l SQL变量描述部分(DECLARE部分); l SQL通信区。 (1) DECLARE部分(描述部分) 描述部分说明程序的SQL变量, 定义部分 以EXEC SQL BEGIN DECLARE SECTION;开始 以EXEC SQL END DECLARE SECTION; 结束的。 在这两个语句之间只允许包含以下语句: 1) SQL变量的类型说明语句 2) EXEC SQL INCLUDE语句 3) EXEC SQL VAR语句 4) EXEC SQL TYPE语句 但不允许包含说明为结构类型的SQL变量,它可以出现在程序的主部,也可出现在局部 l SQL变量的说明和使用 在说明段能为SQL变量指定的数据类型如表所示: 数据类型 描述 CHAR CHAR(n) INT SHORT LONG FLOAT DOUBLE VARCHAR 单字符 n个字符数组 整数 短整数 单精度浮点数 双精度浮点数 变长字符串 这些数据类型实际上就是C语言的数据类型,其中VARCHAR中视为C数据类型的扩充。这在以后会谈到。 SQL变量的使用应注意以下几点: l 必须在描述部分明确定义 l 必须使用与其定义相同的大小写格式 l 在SQL语句中使用时,必须在其之前加一个“:”(冒号),但在C语句中引用时不需加冒号。 l 不能是SQL命令中的保留字。 l 可以带指示变量。 例如:EXEC SQL BEGIN DECLARE SECTIONS; VARCHAR programe[30]; Int porgsal, pempno; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT ENAME, SAL INTO: programe, : progsal FROM EMP WHERE EMPNO = : pempno; (2) 指示器变量的说明和引用 指示变量实际上也是一类SQL变量,它被用来管理与其相关联的宿主变量(即在SQL语句中充 当输入或输出的变量)。每一个宿主变量都可定义一个指示器变量,主要用于处理空值(NULL) 指示器变量的说明基本同一般SQL变量一样, 但必须定义成2字节的整型,如SHORT、INT。在SQL语句中引用时, 其前也应加“:”(冒号),而且必须附在其相关联的宿主变量之后,在C语句中,可独立使用。当指示器变量为-1时,表示空值。 例如: EXEC SQL BEGIN DECLARE SECTION ; INT dept-number; SHORT ind-num; CHAR emp-name; EXEC SQL END DECLARE SECTION ; Scanf(“90d %s”, &dept-number , dept-name ); If (dept-number ==0) Ind-num = -1; Else Ind-num = 0; EXEC SQL INSERT INTO DEPT (DEPTNO, DNAME) VALUES(:dept-number:ind-num, :dept-name); 其中ind-num是dept-number 的指示器变量。当输入的dept-number值是0时,则向DEPT表的DEPTNO列插入空值。 (3) 指针SQL变量的说明和使用 指针SQL变量在引用前也必须在DECLARE 部分先说明。其说明格式同C语言。在SQL语句中引用时,指针名字前要加前缀“:”(冒号)而不加“*”(星号)。在C语句中用法如同C语言的指针变量。 PRO*C在说明段不能说明结构类型的变量,但它能用指针变量引用结构成员。 (4) 数组SQL变更的说明和引用 在SQL语句中引用数组时,只需写数组名(名字前加冒号),不需写下标,在C语句中用法如同C语言的数组变量。 使用数组可大大降低网络传输开销。如要向一表插入100行数据,如果没有数组,就要重复100次, 而引用后,只须执行一次insert语句、便可一次性插入。 例如: EXEC SQL BEGIN DECLARE SECTION; Int emp_number[100]; Char emp_name[100][15]; Float salary[100],commission[100]; Int dept_number; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT EMPNO,ENAME,SAL,COMM INTO :emp_number,:emp_name,:salary,:commission FROM EMP WHERE DEPTNO=:dept_number; 在使用数组时,应注意以下几点; l 不支持指针数组 l 只支持一维数组,而 emp-name [100][15]视为一维字符串 l 数组最大维数为32767 l 在一条SQL语句中引用多个数组时,这些数组维数应相同 l 在VALUES , SET, INTO 或WHERE子名中, 不允许把简单SQL变量与数组SQL变量混用 l 不能在DELARE部分初始化数组 l 当在SQL语句中引用多个数组时,这些数组的维数应当相同,否则PRO*C使用最小的数组维数,并发出警告 例如:下面的引用是非法的 EXEC SQL BEGIN DECLARE SECTION; Int dept-num [3] = {10,20,30}; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT EMPNO, ENAME , SAL INTO :emp-num[i], :emp-name[i], :salarg[i] FROM EMP; (5) 伪类型VARCHAR的说明和引用 VARCHAR变量在引用之前也必须在说明段说明, 说明时必须指出串的最大长度,如: EXEC SQL BEGIN DECLARE SECTION; Int book-number; VARCHAR book-name [ 50 ]; EXEC SQL END DECLARE SECTION; 在预编绎时,book-name 被翻译成C语言中的一个结构变量; Struct { unsigned short len ; unsigned chart arr [ 20 ] ; } boo-name 由此看出, VARCHAR变量实际上是含长度成员和数组成员的结构变量。在SQL语句中引用时,应引用以冒号为前缀的结构名,而不加下标,在C语句 中引用结构成员。 VARCHAR变量在作输出变量时,由ORACLE自动设置, 在作为输入变量时,程序应先把字符串存入数组成员中, 其长度存入长度成员中,然后再在SQL语句中引用。例如: scanf(“90s, 90d’, book-name.arr, & book-number ); book-name.len = strlen (book-name.arr); EXEC SQL UPDATE BOOK SET BNAME = :book-name ; BDESC = :book-number; (6) SQL通信区 SQL通信区是用下列语句描述的: EXEC SQL INCLUDE SQLCA; 此部分提供了用户运行程序的成败记录和错误处理。 SQLCA的组成 SQLCA是一个结构类型的变量,它是ORACLE 和应用程序的一个接口。在执行 Pro*C程序时, ORACLE 把每一个嵌入SQL语句执行的状态信息存入SQLCA中, 根据这些信息,可判断SQL语句的执行是否成功,处理的行数,错误信息等,其组成如表所示: Struct sqlca { char sqlcaid [ 8 ] ; ----à标识通讯区 long sqlabc; ---à 通讯区的长度 long sqlcode; ---à保留最近执行的SQL语句的状态码 struct { unsigned short sqlerrml; -----à信息文本长度 }sqlerrm; char sqlerrp [ 8 ]; long sqlerrd [ 6 ]; char sqlwarn [ 8 ]; char sqlext [ 8 ]; } struct sqlca sqlca; 其中, sqlcode在程序中最常用到,它保留了最近执行的SQL语句的状态码。程序员根据这些状态码做出相应的处理。这些状态码值如下: 0: 表示该SQL语句被正确执行,没有发生错误和例外。 >0: ORACLE执行了该语句,但遇到一个例外(如没找到任何数据)。 <0: 表示由于数据库、系统、网络或应用程序的错误,ORACLE未执行该SQL语句。当出现此类错误时,当前事务一般应回滚。 2. 应用程序体 在Pro*C程序中, 能把SQL语句和C语句自由地混合书写,并能在SQL语句中使用SQL变量,嵌入式SQL语句的书写文法是: l 以关键字EXEC SQL开始 l 以C语言的语句终结符(分号)终结 SQL语句的作用主要用于同数据库打交道。C语言程序用于控制,输入,输出和数据处理等。 (1) 连接到ORACLE数据库 在对数据库存取之前,必须先把程序与ORACLE数据库连接起来。即登录到ORACLE上。所连接命令应该是应用程序的第一个可执行命令。 每个节点都有一个默认数据库。如果在CONNECT语句中,指定节点而不指定数据库,则默认连接到节点的默认数据库上; CONNECT没有AT子句,就是使用默认连接;同样的,若使用了AT子句,则在后面的SQL操作中也要指定该连接,否则操作的是缺省连接上的数据,而不是AT指定的连接。不能在游标控制语句PREPARE、DESCRIBE、OPEN、FETCH、CLOSE 中使用AT子句,如果需要游标与AT指定连接,就需要在DECLARE CURSOR语句中使用AT子句。对于同时连接多个数据库时就需要AT子句。 连接命令格式如下: EXEC SQL CONNECT :username IDENTIFIED BY :passwd 或EXEC SQL CONNECT :user_pwd (:user_pwd的格式为username/password或username/password@dbname) 或EXEC SQL CONNECT :username IDENTIFIED BY :passwd using dbname 或EXEC SQL CONNECT :username IDENTIFIED BY :passwd at db_link_name using dbname 其中,宿主变量username和passwd标识一个用户。dbname包含要登录到其上的远程节点的数据库名。db_link_name命名一个非缺省连接,它是oracle使用的标识符,而不是宿主或程序变量,因此不需在说明段说明。Using子句指出与db_link_name相联系的网络、机器和数据库,其后就可使用含有AT子句的SQL语句在dbname指定的数据库上进行操作。 在使用上述格式进行登入时,应当首先在说明段定义包含用户名和口令的SQL 变量,并在执行CONNECT之前设置它们,否则会造成登录失败。例如: EXEC SQL BEGIN DECLARE SECTION; VARCHAR usename [20]; VARCHAR password[20]; EXEC SQL END DECLARE SECTION; strcpy ( usename.arr, “CSOTT’); usename.len = strlen (username.arr); strcpy (password.arr , “TIGER’); password .len = strlen( password.arr); EXEC SQL WHENEVER SQLERROR GOTO SQLERR; EXEC SQL CONNECT :username INDNTIFIED BY : password; 注意: 不能把用户名和口令直接编写到CONNECT语句中,或者把用引号(’)括起来的字母串在CONNECT 语句中,如下面的语句是无效的。 EXEC SQL CONNECT SCOTT INENTIFIED BY TIGER; EXEC SQL CONNECT ‘SCOTT’ IDENTIFIED BY ‘TIGER’; (2) 数据库查询及游标的使用 在PRO*C中, 查询可分为两种类型: l 返回单行或定行数的查询; l 返回多行的查询.此种查询要求使用游标来控制每一行或每一组(主变量用数组)。 1) 返回单行或定行数的查询 在PRO*C中的查询SQL SELECT语句由以下几个子句组成: SELECT INTO FROM WHERE CONNECT BY UNION INTERSECT MINUS GROUP BY HAVING ORDER BY 其中WHERE子句中的查询条件可以是一个属性或多个属性的集合,在执行是赋值的主变量也可放在WHERE子句中。WHERE子句中所用的主变量称为输入主变量。如: SELECT EMPNO, JOB, SAL INTO:PNAME, :PJOB, :PSAL FROM EMP WHERE EMPNO=:PEMPNO; 若没有找到限定的行, 则SQLCA.SQLCODE返回”+1403”, 表明”没有找到”。 INTO从句中的主变量叫输出主变量,它提供了查询时所需要的信息。 在任何项送给主变量之前,都要求ORACLE把这些项转换成主变量的数据类型。对于数字是通过截断来完成的(如:9.23转换为9)。 如果已确定查询只返回一行,那么就不必使用游标,只给SELECT语句增加一个INTO子句即可。在语义上INTO语句在FROM之前的查询中有多少个选择项就有多少个输出主变量。若在SELECT项中表达式的数目不等于INTO子句中主变量的数目,就把SQLCA.SQLWARN[3]置为”W”。 2) 多行查询及游标的使用 如果查询返回多行或不知道返回多少行,使用带有ORACLE游标(CURSOR)的SELECT语句。Oracle9i之后PRO*C支持上下滚动游标,可以使用可滚动游标代替以往顺序游标。 游标是ORACLE和PRO*C存放查询结果的工作区域。一个游标(已命名的)与一条SELECT语句相关联。 操作游标有由4条命令: Ø DECLARE CURSOR Ø OPEN CURSOR Ø FETCH Ø CLOSE CURSOR A. 定义游标 一个游标必须首先定义, 才能使用它。语法为: 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的一个活动区域。 注意: 1) 定义游标必须在对游标操作之前完成; 2) PRO*C不能引用没有定义的游标; 3) 游标定义后,其作用范围是整个程序。所以对一个程序来讲, 同时定义两个相同的游标是错误的。 B. 打开游标 打开游标的OPEN语句主要用来输入主变量的内容,这些主要是WHERE中使用的主变量。打开游标的语句是:EXEC SQL OPEN 〈游标名〉 当打开游标后,可以从相关的查询中取出多于一行的结果。所有满足查询标准的行组成一个集合,叫做“游标活动集”。通过取操作,活动集中的每一行或每一组是一个一个返回的,查询完成后,游标就可关闭了。如图所示: 定义游标:DECLARE 开始查询:SELECT 打开游标:OPEN 从活动集取数据:FETCH 查询完成 关闭游标:CLOSE 注意:1)游标处于活动集的第一行前面; 2)若改变了输入主变量就必须重新打开游标。 C. 取数据 从活动集中取出一行或一组把结果送到输出主变量中的过程叫取数据。输出主变量的定义在取数据语句中。取数据的语句如下: EXEC SQL FETCH〈游标名〉INTO:主变量1,主变量2,…… FETCH的工作过程如图所示: 满足查询条件的查询结果 满足查询条件的查询结果 输出至当前 在游标打开后 …… 使用FETCH应注意以下几点: l 游标必须先定义再打开。 l 只有在游标打开之后才能取数据,即执行FETCH语句。 l FETCH语句每执行一次,从当前行或当前组取数据一次,下一行或下一组向上移一次。游标每次所指的行或组都为当前行或当前组,而FETCH每次都是取游标所指定的行或组的数据。 l 当游标活动集空之后,ORCLE返回一个SQLCA。SQLCA(=1403)。 l 若希望此游标再操作, 必须先关闭再打开它。 l 在C程序中可以开辟一个内存空间,来存放操作结果,这样就能利用开辟的空间来灵活操纵查询的结果。 D. 关闭游标 取完活动集中所有行后,必须关闭游标,以释放与该游标有关的资源。 关闭游标的格式为: EXEC SQL CLOSE 游标名; 例如: EXEC SQL CLOSE C1; ORACLE V5.0版支持SQL格式“CURRENT OF CURSOR”。这条语句将指向一个游标中最新取出的行,以用于修改和删除操作。该语句必须有取操作之后使用,它等同存储一个ROWID,并使用它。 例如: 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; (3) SQL嵌套的方法及应用 嵌入SQL与交互式SQL在形式上有如下差别: 1) 在SQL语句前增加前缀“EXEC SQL”, 这一小小的差别其目的是在于预编译时容易识别出来, 以便把每一条SQL作为一条高级语言来处理。 2) 每一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 0; } PRO*C可非常简便灵活地访问ORCLE数据库中的数据,同时又具有C语言高速的特点,因而可完成一些ORACLE产品不能完成的任务,例如以下一个固定的特殊格式输出结果。 SQL嵌套源程序示例 #unclude 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;i0:执行成功的状态值; <0:失败,不允许继续执行。 2) 指示器变量 指示器变量有时也称指示变量.指示变量与一个主变量相关联,指出主变量的返回情况. =0:返回值不为空, 未被截断,值放在主变量中; 返回值= >0:返回值为空, 忽略主变量的值; <0:主变量长度不够就被截断。 使用指示变量要注意: l 在WHERE子句中不能用指示变量。用NULL属性来测试空值。 例如下列子句: SELECT… FROM… WHERE ENAME IS NULL; 是正确的,而 WHERE ENAME=:PEME:PEME1 是错误的。 l 指示变量在插入空值之前为—1 l 可输出空值。 3) WHENEVER语句 WHENEVER是说明语句,不返回SQLCODE, 只是根据SQLCA中的返回码指定相关的措施。格式为 EXEC SQL WHENEVER [SQLERROR|SQLWARNING|NOTFORUND] [STOP|CONTINUE|GOTO<标号>]; 其中 Ø [STOP|CONTINUE|GOT<标号>]的缺省值为CONTINUE。 Ø SQLERROR:SQLCA.SQLCODE<0; Ø SQLWARNIGN:SQLCA.SQLWARN[0]=“W”; Ø 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; …… EXEC SQL WHENEVER NOT FOUND GOTO good; For(;;) EXEC SQL FETCH CSOR INTO…… Good: …… printf(“\n查询结束\n”); EXEC SQL CLOSE CSOR1; 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); } (5) 动态定义语句 SQL语句分动态定义语句和静态定义语句两种: 1) 静态定义语句:SQL语句事先编入PRO*C中,在经过预编译器编译之后形成目标程序*。BOJ,然后执行目标程序预即可。 2) 动态定义语句:有些语句不能事先嵌入到PRO*C程序中,要根据程序运行情况,用户自己从输入设备上(如终端上)实时输入即将执行的SQL语句。 动态定义语句有: l EXECUTE IMMEDIATE; l PREPARE 与EXECUTE; l PREPARE与FETCH 和OPEN; l BIND与DEFINE DESCRIPTOR A. 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; 注意: 1) EXECUTE IMMEDIATE只能运行带一个参数的动态语句。其中,abcd是参数,不是关键字。 2) EXECUTE IMMEDIATE使用的先决条件是:SQL语句不能包含主变量;SQL语句不能是查询语句。 3) 可用任何主变量作为EXECUTE IMMEDIATE的参数;也可用字符串作为主变量。 B. PREPARE与EXECUTE语句 此语句表示“预编译/执行”。此语句能够预编译一次而执行多次。语法为: EXEC SQL PREPARE 〈语句名〉FROM:主变量; EXEC SQL EXECUTE〈语句名〉[USING:替换主变量]; PREPARE语句做两件事: Ø 预编译SQL语句; Ø 给出SQL语句的语句名。 注意: l SQL语句不能是查询语句; l PREPARE和EXECUTE可包含主变量; l PREPARE不能多次执行。 例如: #define USERNAME “SCOTT” #define PASSWORD “TIGER” #include 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; } C. FETCH语句和OPEN语句 FETCH语句和OPEN语句这组动态语句是对游标进行操作的,其执行过程如下: PREPARE〈语句名〉FROM 〈主变量字符串〉; DECLARE〈游标名〉FOR〈语句名〉; OPEN 〈游标名〉[USING:替换变量1[,:替换变量变…]] FETCH〈游标名〉INTO: 主变量1[,:主变量2…] CLOSE〈游标名〉 注意: l SQL语句允许使用查询语句; l SELECT子句中的列名不能动态改变,只能预置; l WHERE和ORDER BY 子句可以动态改变条件。 三.Pro*C的编译 1. 环境配置 设置环境变量 ORACLE_HOME=/home/oracle #设定oracle的主目录路径 ORACLE_SID=odsb  #设定oracle实例名 NLS_LANG=AMERICAN_AMERICA.ZHS16GBK  #客户端字符集设置 PATH=${ORACLE_HOME}/bin:${PATH}:. LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${LD_LIBARY_PATH}:. #链接库文件路径 export ORACLE_HOME ORACLE_SID NLS_LANG PATH LD_LIBRARY_PATH 2. PRO*C编译 以下例举部分编译选项 auto_connect 允许自动连接到 ops$ 帐号 char_map 正在映射字符数组和字符串 Close_on_commit 关闭所有 COMMIT 游标 codekr_c 将要生成的代码类型 Comp_charset C 编译器支持的字符集类型 Config 用另一配置文件覆盖系统配置文件 Cpp_suffix 覆盖缺省的 C++ 文件名后缀 dbmsnative 兼容模式 Def_sqlcode 生成 '#define SQLCODE sqlca.sqlcode' 宏 Define 定义预处理器符号 Durationtransaction 设置高速缓存中对象的 pin 持续时间 Dynamic 指定 Oracle 或 ANSI 动态 SQL 语义 Errors 是否将错误消息发送到终端 Errtype 输入文件的列表文件名称错误 Fips ANSI 的 FIPS 标志不符合用法 Header 为预编译标题指定文件扩展名 hold_cursor 在游标高速缓存中控制游标保留 iname 输入文件的名称 Include 包括文件的目录路径 Intype 有关类型信息的输入文件名称 Lines 将 #line 指令添加到生成的代码中 Lname 覆盖缺省列表文件名 Ltype 列表文件中生成的数据量 maxliteral 生成的文字串的最大长度 maxopencursors 高速缓存的开放游标的最大数量 mode 代码符合 Oracle 或 ANSI 规则 Nls_char 指定国家语言字符变量 Nls_local 控制 NLS 字符语义的实现方法 Objects 支持对象类型 oname 输出文件名 oraca 控制 ORACA 的使用 Pagelen 列表文件页面长度 parse 控制进行语法分析的非 SQL 代码 prefetch 游标 OPEN 期间预读取的行数 Release_cursor 控制从游标高速缓存中释放游标 Select_error 控制选择标记错误 sqlcheck 编译时间 SQL 校验总量 Sys_include 系统标题文件所在目录 Threads 指示多线程应用程序 type_code 将 Oracle 或 ANSI 类型代码用于动态 SQL Unsafe_null 允许在没有指示变量的情况下进行> NULL 读取 Userid 用户名/口令 [@dbname] 连接串 Varchar 允许使用隐式 varchar 结构 Version 将要返回的对象版本 编译操作如下: 1. 先用ORACLE预编译器PROC对PRO*C程序进行预处理,该编译器将源程序中嵌入的SQL语言翻译成C语言,产生一个C语言编译器能直接编译的文件。生成文件的扩展名为 .c; 2. 编译器CC 对扩展名为.c的文件编译,产生目标码文件,其扩展名为.o; 3. 编译器CC连接目标码文件,生成可运行文件。 对于简单的编译命令 proc iname=test.pc oname= test.c cc -I${OORACLE_HOME}/precomp/public test.c -o test -L${ORACLE_HOME}/lib –lclntsh 但对于复杂的工程这种编译将效率低下,建议写makefile,但是值得注意的是不同机型的编译器不相同,makefile是不同的。 例举集团客户支撑项目HP-UX下makefile: include $(ORACLE_HOME)/precomp/lib/env_precomp.mk COMPILER=/opt/ CC = $(COMPILER)/bin/aCC +DD64 +u1 -w I_SYM=-I ORALIBPATH=$(ORACLE_HOME)/lib ORALIBS=-lclntsh PRECOMPHOME=$(ORACLE_HOME)/precomp/public PROCPPFLAGS= code=cpp NETWORKHOME=$(ORACLE_HOME)/network/ PLSQLHOME=$(ORACLE_HOME)/plsql/ STLINCLUDE = -I $(COMPILER)/include_std INCLUDE=$(I_SYM). $(I_SYM)$(PLSQLHOME)public $(I_SYM)$(NETWORKHOME)public $(I_SYM)/usr/include ORAINCLUDE=$(I_SYM). $(I_SYM)$(PLSQLHOME)public $(I_SYM)$(NETWORKHOME)public $(I_SYM)$(ORACLE_HOME)/precomp/public CFLAGS= -c -lct -lcs -ltcl -lcomn -lintl -lm LIBHOME=$(ORACLE_HOME)/lib/ COMMONOBJ = ../Common/CConfig.o ../Common/CInit.o ../Common/CIniFile.o ../Common/CLogMng.o ../Common/CTask.o .SUFFIXES: .pc .cpp .C .cc .cxx .o .pc.cpp: $(ORACLE_HOME)/bin/$(PROC) intyp=message_o.typ $(PROCPPFLAGS) cpp_suffix=cpp release_cursor=yes char_map=string ireclen=256 iname=$*.pc parse=none lname=err .cc.o: $(CC) $(DEBUG) $(INCLUDE) $(CXXFLAGS) -c $< .cpp.o: $(CC) $(DEBUG) $(CXXFLAGS) $(INCLUDE) -c $< .c.o: $(CC) $(DEBUG) $(INCLUDE) $(CXXFLAGS) -c $< PROGNAME=CJs PCCSRCS=CJs.pc CJsDev.pc CJsMain.pc CJsRank.pc CJsTgt.pc CJsWarn.pc ../Common/CSqlLdr.pc PCCGENSRCS=${PCCSRCS:.pc=.cpp} CSRCS= CSOBJS=${CSRCS:.cpp=.o} ${PCCGENSRCS:.cc=.o} OBJS=$(CSOBJS) all:$(PROGNAME) clean: - rm -f ./*.cc ./*.o ./*.a - rm $(PROGNAME) objects: $(PCCGENSRCS) $(OBJS) ${BASEOBJS} $(PROGNAME):$(OBJS) $(CC) $(INCLUDE) $(LDFLAGS) -g $(OBJS) $(COMMONOBJ) \ -L $(ORALIBPATH) $(ORALIBS) -o $@ @echo "" @echo "###########################################################" @echo "" @echo " object [ $@ ] Loaded " @echo "" @echo "###########################################################" 四.实际项目应用 1. 集团客户支撑项目系统结构图: 2. 集团客户支撑项目后台程序执行流程 列举CAtomCust中客户资料处理代码流程图如下: 附

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 20 金币 [ 分享文档获得金币 ]
0 人已下载

下载文档

相关文档