oracle - pro*c
pro*c
2004-04-23 15:18 pm来自:Linux文档
现载:Www.8s8s.coM
地址:无名
from 《Oracle背份策略的补充》
[目录]
--------------------------------------------------------------------------------
连接
在Pro*C/C++中可以使用如下的语句连接到Oracle数据库服务器:
EXEC SQL CONNECT :username IDENTIFIED BY:password [USING :server];
或EXECSQL CONNECT : user_pwd [USING:server];
参数说明如下:
·username:数据库用户名。
·password:用户口令。
·server:连接到数据库。user_pwd:用户名及口令,二者必须用反斜杠(/)隔开
[目录]
--------------------------------------------------------------------------------
断开
同连接相比,断开相对简单,只需将所有事务回滚,并释放内存、断开连接即可。在Pro*C/C++中可使用如下语句实现该功能:
EXEC SQL ROLLBACK [WORK] [RELEASE];
其中ROLLBACK起到回滚并结束事务,清除所有保存点的作用。RELEASE子句用于释放内存、断开连接。
我们通过编写函数disconnect来实现与数据库的断开。该函数的编写过程中,我们采用了以上介绍的断开数据库连接技术。
该函数无返回值,无参数。函数声明如下:
void disconnect();
函数中实现断开数据库连接的代码为:
EXEC SQL ROLLBACK WORK RELEASE;
[目录]
--------------------------------------------------------------------------------
动态SQL
在实际工作中,有时我们需要在运行应用程序时接收和处理不同的SQL语句,比如在该程序的功能函数中需要不同的select语句。因为这些SQL语是在程序运行时动态输入的,所以成为动态SQL语句。
动态SQL与静态SQL语句比较:
·静态SQL语句被内嵌到了源程序中,而动态SQL语句则是在应用程序运行时所输入的SQL语句,它被存储到了字符串变量中。因此使用动态SQL比静态SQL更灵活。
·使用动态SQL需要编写更加复杂的代码,而使用静态SQL只需将SQL语句内嵌到应用程序中就可以了。
·如果能够能够确定应用程序所要使用的SQL语句和它的结构,那么使用静态SQL,因为这样不仅可以简化编程,而且应用程序的执行性能更好;而如果不能确定要执行何种SQL语句、宿主变量个数,宿主变量数据类型以及SQL语句所涉及到的数据对象,那么就要使用动态SQL。这样可使应用程序更加灵活,但程序编制更加复杂。
在Pro*C/C++应用程序中使用动态SQL共有四种方法:
·动态SQL方法一:适用于不包含宿主变量的SQL语句,并且不能是SELECT语句。
·动态SQL方法二:适用于宿主变量个数已经确定的SQL语句,并且不能是SELECT语句。
·动态SQL方法三:适用于查询列表已经确定的SQL语句。
·动态SQL方法四:适用于查询列表以及宿主变量个数均不能确定的SQL语句
[目录]
--------------------------------------------------------------------------------
方法三
1.动态SQL方法三
本方法与动态SQL方法二比较类似。不同的是,方法三将PREPARE命令与游标命令结合起来使用。因此,本方法可以接收和处理SELECT语句。但在预编译时,必须要知道查询列表项的列数以及占位符的个数。数据库对象名(例如:表名和列名)可以在运行时指定,但数据库对象名不能是宿主变量。另外,也可以在运行时指定条件、分组以及排序子句。
使用动态SQL方法三的步骤如下:
1)使用PREPARE命令准备SQL语句
该命令用于命名和分析SQL语句。在分析了SQL语句后,可以使用EXECUTE语句多次执行该语句。PREPARE命令的语法如下:
EXEC SQL PREPARE statement_name FROM{:host_string|string_literal};
参数说明如下:
·statement_name:语句名称,它是一个标识符而不是宿主变量。
·host_string:包含了SQL语句的宿主变量。
·string_literal:包含了SQL语句的字符串。
2) 使用DECLARE命令定义游标
该命令语法如下:
DECLARE cursor_name CURSOR FORstatement_name;
参数说明如下:
·cursor_name:游标名。
·statement_name:步骤1中的SQL语句标识符。
3) 使用OPEN命令打开游标
该命令的语法如下:
OPEN cursor_name [USING host_variable_list] ;
参数说明如下:
·cursor_name:步骤2中的游标名。
·host_variable_list:宿主变量列表,使用该列表中的项替换SQL语句中的占位符。
需要注意的是,如果SQL语句不是SELECT语句,那么在执行了OPEN命令后即完成了SQL语句的执行,而无需执行FETCH语句。
4) 使用FETCH语句推进游标、检索数据
该语句的语法如下:
FETCH cursor_name INTO host_variable_list;
参数说明如下:
cursor_name:游标名。
host_variable_list:宿主变量名列表,将检索到的数据保存到这些宿主变量中。
5) 使用CLOSE命令关闭游标
该命令语法如下:
CLOSE cursor_name;
[目录]
--------------------------------------------------------------------------------
方法四
2.动态SQL方法四
使用本方法可以接收和处理各SQL语句,并且在预编译前不需要知道查询列表项和输入宿主变量的占位符个数。因为输入宿主变量以及查询列表项的个数在运行应用程序前无法确定,所以需要为它们动态分配内存。为了完成这项认务,必须使用SQLDA结构。
SQLDA结构的作用是处理和保存查询列表项以及宿主变量占位符的信息。在动态方法四中输入宿主变量实际上并不是作为宿主变量使用,它们只是一些占位符,我们也将它称为绑定变量。关于SQLDA的相关知识请参阅第八章,这里不再累述。
应用方法四主要处理查询列表项或宿主变量个数未知的SQL语句。其基本步骤如下:
1)定义用于保存动态SQL语句的宿主字符串
应用程序需要使用宿主变量来存储动态SQL语句,这样就需要定义一个字符串宿主变量。
2)定义SQLDA
应用程序需要使用SQLDA结构来存储查询列表项以及占位符的信息,所以我们必须使用如下语句将该结构包含到应用程序中:
EXEC SQL INCLUDE sqlda;
尔后还要定义指向查询描述区的指针。
3)为描述区分配内存
在定SQLDA结构后,为了使用查询描述区和绑定描述区,我们还必须使用函数sqlald()为它们分配内存。当分配描述区时,函数sqlald()会将V[0]到V[N-1]设置为0。该函数语法如下:
descriptor_name=sqlald(max_vars,max_name,max_ind_name);
参数说明如下:
·max_vars:查询列表项或占位符的最大个数。
·max_name:查询列表项名称或占位符名称的最大长度。
·max_ind_name:占位符指示变量名称的最大长度。
4)设置DESCRIBE命令所对应的查询列表项或占位符的最大个数
这一步用于设置DESCRIBE命令可以描述的查询列表项或占位符的最大个数。
5)将SQL语句存储到宿主字符串中
这一步用于接收SQL语句,并将SQL语句保存到宿主变量中。
6)使用PREPARE命令准备动态SQL语句
这一步用于命名和解析SQL语句。
7)使用DECLEAR命令定义游标
8)使用DESCRIBE命令获取绑定变量信息
DESCRIBE BIND VARIABLES命令用于将占位符信息存储到绑定描述区中。
9)重新设置占位符个数
这一步是将DESCRIBE命令获取到的实际占位符个数设置为变量N的值。
10)为绑定变量分配内存并输入数据
如果存在绑定变量占位符,那么应用程序必须为其赋值并分配内存。
11)打开游标
12)使用DESCRIBE命令获取查询列表信息
如果动态SQL语句是SELECT语句,我们还必须使用DESCRIBE SELECT LIST命令将查询列表项的信息存储到查询描述区中。另外需要注意两点:
·该命令将F设置为实际的查询列表数,如果SQL语句不是SELECT语句,则变量F被设置为0。
·NUMBER值长度不可用,必须使用函数sqlprc()获取精度和标度。
13)重新设置查询列表项
这一步用于将DESCRIBE命令获取到的实际查询列表项个数设置为查询列表项的最大个数。
14)重新设置每个查询列表项的长度和数据类型
在使用FETCH命令获取查询列表项数据前,为显示结果可能需要重新设置某些元素的长度和数据类型。
15)利用FETCH命令检索数据
执行此命令后,数据被存储到了查询描述区中。
16)获取并处理查询列表值
在执行了FETCH命令后,可以通过数组V和数组I中的元素来处理检索到的数据。
17)关闭游标
在推进游标、检索完数据后,执行如下命令关闭游标:
EXEC SQLCLOSE s_cursor;
18)释放空间使用函数free()释放由函数malloc()所分配的内存,使用函数sqlclu()释放为查询描述区以及绑定描述区所分配的空间
[目录]
--------------------------------------------------------------------------------
检测错误和状态改变
在Pro*C/C++中,用于检测错误和状态改变的方法有如下两种:
·定义状态变量SQLSTATE或SQLCODE,在执行了SQL语句后检查它们的值,并根据需要执行相应的操作。
·使用SQLCA。SQLCA被定义在头文件sqlca.h中。
在该程序中我们使用了SQLCA进行错误检测。关于SQLCA的详细描述请参阅第八章相关说明,这里不再累述。
WHENEVER语句用于检测并处理错误,使用该语句的语法如下:
EXEC SQL WHENEVER<condition><action>
1)条件(condition)
Oracle可自动检测以下条件:
·SQLWORING:当Oracle返回警告信息时会设置sqlworn[0]为“W”。使用该条件必须定义SQLCA。
·SQLERROR:出现严重错误,此时SQLCODE为负值。
·NOT FOUND:当Oracle不能找到满足条件的记录时SQLCODE被置为+1403。
2)操作(action)
当Oracle检测到以上条件时,应用程序可以执行如下操作:
·CONTINUE:继续运行下一条语句。
·DO:执行错误处理函数。
·GOTO lable_name:转移到标号处执行。STOP:停止执行,回滚事务。
[目录]
--------------------------------------------------------------------------------
SQLCA
SQLCA是一个数据结构,它的成员包含了SQL语句执行后的错误、警告和状态信息。在ORACLE_HOMEpro80cinclude目录下的sqlca.h文件中定义了SQLCA结构。
使用如下语句可以将SQLCA包含到应用程序中:
EXEC SQL INCLUDE SQLCA;
或 #include<sqlca.h>
其部分结构成员如下:
·sqlcaid:标识SQL通讯区的字符串成员,它被初始化为“SQLCA”。
·sqlcabc:整数成员,用于保存SQLCA的字节长度。
·sqlcode:整数成员,它保存着SQL语句执行后的状态代码。Sqlcode的值和含义见表8-1:
Sqlcode的值
含义
0 执行SQL语句成功
>0 执行了该语句但检测到异常情况
<0 出现严重错误,语句没有执行
·sqlwarn:用于设置警告标记的单字符数组,通过赋“W”来设置警告标记。
·sqlerrm:包含了成员sqlerrml及sqlerrmc的一个结构,其中sqlerrml用于保存错误文本长度,sqlerrmc用于保存错误文本。
Sqlerrmc最多可以保存70个字符的错误消息,使用函数sqlglm可以获得完整的错误消息文本,该函数的语法如下:
voidsqlglm(char *message_buffer,size_t *buffer_size,size_t *message_lenth);
参数说明如下:
·message_buffer:存储错误消息的文本缓冲区(尾部以空格填充)。
·buffer_size:缓冲区的字节长度。
·message_lenth:错误消息的实际长度。
注意,调用该函数前必须确保SQLCODE或sqlca.sqlcode不等于0。该函数只能用于非线程应用。
SQLCA中还包括其它结构成员,包括sqlerrp、sqlerrd、sqlext等,由于这些成员的作用相对次要或在程序中没有使用,故这里暂不作介绍。
[目录]
--------------------------------------------------------------------------------
SQLDA
SQLDA结构的作用是处理和保存查询列表项以及宿主变量占位符的信息。
当SQL语句所包含的查询列表项或绑定变量的个数不能确定时,我们就需要使用SQLDA结构来定义和描述查询列表项或绑定变量占位符。因此,该结构也被称为描述区,绑定变量列表所对应的绑定变量列表所对应的描述区就称为绑定描述区。
SQLDA结构保存在ORACLE_HOMEpro80include目录下的sqida.h文件中。利用如下语句可以将该结构包含至应用程序中:
EXEC SQL INCLUDE sqlda;
尔后还要定义指向查询描述区和绑定描述区的指针:
SQLDA *bind_dp;
SQLDA *selectdp;
该结构的内容如下:
struct SQLDA
{
long N;
char **V;
long *L;
short *T;
short **I;
long F;
char **S;
short *M;
short *C;
char **X;
short *Y;
short *Z;
};
该结构的成员函数在动态SQL方法四中发挥着重要的作用,故在这里进行较详尽的介绍:
·变量N:
变量N用于指定查询列表项或占位符的最大个数。在执行DESCRIBE命令前,必须将变量N设置为查询列表项或占位符的最大个数;在执行了DESCRIBE命令后,还必须将变量N设置为存储在变量F中的实际变量数。
·变量V:
变量V是指向数据缓冲区地址数组的指针,该数据缓冲区用于存储查询列表项或绑定变量的值。当分配描述区时,函数sqlald()会将V[0]到V[N-1]设置为0。该函数语法如下:
descriptor_name=sqlald(max_vars,max_name,max_ind_name);
参数说明如下:
·max_vars:查询列表项或占位符的最大个数。
·max_name:查询列表项名称或占位符名称的最大长度。
·max_ind_name:占位符指示变量名称的最大长度。
函数sqlald()只用于非线程应用。而如果要在线程应用中完成同样的功能,则需要使用函数sqlaldt()。另外,也可以使用SQLLIB的新函数SQLSQLDAAlloc(),该函数既可用于线程应用,又可用于非线程应用。
对于查询描述区来说,在执行FETCH命令前必须为变量V分配内存。语句EXEC SQL FETCH…USINGDESCRIPTOR…将查询列表数据存储到了由V[0]到V[N-1]所指向的数据缓冲区中。其中,第i个值存储在V[i-1]所指向的数据缓冲区中。
对于绑定描述区来说,在执行OPEN命令前必须为变量V分配内存。语句EXEC SQL OPEN…USINGDESCRIPTOR…将使用由V[0]到V[N-1]所指向的绑定变量值来执行动态SQL语句。其中,第i个绑定变量的值存储在V[i-1]所指向的数据缓冲区中。
·变量L:
变量L是指向存储在数据缓冲区中的查询列表值或绑定变量值的长度数组的指针。
对于查询描述区来说,DESCRIBESELECT LIST命令会将长度数组设置为每个查询列表项的最大长度。各种数据类型的长度是各不相同的。对于CHAR或VARCHAR2类型的查询列表项来说,DESCRIBE SELECT LIST将L[i]设置为查询列表项的最大长度;而对于NUMBER类型的查询列表项来说,分别被保存到了,通过调用函数sqlpre()可以从L[i]中读取到精度和标度值。函数sqlpre()的语法如下:
sqlpre(long*length,int*precision,int*scale);
该函数的原型在sqlcpr.h文件中。参数说明如下:
·length:指向存储NUMBER值长度的长整数变量的指针。对于变量L来说,长度被存储到L[i]中,而精度和标度分别存储在该变量的低字节和高字节中。
·precision:指向整数变量的指针,NUMBER值的精度返回到该变量中。
·scale: 指向整数变量的指针,NUMBER值的标度返回到该变量中。
该函数只能用于非线程应用。而如果要在线程应用中完成同样功能,则需要使用函数sqlprct()。另外,也可以使用SQLLIB的新函数SQLNumberProV6(),该函数既可用于线程应用又可用于非线程应用。
在执行FETCH命令前,还必须设置L[i]。例如,当将NUMBER值转换为char类型时,应该将L[i]设置为精度加二(也即数字位数+符号位+小数点);而当将NUMBER值转换为float类型时,应该将L[i]设置为浮点数的长度。
对于绑定描述区来说,在执行OPEN命令前必须设置变量L。例如,我们可以通过使用函数strlen()获得绑定变量字符串的长度,尔后将变量L设置为该长度值。
·变量T:
变量T是指向查询列表值或绑定变量值的数据类型代码数组的指针,这些数组类型代码确定了如何进行数据类型转换。
下面列出了Oracle内部数据类型所对应的代码:
Oracle内部数据类型 数据类型代码
VARCHAR2 1
NUMBER 2
LONG 8
ROWID 11
DATE 12
RAW 23
LONG ROW 24
CHARTER(或VHAR) 96
MISLABLE 106
下面列出了Oracle外部数据类型所对应的代码以及C数据类型:
Oracle内部数据类型 数据类型代码 C数据类型
VARCHAR2 1 char[n]
NUMBER 2 char[n](n 22)
INTEGER 3 int
FLOAT 4 float
STRING 5 Float char[n+1]
VARNUM 6 char[n](n 22)
DECIMAL 7 float
LONG 8 char[n]
VARCHAR 9 char[n+2]
ROWID 11 char[n]
DATE 12 char[n]
VARRAW 15 char[n]
RAW 23 unsigned Char[n]
LONG RAW 24 unsigned Char[n]
UNSIGNED 68 unsigned int
DISPLAY 91 char[n]
LONG VARCHAR 94 char[n+4]
LONG VARRAW 95 unsigned char[n+4]
CHARTER(或VHAR) 96 char[n]
MISLABLE 106 char[n]
对于查询描述区来说,DESCRIBESELECT LIST 命令将Oracle内部数据类型所对应的代码返回到了数据类型代码数组中。在使用FETCH命令检索数据时,Oracle会自动在内部和外部数据类型间进行转换,但对于有些数据类型在执行FETCH命令前就需要进行数据类型转换。对于字符数据来说,比较容易处理,但是有些类型的数据处理起来可能比较困难,此时就需要重新设置T的元素了。例如,将NUMBER的值重置为FLOAT或INT。
T[i]的高位存储着第i个查询列表项的NULLNOTNULL状态信息。在执行OPEN或FETCH命令前必须清除该位,这可以通过调用函数sqlnul()来完成。函数sqlnul()的语法如下:
Sqlnul(unsigned short *value_type,unsigned short *type_code,int*null_status);
参数说明如下:
·values_type:指向无符号短整数变量的指针,该变量存储着查询列表项的数据代码类型,而数据类型存储在T[i]中。
·type_code:指向无符号短整数变量的指针,该变量返回了查询列表项的数据类型代码。
·null_status:指向整数变量的指针,该变量返回了查询列表项的NULLNOT NULL状态。其中,1表示允许该列为空,而0表示不允许该列为空。
对于绑定描述区来说,DESCRIBEBIND VARIABLES命令将数据类型代码数组设置为0。在执行OPEN命令前必须设置存储在每个元素中的数据类型代码,该代码表示了V[i]所指向的数据缓冲区中数据的外部存储类型。一般情况下,绑定变量值都被存储在字符串中,所以数据类型数组元素均被设置为1(VARCHAR2的数据类型代码),当然也可使用数据类型代码5(STRING)。
·变量I:
变量I是指向数据缓冲区地址数组的指针,在该数据缓冲区中存储着指示变量值。
对于查询描述区来说,在执行FETCH命令前。当执行EXEC SQL FETCH…USINGDESCRIPTOR…语句时,如果第i个查询列表值为NULL,那么I[i]所指向的指示变量值被设置为-1,否则被置为0(表示值为NOT NULL)或正整数(表示值被截断)。
对于绑定描述区来说,在执行命令前必须为变量I分配内存。当执行EXECSQL OPEN…USING DESCRIPTOR…语句时,I[i]所指向的数据缓冲区可以确定第i个绑定变量是否有NULL值。如果变量值为-1,则相应的绑定变量值为NULL。
·变量F:
变量F是执行了DESCRIBE命令所找到的查询列表项或占位符的实际位数。如果变量F的值小于0,则表示找到的查询列表项或占位符个数太多,超出了描述区尺寸。
·变量S:
变量S是指向数据缓冲区地址数组的指针,在该数据缓冲区中存储着查询列表项或占位符的名称。
在执行了DESCRIBE命令后,第i个查询列表项或占位符的名称被保存到S[i-1]所指向的数据缓冲区中。
·变量C:
变量C是指向数组的指针,该数组保存着查询列表项或占位符名称的当前长度。
在执行了DESCRIBE命令后,元素C[0]到C[N-1]被设置为每个查询列表项或占位符名称的实际字符个数。
在SQLDA中还有其它几个变量,包括变量M、变量X、变量Y、变量Z,因其作用在程序中相对次要,这里不作介绍。
[目录]
--------------------------------------------------------------------------------
编译和链接
在系统特定的Oracle文件内具有关于如何编译和链接Pro*C/C++应用程序的指令,在UNIX系统中有一个make文件,在demo目录中称为proc.mk。执行此程序即可方便地完成如下两项功能:
·将内嵌SQL和PL/SQL转换为对Oracle运行库的调用,同时生成转换后的C或C ++源代码。
·经过编译和链接生成可执行程序。
执行编译和链接时在UNIX命令行中输入命令:
make –f proc.mk [源程序名]
即可将后缀为.pc的源文件编译为后缀为.exe的可执行文件。