(7)
动态定义语句
SQL语句分动态定义语句和静态定义语句两种:
(1)
静态定义语句:SQL语句事先编入PRO*C中,在经过预编译器编译之后形成目标程序*。BOJ,然后执行目标程序预即可。
(2)
动态定义语句:有些语句不能事先嵌入到PRO*C程序中,要根据程序运行情况,用户自己从输入设备上(如终端上)实时输入即将执行的SQL语句。
动态定义语句有:
l EXECUTE IMMEDIATE;
l PREPARE 与EXECUTE;
l PREPARE与FETCH 和 OPEN ;
l BIND与DEFINE DESCRIPTOR。
1. EXECUTE
IMMEDIATE语句
此语句表示立即执行, 并且只向SQLCA返回执行结果,无其它信息。例如:
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR abcd[89];
VARCHAR deay[20];
EXEC SQL END DECLARE SECTION;
EXEC SQL EXECUTE IMMEDIATE :abcd;
注意:
1) EXECUTE IMMEDIATE只能运行带一个参数的动态语句。其中,abcd是参数,不是关键字。
2) EXECUTE IMMEDIATE使用的先决条件是:SQL语句不能包含主变量;SQL语句不能是查询语句。
3) 可用任何主变量作为EXECUTE IMMEDIATE的参数;也可用字符串作为主变量。
2.
PREPARE与EXECUTE语句
此语句表示“预编译/执行”。此语句能够预编译一次而执行多次。语法为:
EXEC SQL PREPARE 〈语句名〉FROM:主变量;
EXEC SQL EXECUTE〈语句名〉[USING:替换主变量];
PREPARE语句做两件事:
(1) 预编译SQL语句;
(2) 给出SQL语句的语句名。
注意:
l SQL语句不能是查询语句;
l PREPARE和EXECUTE可包含主变量;
l PREPARE不能多次执行。
例如:
#define
USERNAME “SCOTT”
#define PASSWORD “TIGER”
#include <stdio.h>
EXEC SQL INCLUDE sqlca;
EXEC SQL BEGIN DECLARE SECTION;
Char * username=USERNAME;
Char * password=PASSWORD;
VARCHAR sqlstmt[80];
Int emp_number;
VARCHAR emp_name[15];
VARCHAR job[50];
EXEC SQL END DECLARE
SECTION;
Main()
{
EXEC SQL WHENEVER SQLERROR GOTO :sqlerror;
EXEC SQL CONNECT :username
IDENTIFIED BY :password;
Sqlstmt.len=sprintf(sqlstmt.arr,”INSERT
INTO EMP (EMPNO,ENAME,JOB,SAL)
VALUES(:V1,:V2,:V3,:V4)”);
Puts(sqlstmt.arr);
EXEC SQL PREPARE S FROM :sqlstmt;
For(;;)
{
printf(“\nenter
employee number:”);
scanf(“%d”,&emp_number);
if (emp_number==0) break;
printf(“\nenter
employee name:”);
scanf(“%s”,&emp_name.arr);
emp_name.len=strlen(emp_name.arr);
printf(“\nenter
employee job:”);
scanf(“%s”,job.arr);
job.len=strlen(job.arr);
printf(“\nenter
employee salary:”);
scanf(“%f”,&salary);
}
EXEC SQL EXECUTE S USING :emp_number,:emp_name,:job,:salary;
}
3.
FETCH语句和OPEN语句
FETCH语句和OPEN语句这组动态语句是对游标进行操作的,其执行过程如下:
PREPARE〈语句名〉FROM 〈主变量字符串〉;
DECLARE〈游标名〉FOR〈语句名〉;
OPEN
〈游标名〉[USING:替换变量1[,:替换变量变…]]
FETCH〈游标名〉INTO: 主变量1[,:主变量2…]
CLOSE〈游标名〉
注意:
l SQL语句允许使用查询语句;
l SELECT子句中的列名不能动态改变,只能预置;
l WHERE和ORDER BY 子句可以动态改变条件。
第一个Proc程序
1、环境的搭建
安装好ORACLE后,在用户.profile文件中添加
LD_LIBRARY_PATH=/usr/lib:$ORACLE_HOME/lib:$ORACLE_HOME/ctx/lib:$ORACLE_HOME/rdbms/lib
然后
export LD_LIBRARY_PATH
2、在命令行执行proc正确后,在文件/oracle_install/product/10.2.0.1/precomp/admin/pcscfg.cfg中添加如下内容:
sys_include=(/ade/aime_rdbms_9819/oracle/precomp/public,/usr/include,/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include,/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/include,/usr/lib/gcc-lib/i386-redhat-linux7/2.96/include)
ltype=short
code=cpp
cpp_suffix=cc
parse=none
SQLCHECK=SEMANTICS
注:关于code=cpp,这里有三种模式,code=cpp、code=kr_c、code=ansi_c。采用何种方式决定了与编译proc编译后的文件后缀名和函数原型的方式。
2.1 code=cpp
此时,与编译将采用C++的原型编译方式,编译后的文件以.cc结尾。
2.2 code=kr_c和code=ansi_c
此时编译器都将按照C语言的原型方式编译,编译后文件以.c结尾。两者的区别是:
当采用code=kr_c的方式编译时,原型编译为如下形式:
extern void sqlora() ;
当采用code=ansi_c的方式编译时,原型编译形式如下:
extern void sqlora(long *, void *) ;
3、编写源程序first.pc。
#include <stdio.h>
EXEC SQL include sqlca.h ;
EXEC SQL BEGIN DECLARE SECTION ;
char *uid = "";
char *username = "guoxin";
char *password = "guoxin";
char *conn_name = "10.10.10.22:1521/ipuser";
char *db_link_name = "ipuser";
EXEC SQL END DECLARE
SECTION ;
int main()
{
EXEC SQL CONNECT :uid;
//or EXEC
SQL CONNECT :username
IDENTIFIED BY :password
USING :conn_name;
if (sqlca.sqlcode == 0) {
printf("Conn
OK;/n") ;
} else {
printf("Conn
ERROR;/n") ;
}
return 0 ;
}
4、编写Makefile文件。
CC=g++
first:
proc first.pc
${CC} -o first -I$(ORACLE_HOME)/precomp/public/
-L$(ORACLE_HOME)/lib/ -lclntsh first.cc
rm -rf t* first.lis first.cc
clean:
rm -rf t* first.lis first.cc
rm -rf first
值得说明的是,如果我们采用code=cpp的方式编译,CC必须使用g++编译器,否则报错;如果采用code=ansi_c/code=kr_c的方式编译,则可使用C语言的编译器,如cc、gcc等。上述给出的是采用code=cpp的方式编译的,下面给出code=ansi_c/code=kr_c的makefile文件。
CC=cc
first:
proc first.pc
${CC} -o first -I$(ORACLE_HOME)/precomp/public/
-L$(ORACLE_HOME)/lib/ -lclntsh first.c
rm -rf t* first.lis first.c
clean:
rm -rf t* first.lis first.c
rm -rf first
注意此时的first.cc都变成了first.c文件。
5、执行make命令,则输出如下结果:
proc first.pc
Pro*C/C++:
Release 10.2.0.1.0 - Production on Thu Jan 15 15:23:19
2009
Copyright
(c) 1982, 2005, Oracle. All rights reserved.
System
default option values taken from:
/oracle_install/product/10.2.0.1/precomp/admin/pcscfg.cfg
g++ -o
first -I/oracle_install/product/10.2.0.1/precomp/public/
-L/oracle_install/product/10.2.0.1/lib/ -lclntsh -lecpg
first.cc
rm -rf t* first.lis first.cc
表明执行成功,通过ls命令可以看到first执行程序已经成功被编译出来。
$ ls
first first.pc makefile
$ 6、运行first。
$ ./first sqlca.sqlerrm.sqlerrmc:[];
Conn OK;
$ 至此,第一个proc程序结束。
注意:
oracle proc PCC-S-02015错误
错误信息:
System default option values taken from:
/u01/app/oracle/product/10.1.0/precomp/admin/pcscfg.cfg
Error at line 34, column 11 in file /usr/include/stdio.h
# include
..........1
PCC-S-02015, unable to open include file
Error at line 31, column 10 in file
/usr/include/bits/types.h
#include
.........1
PCC-S-02015, unable to open include file
Error at line 14, column 10 in file
/usr/include/_G_config.h
#include
.........1
PCC-S-02015, unable to open include file
Error at line 48, column 10 in file /usr/include/wchar.h
#include
.........1
PCC-S-02015, unable to open include file
Error at line 48, column 10 in file /usr/include/wchar.h
#include
.........1
PCC-S-02015, unable to open include file
Error at line 31, column 10 in file /usr/include/gconv.h
#include
.........1
PCC-S-02015, unable to open include file
解决修改:$ORACLE_HOME/precomp/admin/pcscfg.cfg
(网络上很多答案是添加选项parse=none,意思是忽略头文件预编译.如果说含有宏定义则根本没有解决.不提倡)
在/usr/lib/下查找未找到的"stddef.h"文件,找到路径在pcscfg.cfg修改或添加该路径.
find . -name "stddef.h" -print ./gcc-lib/i386-redhat-linux/3.2.3/include/stddef.h
原来:sys_include=(/tmp/p/precomp/public,/usr/include,/usr/lib/gcc-lib/i486-suse-linux/3.2.2/include,/usr/lib/gcc-lib/i486-suse-linux/3.2/include,/usr/lib/gcc-lib/i386-redhat-linux/4.0.0/include,/usr/lib/gcc-lib/i386-redhat-linux7/3.2.3/include,/usr/lib/gcc-lib/i586-suse-linux/3.3.3/include)
改为:
sys_include=(/tmp/p/precomp/public,/usr/include,/usr/lib/gcc-lib/i486-suse-linux/3.2.2/include,/usr/lib/gcc-lib/i486-suse-linux/3.2/include,/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/include,/usr/lib/gcc-lib/i386-redhat-linux7/3.2.3/include,/usr/lib/gcc-lib/i586-suse-linux/3.3.3/include)
如果使用时为乱码,执行 export NLS_LANG="Simplified Chinese_china.AL32UTF8"