日期:2014-05-16  浏览次数:20458 次

PRO*C中使用动态游标的四种方法

? PRO*C中使用动态游标的四种方法

动态方法1
?

动态方法1的处理过程是先构造一个动态SQL语句然后用EXECUTE IMMEDIATE来执行,EXECUTE IMMEDIATE的功能是分析动态的语句的文本,检查是否有错误,
如果SQL 语句仅执行一次动态方法1的效率很高,动态方法1一定不是SELECT 语句
??????????? 1? EXEC SQL EXECUTE IMMEDIATE CREATE TABLE .............;
???????????
??????????? 2 sprintf(host_string,"");
?????????????? EXEC SQL EXECUTE IMMEDIATE :host_string ;

动态方法2

方法2与方法1 类似也是能含有SELECT语句,方法2中含义虚拟输入宿主变量,比方法1 多了一步SQL语句的语法分析,
?处理方式分为3步:
??????????????? 构造一个动态SQL
??????????????? 用PREPARE分析和命名该SQL
??????????????? 用EXECUTE来执行它
??? 用法: sprintf(host_string,"DELETE FROM table_name WHERE no=:v1 AND name=:name");(拼带有输入宿主变量的SQL)
????????? EXEC SQL PREPARE sql_name FROM :host_string;(分析语法)
????????? EXEC SQL EXECUTE IMMEDIATE sql_name USING :v1,:name;(传递实际变量)
?????????
动态方法3

方法就是使用游标,查询并返回多行,如果在方法1和方法2中的SELECT 语句查询返回一行的话,也可以使用SELECT 语句,
方法为 SELECT column1,column2...INTO:variale1,variable2;
方法3是专门解决一次返回多行的,使用方法:
????????????????????????????????????? 1? 拼成一个 SQL sprintf(host_string,"")
????????????????????????????????????? 2? 用EXEC SQL PREPARE name FROM :host_string 来分析其语法
????????????????????????????????????? 3? 用EXEC SQL DECLARE c_name CURSOR FOR : name 来声明游标
????????????????????????????????????? 4? 用EXEC SQL OPEN c_name ;
????????????????????????????????????? 5? 用EXEC SQL FETCH c_name INTO:variable1,:variable2;取出游标中的数据
????????????????????????????????????? 6? EXEC SQL CLOSE c_name;关闭游标
?????????
三种动态SQL方法的特点都是先在C语言中拼成所需要的SQL 文本串,然后用EXECUTE IMMEDIATE 来执行

?

下面是我从网上收集的可以和我的对照,ProC前三种动态SQL的完整示例。

?

?

下面是ProC前三种动态SQL的完整示例。

?

(1)动态SQL1: 不能是查询(SELECT)语句,并且没有宿主变量.?
用法:拼一句动态SQL语句,并用EXECUTE IMMEDIATE执行,如:
?
EXEC SQL EXECUTE IMMEDIATE CREATE TABLE test (test_col VARCHAR2(4));
EXEC SQL EXECUTE IMMEDIATE INSERT INTO TABLE test ('AAAA');
EXEC SQL EXECUTE IMMEDIATE DELETE test WHERE test_col='AAAA';

?

(2)动态SQL2: 不能是查询(SELECT)语句,并且输入的宿主变量数目是知道的,
用法:拼一句动态SQL语句,用PREPARE,EXECUTE语句执行.
strcpy(sqlstring, "DELETE FROM test WHERE test_col = :?");?
EXEC SQL PREPARE sqlproc FROM :sqlstring;
EXEC SQL EXECUTE sqlproc USING :emp_number;?
?
下文示例中大多数是采用动态SQL2.
?
(3)动态SQL3: 用于创建动态查询, 并且要查询的字段以及输入的宿主变量数目是知道的
用法: 拼一句动态SQL语句,用PREPARE分析该语句,并要定义一个CURSOR进行取值
如:要查询的数据在多张表中,select user_name from,可采用动态SQL3来进行查询
strcpy(sql,"select user_name from ");
strcat(sql,"table1");//table2,table3,table4
EXEC SQL PREPARE sqlproc FROM :sql;
EXEC SQL DECLARE cur_user_name CURSOR FOR sqlproc;
EXEC SQL OPEN cur_user_name;
while(1)
{?
EXEC SQL FETCH cur_user_name into :ora_id;
if (sqlca.sqlcode < 0)
{?
/*FETCH CURSOR失败*/?
printf("fetch cursor fail,sqlcode=%ld,sqlserr=%s",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
}
if( sqlca.sqlcode == SQLNOTFOUND)
{
break;
}
}
EXEC SQL CLOSE cur_user_name;?

?

下文示例中Case5也是采用这种方法.

//Proc 示例

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "sqlca.h"
#include <ctype.h>

//变量,过程预声明
int i;
char screen[1];
char cmd[1];

//**********************************************************
//CASE对应与db_selectop的switch
EXEC SQL BEGIN DECLARE SECTION;

VARCHAR oraName[30];    //CASE 1,2,3

VARCHAR oraValue[20];    //CASE 1,2,3,5
int oraCount;          //CASE 1,2,3,4,5
VARCHAR oraSql[30],oraTable[20]; //CASE 4,5

VARCHAR oraField[10];    //CASE 5
VARCHAR oraCountSql[30];   //CASE 5

VARCHAR oraCode[10];    //CASE 6
VARCHAR oraContent[10];    //CASE 6

EXEC SQL END DECLARE SECTION;
//**********************************************************

int db_connect();
int db_selectop();

//v