|
SQL语句执行后,Oracle 运行时会在这个结构中填入信息。如果要使用SQLCA,你要用#include包含进sqlca.h头文件。如果在很多地方包含了头文件,你要使用#undef SQLCA来取消SQLCA的宏定义。sqlca.h中的相关程序块如下: #ifndef SQLCA
#define SQLCA 1
struct sqlca {
/* ub1 */ char sqlcaid[8];
/* b4 */ long sqlabc;
/* b4 */ long sqlcode;
struct {
/* ub2 */ unsigned short sqlerrml;
/* ub1 */ char sqlerrmc[70];
} sqlerrm;
/* ub1 */ char sqlerrp[8];
/* b4 */ long sqlerrd[6];
/* ub1 */ char sqlwarn[8];
/* ub1 */ char sqlext[8];
};
/* ... */sqlca域有下列的意义: sqlcaid该字符串域初始化为"SQLCA",以指明这是个SQL通讯区。sqlcabc该整数域用byte标识SQLCA结构的长度。sqlcode这个整数域标识最近执行的SQL语句的状态码: 0没有错误。>0语句执行但捕获异常。当Oracle根据WHERE条件查找不到任何记录,或SELECT INTO或FETCH影响记录数为0时会发生这种情况。<0由于一个错误Oracle不能执行SQL语句。当这个错误发生时,多数情况下当前的事务应该回滚(rollback)。 sqlerrm这个内嵌结构包含两个域: - sqlerrml - 在sqlerrmc中保存的信息文本的长。
- sqlerrmc - 最大到70个字符(character)的信息文本,与sqlcode中存储的错误码相似。
sqlerrp保留sqlerrd这个二进制整形数组包含6个元素: - sqlerrd[0] - 保留
- sqlerrd[1] - 保留
- sqlerrd[2] - 最近被执行的SQL语句影响的记录行数。
- sqlerrd[3] - 保留
- sqlerrd[4] - 分析最近执行语句出现错误,错误的开始字符的偏移。
- sqlerrd[5] - 保留
sqlwarn这个单字符数组包含8个元素,用于警告标志。Oracle使用字符''''W''''设置一个标记。 sqlwarn[0]当其它标记被设置时设置。sqlwarn[1]当输出宿主变量中保存的是被截断的字段值时设置。sqlwarn[2]当计算SQL统计如AVG或SUM时,如果一个NULL字段不能被使用时被设置。sqlwarn[3]当SELECT的字段数与INTO句中指定的宿主变量数不等时设置。sqlwarn[4]当没有使用WHERE子句的UPDATE或DELETE语句处理了数据表中的每一行时设置。sqlwarn[5]当由于PL/SQL编译错误而导致procedure/function/package/package body创建命令失败时设置。sqlwarn[6]不再使用sqlwarn[7]不再使用 sqlext保留SQLCA只能在sqlerrm域中存储最大70字符长的错误信息。要得到更长的(或嵌套的)全部错误信息字符,可以使用sqlglm()函数: void sqlglm(char *msg_buf, size_t *buf_size, size_t *msg_length); msg_buf是Oracle存储错误信息的字符缓冲;buf_size指定msg_buf的长(byte); Oracle在*msg_length中存放实际的错误信息长。Oracle错误信息的最大长度是512字节(byte)。
WHENEVER语句这个表达式进行自动错误检查和处理。语法是: EXEC SQL WHENEVER <condition> <action>; Oracle自动检查<condition>的SQLCA,当条件被检测到时,程序会自动执行<action> <condition>可以是下列各项: - SQLWARNING - 由于Oracle返回一个警告而设置sqlwarn[0]
- SQLERROR - 由于Oracle返回一个错误, sqlcode的值为负
- NOT FOUND - 由于Oracle按WHERE的条件没有找到任何一条记录,或SELECT INTO或FETCH返回0条记录,而使sqlcode为正
<action> 可以为下列各项: - CONTINUE - 只要可能,程序会尝试继续运行之后的语句
- DO - 程序将控制权交给一个错误处理模块
- GOTO <label> - 程序跳转到被标示的语句
- STOP - 调用exit()结束程序,回滚未提交的操作
下面是WHENEVER语句的例子: EXEC SQL WHENEVER SQLWARNING DO print_warning_msg();
EXEC SQL WHENEVER NOT FOUND GOTO handle_empty; 下面是一个更详细的例子: /* code to find student name given id */
/* ... */
for (;;)
{
printf("Give student id number : ");
scanf("%d", &id);
EXEC SQL WHENEVER NOT FOUND GOTO notfound;
EXEC SQL SELECT studentname INTO :st_name
FROM student
WHERE studentid = :id;
printf("Name of student is %s.\n", st_name);
continue;
notfound:
printf("No record exists for id %d!\n", id);
}
/* ... */注意WHENEVER表达式不遵从标准C的作用域规则,整个程序都是它的作用域。举例来说,如果下面的语句在你程序中的什么地方(如在一个循环之前): EXEC SQL WHENEVER NOT FOUND DO break; 这个文件在这行之后出现的所有SQL语句都会受其影响。当不再需要WHENEVER 的来影响程序时(比如在你的循环之后),确保使用下面的语句取消它的使用。 EXEC SQL WHENEVER NOT FOUND CONTINUE;
Demo程序注意: 例程会创建、使用四个表:DEPT、EMP、PAY1和PAY2。注意你的数据库中可能会存在相同名子的表! 在leland系统的/afs/ir/class/cs145/code/proc下有很多例程。它们被命名为sample*.pc(C用户)和cppdemo*.pc(C++用户)。 ".pc"是Pro*C代码的扩展名。由于有几个固定的步骤复制这些文件,所以不要手工复制它们。下面介绍如何下载和设置例程: - 确认你已经运行了source /afs/ir/class/cs145/all.env
- 在你的目录下,运行load_samples <db_username> <db_passwd> <sample_dir>, <sample_idr>是你想放置例程的地方(例:load_samples sally etaoinshrdlu cs145_samples )
- cd <sample_dir>
- 运行make samples(C++用户运行make cppsamples)编译所有的例程。
第2步将会建立样品数据库,创建在<sample_dir>指定的新目录,然后把文件复制到目录下。它会在例程中修改你的用户名和密码,所有你不必每次运行例程时都要输入用户名和密码。sample1 和cppdemo1也为用户提供了输入用户名和密码的接口,当你想要学习如何使用的时候。如果在第2步输入用户名和密码时产生了任何错误,只要在你的目录下运行clean_sample <db_username> <db_passwd> & lt;sample_dir>,然后重做第2步到第4步。 对于第4步,你可以单独编译每一个例程。比如单独编译sample1.pc。编译过程实际上有两句: - proc iname=sample1.pc
把内嵌SQL代码转换为相应的库调用,输出sample1.c - cc <a_number_of_flags_here> sample1.c
主成可执行的sample1
编译你自己的代码,如foo.pc,只要修改Makefile的几个变量:在SAMPLES变量中加入foo程序名,在SAMPLE_SRC变量中加入foo.pc源文件名。然后,写好foo.pc 后make foo。foo.pc被预编译为foo.c,再编译为可执行的foo。C++用户要把程序名和源文件名加入到CPPSAMPLE和CPPSAMPLE_SRC而不是SAMPLES和SAMPLE_SRC。 例程运行于下面的数据库表上: CREATE TABLE DEPT
(DEPTNO NUMBER(2) NOT NULL,
DNAME VARCHAR2(14),
LOC VARCHAR2(13));
CREATE TABLE EMP
(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2));
CREATE TABLE PAY1
(ENAME VARCHAR2(10),
SAL NUMBER(7, 2));
CREATE TABLE PAY2
(ENAME VARCHAR2(10),
SAL NUMBER(7, 2));当在第2步运行load_samples的时候这些表就自动创建好了。一些tuples(译注:没找到合适的词,把原词放这了)也插入了。你可以在程序运行前查看这些表也可以任意操作这些表(如:插入、删除或是更新tuples)。当你运行clean_sample时,这些表自动被删除。注意:clean_sample也会清理整个<sample_dir>;; 确保在运行这个命令之前将你自己的文件转移到其它的地方! 你应该在运行它之前看一看源代码,头部的注释描述了程序都做些什么。例如,sample1从一个雇员的EMPNO 得到他的名子和工资,从EMP表中得到的那个雇员的佣金。 通过学习源程序你应该可以学到下面的东西: - 如何从主机连接到Oracle
- 如何在C/C++中嵌入SQL
- 如何使用游标
- 如何使用宿主变量与数据库通讯
- 如何使用WHENEVER进行不同的错误处理动作
- 如何使用指示器变量检测输出中的空值
现在,你可以使用这些技术编写你自己的数据库应用程序了。And have fun!
C++用户要使用预编译器生成合适的C++代码,你需要注意下面的事项: - 代码被预编译器展开。要得到C++代码,你需要在执行proc时设置CODE=CPP选项。
- 解析能力。proc的PARSE选项可以是下面的值:
- PARSE=NONE. C预处理指令只能在声明节中被解析,所以所有的宿主变量需要在声明节中声明。
- PARSE=PARTIAL. C预处理指令能被解析;然而,所有的宿主变量需要在声明节中声明。
- PARSE=FULL. C预处理指令能被解析,而且宿主变量可以声明在任何地方。当CODE不为 CPP时,这是默认设置;但当CODE=CPP时,指定PARSE=FULL却是个错误。
所以,C++用户必须指定PARSE=NONE或PARSE=PARTIAL,因此这也失去了在任意地方声明宿主变量的自由。更有,宿主变量必须被包在一个声明节中,如下: EXEC SQL BEGIN DECLARE SECTION;
// declarations...
EXEC SQL END DECLARE SECTION;你需要使用这种方法去声明所有的宿主和指示器变量。- 文件扩展名。你要指定设置CPP_SUFFIX=cc或CPP_SUFFIX=C。
- 头文件定位。默认情况下,proc像标准定位stdio.h文件一样查找头文件。然而C++有自己的头文件,如iostream.h,被放置在别处。所以,你需要使用SYS_INCLUDE选项指定proc查找头文件的路径。
Pro*C支持的嵌入SQL语句列表声明表达式EXEC SQL ARRAYLEN在PL/SQL中使用宿主变量EXEC SQL BEGIN DECLARE SECTION EXEC SQL END DECLA上一页 [1] [2] [3] 下一页 [Access]sql随机抽取记录 [Access]ASP&SQL让select查询结果随机排序的实现方法 [办公软件]在sybase中插入图片、PDF、文本文件 [办公软件]安装Sybase ASE [办公软件]linux指令大全(完整篇) [办公软件]Linux新手入门常用命令大全 [办公软件]在RedHat Linux 9里安装gaim0.80 [办公软件]浅谈Linux 下Java 1.5 汉字方块问题解决方法 [办公软件]Linux程序员必读:中文化与GB18030标准 [办公软件]linux指令大全
|