proc编程.docx
《proc编程.docx》由会员分享,可在线阅读,更多相关《proc编程.docx(48页珍藏版)》请在冰豆网上搜索。
proc编程
C语言的预编译接口(PRO*C)
中科院数学所计算机科学室徐泽同整理
访问ORACLE有多种方法,归纳有:
1.利用SQL*PLUS或PL/SQL,用户向系统输入SQL语句,系统执行该语句,其后将结果向用户返回,
交互式地访问DB。
2.利用SQL*Forms、SQL*ReportWriter和SQL*Menu等4GL语言访问DB。
3.利用SQL与3GL的结合(比如与C结合)访问DB。
SQL是非过程化的语言,它没有提供定义变量的说明,
没有描写复杂控制结构的能力,而仅长于数据的管理。
SQL语言嵌入到算法语言,
得DB语言与算法语言共同的长处,将有利于应用。
在ORACLE中,C对DB操作有两种形式。
一种是把SQL语句嵌入到C程序中,
PRO*C是C这样对ORACLEDB进行操作的接口。
另一种是在C程序中如调用一般子程序一样,直接调用ORACLE的功能,这种结口称为ORACLE调用接口或叫OCI。
我们将分别讲述PRO*C和OCI。
一.PRO*C的程序结构
1.1PRO*C的处理过程
一个PRO*C程序先要经过ORACLE的预编译PCC处理,它将嵌入的SQL语句或PL/SQL块译为相应的DB调用的
C语言的代码,产生纯的C程序,再用C编译编为目标代码,最后用连接成可执行的代码,整个编译过程如后:
PRO*CPCC纯的CC目标连接可执行
源程序-->预编译-->程序-->编译-->文件-->编辑-->文件
1.2PRO*C中的SQL
PRO*C允许C中嵌入SQL的数据定义、数据操纵、会话控制、系统控制、事务控制等语句。
为了PRO*C能方便地识别源程序中的SQL语句,要求为SQL语句加前缀"EXECSQL",PCC则能方便的认识SQL
语句,并将它编译为C语言对DB的调用语句。
嵌入的SQL分为说命性语句和执行性语句。
说命性语句用来说明ORACLE对象、通信区和变量等,其位于
C的说明语句的地方。
执行性语句导致调用运行库SQLLIB,其实现对ORACLE的连接,可定义、查询、
操纵ORACLE数据,也控制对ORACLE数据的存取和对事务的处理等,其位于C的执行语句的地方。
说明语句有:
ARRAYLEN(*),在PL/SQL情况下使用宿主数组;BEGINDECLARESECTION(*),说明宿主变量段的开始语句;
ENDDECLARESECTION(*),说明宿主变量段的结束语句;DECLARE(*),说明ORACLE对象;INCLUDE(*),
拷贝文件;TYPE(*)、VAR(*),等价数据类型;WHENEVER,处理运行错误。
执行性语句有:
ALTER、ANALYZE、AUDIT、COMMENT、CONNECT(*)、CREATE、DROP、GRANT、NOAUDIT、RENAME、REVOKE、
TRUNCATE等定义和控制对ORACLE数据的存取;CLOSE(*)、DELETE、EXPLAINPLAN、FETCH(*)、INSERT、
OPEN(*)、SELECT、UPDATE检索和操纵ORACLE数据;COMMIT、ROLLBACK、SAVEPOINT、SETTRANSACTION处理事务
;DESCRIBE(*)、EXECUTE(*)、PREPARE(*)使用动态SQL;ALTERSESSION、SETROLE控制会话;系统控制语句
ALTERSYSTEM。
加注(*)的语句表无对应的交互语句。
1.3PRO*C程序的组成
PRO*C程序由C程序嵌入SQL语句或PL/SQL块组成,因此它有C和SQL共同的特点。
PRO*C程序由程序首部及
程序体组成。
程序由程序首部开头,它为PRO*C程序处理ORACLEDB作准备,包括DECLARE节、SQL通信区、
与ORACLE系统的连接三个部分。
程序首部后有程
序体,它包含程序用SQL语句对ORACLE的操作。
1.4DECLARE节
PRO*C程序由SQL语句嵌入到C程序组成,称C为宿主语言,SQL语句有时要用宿主语言的变量,称在SQL语句中使用的C语言变量为主变量,主变量必需在DECLARE节中加以说明,DECLARE节定义SQL语句使用的全部变量,其由EXECSQLBEGINDECLARESECTION;和EXECSQLENDDECLARESECTION;两个语句括着。
其间允许宿变量和指示变量的说明语句、EXECSQLINCLUDE、EXECSQLVAR、EXECSQLTYPE和C的注释等。
1.5通信区及错误处理
在PRO*C程序中,常需知SQL执行的成败,以便用户作处理。
为了将SQL语句的执行情返回给程序,需在PRO*C中定义与ORACLE的通信区,ORACLE将SQL执行的信息送入通信区,PRO*C则可从中取的有关信息,进行必要的错误处理。
PRO*C用EXECSQLINCLUDESQLCA;
EXECSQLINCLUDEORACA;定义通信区,SQLCA和ORACA起着PRO*C和ORACLE之间通信的作用。
1.6与ORACLE系统的连接
在使用ORACLE之前,PRO*C必需与ORACLE系统连接。
连接时用户提供用户名和口令,系统进行检查,如正确,则连接成功,这时PRO*C则可对ORACLE数据库访问;否则连接失败,PRO*C不能工作。
连接用SQL的CONNECT语句来完成,其格式为:
EXECSQLCONNECT:
IDENTIFIED:
;
或者为:
EXECSQLCONNECT:
;
在前一格式,用户名和口令分别放在不同的变量;在后一格式,用户名和口令放在同一变量,这些变量必须在DECLARE节说明。
CONNECT要执行成功,必须将正确的用户名和口令值先放在变量里,如变量说明为定长字符串,则用户名和口令值串右边用空格补齐。
SQL语句分为说明语句和可执行语句,在预编译后说明语句不产生代码;可执行语句在目标文件生成相应的调用码,可执行语句执行后在SQL通信区SQLCA返回有关执行的信息。
CONNECT是可执行语句,它在PRO*C中必须是第一个语句。
1.7程序体
在首部后面是程序体,体中是程序用SQL语句对ORACLE数据库的操作。
下面给出生成表PEMP,定义索引INDEX_PEMP的例子:
#include
#include
EXECSQLBEGINDECLARESECTION;
VARCHARuid[20];
VARCHARpwd[20];
EXECSQLENDDECLARESECTION;
EXECSQLINCLUDESQLCA;
main(){
strcpy(uid.arr,"scott");
uid.len=strlen(uid.arr);
strcpy(pwd.arr,"tigger");
pwd.len=strlen(pwd.arr);
EXECSQLCONNECT:
uidIDENTIFIED:
pwd;
printf("SuccessfullyconnectedtoORACLE\n");
EXECSQLCREATETABLEPEMP
(EMPNOCHAR(4),ENAMECHAR(5),HIRE_DATEDATE,
SALARYNUMBER(6,2),BONUSNUMBER(6,2),
TELCHAR(6),DEPTNOCHAR(4));/*生成表*/
printf("TablePEMPiscreated\n");
EXECSQLCREATEINDEXINDEX_PEMP
ONPEMP(SALARY,EMPNO);/*生成索引*/
printf("IndexINDEX_PEMPiscreated\n");
EXECSQLCOMMITWORKRELEASE;
exit(0);
}
二.ORACLE数据类型及转换
2.1内部数据类型
ORACLE操作的每个直接量和列值都有一种数据类型,过程或存储函数的变量也有自己的类型。
数据类型确定了列、变量的取值范围。
ORACLE有下述内部数据类型。
VARCHAR2变长字符串,<=2000字符;
NUMBER定点或浮点数;
LONG定长字符串,<=2**31-1字节;
ROWID二进值,6字节;
DATE定长日期/时间,7字节;
RAW定长二进制数据,<=255字节;
LONGRAW定长二进制数据,<=2**31-1字节;
CHAR定长字符串,<=255字符;
MLSLABEL变长二进制数据,2到5字节。
伪列和函数
伪列在表中不存在,查询时可引用,但不能对它插入、修改或删除。
SQL有下列伪列CURRVAL、NEXTVAL、LEVEL、ROWID、ROWNUM和函数USER、UID、SYSDATE。
可在SELECT、INSERT、UPDATE、DELETE中引用。
2.2外部数据类型
外部数据类型包括全部内部数据类型和宿主语言中提供的几个数据类型,其是:
VARCHAR2,变长字符串;NUMBER,二进制数;
INTEGER,有符号整数;FLOAT,浮点数;
STRING,以Null结尾的字符串;VARNUM,变长二进制数;
DECIMAL,COBOL或PL/I的10进数;LONG,定长字符串;
VARCHAR,变长字符串;ROWID,二进制值;
DATE,定长日期/时间值;VARRAW,变长二进制数据;
RAW,定长二进制数据;LONGRAW,变长二进制数据;
UNSIGNED,无符号整数;DISPLAY,COBOL数值字符串;
LONGVARCHAR,变长字符串;LONGVARRAW,变长二进制数据;
CHAR,定长字符串;MLSLABEL,变长二进制数据;
CHARZ,C中定长,以Null结尾的字符串。
三.SQL变量的说明和引用
PRO*C中的SQL语句所引用的变量叫SQL变量,它包扩宿主变量和指示器变量,宿主变量又分为简单宿主变量、数组宿主变量和指针宿主变量等。
宿主变量是PRO*C和ORACLE之间通信的关键。
宿主变量分为输入和输出两类,在SELECT和FETCH的INTO子句中的宿主变量是输出类,其它SQL中的是输入类。
3.1宿主变量的说明和引用
宿主变量引用前必作说明,即在说明段据C的规则,说明宿主变量,使之又要符合ORACLE的要求。
在说明段能为宿主变量指明的数据类型为char,单字符;char[n],n个字符数组;int,整数;short,短整数;long,长整数;float,单精度浮点数;double,双精度浮点数;VARCHAR[n],变长字符串。
C的数据类型和ORACLE的内部类型之间有下对应:
ORACLE内部类型C的类型说明
CHAR(X)1char单字符
char[n]n字节的字符数组
VARCHAR2(Y)1VARCHAR[n]n字节的变长字符数组
int整数
short短整数
long长整数
float单精度浮点数
double双精度浮点数
NUMBERint整数
short短整数
NUMBER(P,S)2long长整数
float单精度浮点数
double双精度浮点数
char单字符3
char[n]n字节的字符数组4
VARCHAR[n]n字节的变长字符数组
DATE5char[n]n字节的字符数组
LONG6VARCHAR[n]n字节的变长字符数组
RAW(X)1unsignedchar[n]n字节无符号的字符数组
LONGRAW6VARCHAR[n]n字节的变长字符数组
ROWID7
MLSLABEL8
说明:
1)X取值1-255,Y取值1-2000,缺省为1;
2)2)P为精度,取值2-38,S为定标,取值-84-127;
3)转换是字符,不是二进制;
4)4)如含'0'到'9','.','+','','E','e',串才能被转换为NUMBER,对NLS设置,小数点为',';
5)作为串类型转换时,DATA长度取决于NLS设置;作为二进制转换时,长度为7字节;
6)对VARCHAR,n<=65533;
7)作为串类型转换时,ROWID长度要求18-256字节;作为二进制转换时,长度依耐系统;
8)仅对TrustedORACLE有用。
下面说明了三个宿主变量:
EXECSQLBEGINDECLARESECTION;
intemp_number;
charhire_date[9];
floatsalary;
EXECSQLENDDECLARESECTION;
也可说明简单C类型的一维数组:
EXECSQLBEGINDECLARESECTION;
intemp_number[50];
floatsalary[50];
EXECSQLENDDECLARESECTION;
对于C的标准类型能使用重复定义:
EXECSQLBEGINDECLARESECTION;
intvar1,var2,var3;
EXECSQLENDDECLARESECTION;
可说明有初值的宿主变量,但不能说明初始化宿主数组:
EXECSQLBEGINDECLARESECTION;
charhire_date[10]="14-FEB-90";
floatsalary=2500;
EXECSQLENDDECLARESECTION;
可用auto、extern、static存储类型说明宿主变量,但不能用register存储类型说明宿主变量:
EXECSQLBEGINDECLARESECTION;
autointi,j,k;/*autoisthedefault*/
externintmax;
staticcharsw='N';
EXECSQLENDDECLARESECTION;
在说明段还可用类型限制符const和volatile,const宿主变量必是常数,volatile宿主变量可用程序不知的办法来改变值:
EXECSQLBEGINDECLARESECTION;
conststortloc=20;
volatileintport;
EXECSQLENDDECLARESECTION;
在说明段还可同时使用存储类型及类型限制符说明宿主变量:
staticconststortloc=20;
为了与ANSIC一致,允许带或不带最大长度的externchar[n]说明宿主变量:
EXECSQLBEGINDECLARESECTION;
externcharprotocol[15];
externcharmsg[];
EXECSQLENDDECLARESECTION;
对不带最大长度的msg[],编译时发出警告,设为255字节,如存储长度超过它,应带最大长度。
在SQL语句中引用宿主变量,应在其前加':
'号,在C程序中引用宿主变量不加。
EXECSQLBEGINDECLARESECTION;
intemp_number;
fioatsalary;
EXECSQLENDDECLARESECTION;
...
EXECSQLSELECTsalINTO:
salary
FROMempWHEREempno=:
emp_number;
四.数据类型等价
数据类型等价向用户提供了控制ORACLE解释输入数据和格式化输出数据的方法。
可把C语言的数据类型与
ORACLE的外部类型等价,也可用户定义的数据类型与ORACLE的外部类型等价。
4.1宿主变量等价
按照缺省规定,PRO*C预编译把指定的数据类型分配给每个宿主变量,分配如下关系:
宿主数据类型外部数据类型
char,char[n],char*VARCHAR2
char,char[n],char*CHAR
int,int*INTEGER
short,short*INTEGER
long,long*INTEGER
float,float*FLOAT
double,double*FLOAT
VARCHAR[n]VARCHAR
在说明段,可用VAR语句说明宿主变量等价,语法为:
EXECSQLVARhost_variableIStype_name[(length)]
host_variable:
宿主变量名,必在说明段先说明;
type_name:
有效的外部数据类型名;
length:
整直接量,指出有效字节数。
.宿主变量等价用于保证从DB列SELECT或FETCH出的串以Null结尾:
EXECSQLBEGINDECLARESECTION;
...
intemp_number;
charemp_name[11];
EXECSQLVARemp_nameISSTRING(11);
EXECSQLENDDECLARESECTION;
...
mian()
{
EXECSQLSELECTenameINTO:
emp_name
FROMempWHEREempno=:
emp_number;
printf("\n%s",emp_name);
...
}
EMP中ENAME长10字符,为加Null结尾,emp_name定义11字符,emp_nameISSTRING(11)则保证了串以Null结尾。
.宿主变量等价可让ORACLE的列存储不解释的数据,如在LONGRAWDB列存储整数:
EXECSQLBEGINDECLARESECTION;
...
intint_arry;
EXECSQLVARint_arryISLONGRAW(100);
EXECSQLENDDECLARESECTION;
.可用数据类型等价来代替缺省分配,如把DATE列SELECT到宿主变量时,ORACLE返回9字节的标准格式DD-MON-YY,如把宿主变量与DATE外部类型等价,ORACLE则返回7字节的格式
字节数1234567
含义世纪年月日小时分秒
五.字符数据的处理
PRO*C中处理字符的宿主变量有四种:
.char[n]字符数组
.char*字符指针
.VARCHAR[n]变长串
.VARCHAR*VARCHAR指针
就字符处理而言,MODE={ANSI14|ANSI13}等价MODE=ORACLE,因此MODE可选OEACLE或ANSI。
5.1字符数组
输入字符数组:
当MODE=ORACLE时,输入字符数组必用空格填充;当MODE=ANSI时,输入字符数组必用null结束。
当MODE=ORACLE时,把输入字符数组存入DB之前,ORACLE删去尾部空格,如:
strncpy(emp_name,"MILLER",10);/*尾部4个空格*/
EXECSQLINSERTINTOemp(empno,ename,deptno)
VALUES(1234,:
emp_name,20);
插入结果为"MILLER",其中不含空格。
如执行下列句子:
EXECSQLBEGINDECLARESECTION;
charemp_name[10];
...
EXECSQLENDDECLARESECTION;
strncpy(emp_name,"MILLER");
/*不正确,尾部应填4个空格*/
EXECSQLINSERTINTOemp(empno,ename,deptno)
VALUES(1234,:
emp_name,20);
这时插入的为"MILLER\0\0\0\0",而不是"MILLER"。
当MODE=ANSI时,字符数组输入数据必以Null结尾,如:
EXECSQLBEGINDECLARESECTION;
charemp_name[11];
...
EXECSQLENDDECLARESECTION;
strncpy(emp_name,"MILLER");
/*Null结尾,不需填空格*/
EXECSQLINSERTINTOemp(empno,ename,deptno)
VALUES(1234,:
emp_name,20);
输出字符数组:
当MODE=ORACLE时,ORACLE将该输出字符数组尾部填充空格;当MODE=ANSI时,输出字符数组先填充空格,再用null结束。
如:
CREATETABLEtest_char(c_colCHAR(10),v_colVARCHAR2(10));
...
INSERTINTOtest_charVALUES("MILLER","KING");
对test_char的SELECT为:
EXECSQLBEGINDECLARESECTION;
charname1[10];
charname2[10];
EXECSQLENDDECLARESECTION;
...
EXECSQLSELECTc_col,v_colINTO:
name1,:
name2
FROMtest_char;
当MODE=ORACLE时:
name1为"MILLER"/*尾部有4个空格*