SQL变量的申明: EXEC SQL BEGIN DECLARE SECTION; 类型 变量名【长度】 varchar2 serv_number[11]; 其中可以定义C变量 EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE Slqca; 说明SQL的通讯区,记录执行每一个SQL语句的状态。 错误信息处理 EXEC SQL WHENEVER SQLERROR DO sqlerror(); 指出执行SQL语句时,如果发生错误应如何处理。 连接数据库 EXEC SQL CONNECT :username IDENTIFIED BY :password; 嵌入式SQL语句或pl/sql块中的关键字应大写。 SQL变量 在变量的申明中定义,只允许包含下列语句: (一)SQL变量的类型说明语句 (二)EXEC SQL INCLUDE (三)EXEC SQL VAR (四)EXEC SQL TYPE EXEC SQL VAR 和EXEC SQL TYPE 分别用于将sql变量和外部的变量等价。用法如下: EXEC SQL VAR host_variable IS type_name[(length)]; 可以用户定义类型和等价: struct screen { short len; char buff[100]; } typedef struct screen graphics; EXEC SQL BEGIN DECLARE SECTION; EXEC SQL TYPE graphics IS VARRAW(4000); EXEC SQL END DECLARE SECTION; 可以将一个用户说明的类型定义为显示的或隐式的指针,然后使用新的类型。必须使用Reference; 如: EXEC SQL TYPE graphics varraw(4000) Reference; graphics my_raw; 可以使用如下的修饰符来说明变量的性质: auto static extern const 定义的常量 volatile 有一个程序不知道的方法(如 通过设备)来改变值 VARCHAR变量的说明和应用: C中没有这种类型,特别引入的这种类型,称为伪类型。 EXEC SQL BEGIN DECLARE SECTION; VARCHAR user_name(11); EXEC SQL END DECLARE SECTION; 在预编译时,该变量被翻译成: struct { unsigned short len; unsigned char arr[20]; } user_name; 通讯区的说明: Oracle提供了两个通讯区SQL通讯区(sqlca)和Oracle通讯区(oraca) sqlca是一个结构类型的标量,是Oracle和应用程序的接口,执行Pro*C时,Oracle把每一个嵌入的SQL执行的状态存入sqlca; sqlca的结构: struct sqlca{ char sqlcaid[8]; //标识一个sql通讯区 long sqlbc; //通讯区的长度 long sqlcode; /* 最近执行Sql后的状态码 有三中可能的值: 0 正确结束 >0 Oracle执行了该语句,但遇到了例外 <0 Oracle未执行该语句,当出现这类错误时,应该回滚该事务。 */ struct { unsigned short sqlerrml; //保存sqlerrmc中的文本的长度 unsigned char sqlerrmc[70]; //保存sqlcode编码对于的错误信息,只有当sqlcode的值为负时,才应用sqlerrmc,只有70个字符,如果要应用超过70个字符的信息,必须使用SQLGLM()函数。如果sqlcode执行为0时,sqlerrmc为最近sql的信息。 }sqlerrm; char sqlerrp[8]; long sqlerrd[6]; char sqlwarn[8]; char sqlext[8]; } sqlca; 通讯区的应用方式: EXEC SQL INCLUDE sqlca; 或将上述编码拷贝到C代码中。 SQLGLM的应用,sqlglm(message_buffer,&buffer_size,&message_length); message_buffer: 文本缓冲区,将错误的信息保留中这里,用空格补充后面的空间。 buffer_size : 缓冲区的长度。 message_length: Oracle错误信息的实际的长度。 oraca 类似与sqlca,但比sqlca提供的信息更多。 INCLUDE 语句 作用将一个文件拷贝到程序中,类似于#include 定义: EXEC SQL INCLUDE filename; 程序中使用的是filename的副本。 断开数据库连接 EXEC SQL COMMIT WORK RELEASE; 错误处理的方法: EXEC SQL WHENERVE SQLERROR GOTO sqlerror; sqlerror: EXEC SQL WHENERVER SQLERROR CONTINUE; EXEC SQL ROLLBACK; exit(1); 也可以使用方法: sqlerror(); void sqlerror; EXEC SQL WHENEVER SQLERROR DO sqlerror(); void sqlerror() { EXEC SQL WHENERVER SQLERROR CONTINUE; EXEC SQL ROLLBACK; exit(1); } 数据未找到信息的处理方法: EXEC SQL WHENEVER NOT FOUND GOTO notfound; notfound : printf("not found"); SQLCA.SQLERRD[2] //记录处理的行数 select 语句中不允许使用FOR子句。 select返回的多行确定时,可以使用数组,但必须有MODE={ANSI|ANSI13|ORACLE}; 当select返回的行不确定时,可以使用光标。 光标的思想: 使用光标时,开辟了一个缓冲区,将SELECT的查询结果存放在缓冲区中,并将指针指向第一条记录。 光标语句的使用: (一)说明一个游标 使用declare cursor EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT BRAND_ID,BRAND_DESC FROM TB_DET_BRAND WHERE BRAND_ALL_ID=:emp_number; 注意:光标的全程必须在一个编译区内。 (二)打开光标 EXEC SQL OPEN emp_cursor; OPEN语句的作用: 1. 定义一个光标缓冲区 2. 把满足条件的行检索到缓冲区中 3. 将光标指向第一行 4. 行计算器sqlca.sqlerrd[2]清0; (三)提取 EXEC SQL FETCH emp_cursor INTO :brand,:brand_name; (四)关闭光标 EXEC SQL CLOSE emp_cursor; 技巧: Oracle中的字符串以NULL结尾。因而,可以使用类型等价实现。 typedef char aciz; aciz name; aciz brand; EXEC SQL TYPE aciz IS SRTING(20); 这样,aciz是以NULL为结束符。 光标使用的例子: main() { ....... EXEC SQL WHENEVER SQLERROR DO sqlerror(); //连接数据库 EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT BRAND_ID,BRAND_DESC FROM TB_DET_BRAND WHERE BRAND_ALL_ID=:emp_number; EXEC SQL OPEN emp_cursor; for(;;) { EXEC SQL WHENEVER NOT FOUND DO break; EXEC SQL FECTH emp_cursor INTO :brand,:brand_name; //处理信息 } EXEC SQL CLOSE emp_cursor; exit(0); } Pro*C嵌入PL/SQL块 认为特色的地方: 可以使用RECODE类型 TYPE test_type IS RECODE ( brand_id varchar2(4) not null, brand_desc varchar2(80)); 嵌入PL/SQL的方法 EXEC SQL EXECUTE DECLARE ---pl/SQL BEGIN END; END_EXEC; 指示器变量: 作用: 从宿主程序接收NULL值存入数据库表中 把NUll或截断的值输出给宿主变量 使用方法: 如 :emp_name:ind_emp 过程: 当进入PL/SQL块时,如果指示器的值为-1,则PL/SQL自动把NULL值赋给相应的宿主变量。 退出该块时,如果宿主变量的值为NULL,则把-1赋给相应的指示器变量。 PL/SQL块中只使用数组的一部分时,可以指定最小的数组的大小: 方法: EXEC SQL ARRAYLEN host_array (array_integer); EXEC SQL BEGIN DECLARE SECTION; float salary[100]; int m; EXEC SQL ARRAYLEN salary(m); EXEC SQL END DECLARE SECTION; 指定数据的维数 m=30; 上例中只有30个元素被传递到PL/SQL块中。 方法: (一)启动oracle通讯区 EXEC ORACLE OPTION (ORACA=YES); (二)指定RELEASE_CURSOR=YES,用于释放Pro*C执行后SQL的资源,这将保证数据操作后,oracle不保持表分析锁,后续的数据定义操作不会导致分析锁错误。 EXEC ORACLE OPTION (RELEASE_CURSOR=YES); 错误处理 动态SQL技术 动态sql方法1: 用于非select语句,方法: execute immedite ‘insert into ....’;不允许输入宿主变量; 动态sql方法2:(用于非SELECT) PREPARE语句:(分析和命名一个动态SQL语句) EXEC SQL PREPARE [statement_name][block_name] FROM [:host_string][string_literal]; 例: strcpy(sql_t1,"DELETE FROM EMP WHERE EMP_NAME=:V"); EXEC SQL PREPARE p1 FROM :sql_t1; EXECUTE 语句: 例 EXEC SQL EXECUTE p1 USING :ind_emp; 方法1和方法2区别: 方法1每执行一次分析一次,而方法二分析一次,多次执行。 动态SQL方法3:(只用于select语句) 例: EXEC SQL BEGIN DECLARE SECTION; VARCHAR sqlstmt[80]; int imp; int brand; int brand_a; EXEC SQL END DECLARE SECTION; .... main() { //构造动态SQL sqlstmt.len=sprintf(sqlstmt.arr,"select brand_id,brand_all_id from tb_det_brand where brand_all_id=:v"); //分析动态的SQL EXEC SQL PREPARE p1 FROM :sqlstmt; //说明光标 EXEC SQL DECLARE c1 CURSOR FOR p1; imp=1001; ...... //打开光标 EXEC SQL OPEN c1 USING :imp; EXEC SQL WHENEVER NOT FOUND DO break; while(true) { //提取数据 EXEC SQL FETCH c1 INTO :brand,:brand_a; ................ } //关闭光标 EXEC SQL CLOSE c1; } 动态方法四: 特点: 在执行SQL之前,表项、宿主变量个数、类型直到执行前仍然不知道。因而,不能在预编译时产生完整的Oracle调用。 对于方法四,要求提供如下的信息: 选择表项和实宿主变量的个数。 每一个表项和实宿主变量的长途。 每一个表项和实宿主变量的类型。 每一个输出宿主变量(存储选择表项的值)和实输入宿主变量的内存单元地址。 提供信息的方法: oracle提供的SQL的描述区来说明,它提供了一个sqlda 的数据结构。 具体的过程如下: 将选择表项和虚拟输入宿主变量分别保存在选择SQLDA和结合SQLDA中。选择表项的值和名字被存储在输出缓冲区,而实输入宿主变量的值和名字被存储在输入缓冲区。输出缓冲区的地址存储在选择SQLDA中,而输入缓冲区的地址存储在结合SQLDA中。 SQLDA写入信息的方法: (一)sqlald()函数 在分配描述区和缓冲区时,还把SLI(选择表项)或P(虚拟输入宿主变量)的名字在缓冲区中的地址和长度写入SQLDA中。 (二)应用程序 通过程序把存放SLI或BV(结合变量或实输入宿主标量)的值的缓冲区的地址、长度及数据类型写入SQLDA中。 (三)DESCRIBE DESCRIBE SELECT LIST 检查每一个选择表项的信息将信息存储在选择SQLDA及输出缓冲区中。 DESCRIBE BIND VARIABLES 检查每一个虚拟输入宿主变量的信息将信息存储在结合SQLDA及输入缓冲区中。 SQLDA的说明和应用 1. 使用INCLUDE EXEC SQL INCLUDE sqlda; 2. 使用指针 EXEC SQL INCLUDE sqlda; sqlda *bind_dp; sqlda *select_dp; bind_dp=sqlald(....); select_dp=sqlald(....); SQLDA的应用 对于每一个动态的SQL都应该说明一个SQLDA. 库函数sqlprc()分离精度和定标。 用户出口(SQL*Forms) EXEC IAF GET EXEC IAF PUT EXEC IAF GET 将form中的值取出赋给宿主变量 例 EXEC IAF GET brand_id INTO :brand; //将brand_id的值取出赋给宿主变量brand EXEC IAF PUT 将常量或宿主变量的值放入forms中 例 EXEC IAF PUT brand VALUES(:brand_id); 用户出口的引用 方法: 定义触发器,在触发器中,用USER_EXIT(user_exit_string[,error_string])引用出口。 错误处理 whenever 子句 EXEC SQL WHENEVER {SQLERROR|NOT FOUND|SQLWARNING} {CONTINUE|DO function call|DO break|GOTO table|STOP};
时间: 2024-10-08 17:16:44