proc/c++
籍辰沛
2023-12-01
一.什么是pro程序
通过在过程化编程语言中 嵌入sql语句开发出的
应用程序叫pro程序。
宿主语言:sql 语句所嵌入的语言。
sql语句是寄生在这些语言上的。
二.proc/c++
希望通过c或者c++ 成为访问oracle数据库的工具
三.一个proc程序 涉及到内容
定义变量
定义函数
导入头文件
和数据操作相关的
连接数据库:
exec sql connect:userpasswd;
exec sql connect:username identified
by userpasswd;
查询数据库:
exec sql select first_name into :变量
from s_emp where 条件;
断开数据库连接:
exec sql commit work release;
exec sql rollback work release;
四.如何写一个c程序?
1.编写源代码
vi ***.c
2.编译
gcc -c ***.c
3.链接
gcc ***.o -l库名
4.执行
./a.out
五.如何写一个proc程序?
1.编写源代码
vi ***.pc
2.预编译 得到c文件
proc ***.pc
3.编译 链接
gcc ***.c -lclntsh
gcc ***.c -lorasql10 -L (windows)
4.执行
./a.out
上传文件
1.找到要上传的文件
2.ftp IP
openlab
open123
3.切换服务器的目录
cd 目录
4.放入文件
put 文件名;
find / -name clntsh* 2>/dev/null
find / -name stddef.h 2>/dev/null
proc first.pc include="头文件的路径"
六. 宿主变量
6.1 概念
既能在sql语句中使用的变量 又能在宿主语言中
使用的变量。
6.2 类型限制
char
char var[n] 定长字符串
int
short
long
float
double
varchar var[n] 变长字符串
定长字符串 char var[n]
变长字符串 varchar var[n]
在select语句中 要和正常的变量一样去使用
在宿主语言中需要使用 变量名.arr 取得
数据。数据的长度可以使用.len 获得。
要注意垃圾数据的问题。
给变长字符串数组 进行初始化
varchar var_name[30]={0};
var_name.arr[var_name.len]='\0';
七.proc 的预编译选项
proc ***.pc include="头文件路径"
char_map=charz 默认的 定长 空格补齐 \0
charf varchar2 定长 空格补齐
string 变长 \0结尾
和c++ 相关的选项
oname 输出文件名 默认以.c结尾
c++ 一般以点cpp 结尾
parse 默认是c的full方式
partia 严格的c++检查 不建议使用
none c++ 推荐使用
code 默认是 ansi_c
cpp 则必须把宿主变量放入申明区
exec sql begin declare section;
exec sql end declare section;
(c++ 程序的编译器是g++ )
proc ***.pc oname=***.cpp parse=none
code=cpp
g++ ***.cpp -lclntsh
和PLSQL调用相关的选项
sqlcheck=semantics
userid=用户名/密码
#include <sys/types.h>
include="/usr/include/i386"
八.宿主变量 使用的注意事项
宿主变量名前 要加冒号
exec sql select first_name into :var_name
from s_emp where id=:id;
宿主变量 推荐放入申明区
不同系统 不同语言对宿主变量的定义不同
加上申明区 可以避免这些差异。
exec sql begin declare section;
exec sql end declare section;
宿主变量的类型 可以是指针类型 但必须分配
内存空间.(字符串尽量不要用堆分配)
DDL 中不能使用宿主变量
char table_name[30]="s_emp";
exec sql drop table table_name;
exec sql drop table :table_name;
九.指示变量
9.1 作用
当数据库中的字段的值 赋值给宿主变量时 赋值的
状态可以通过指示变量得到。
==0 赋值正常
==-1 数据库中的字段值是NULL值
>0 截断赋值 尽量避免
9.2 语法
指示变量 必须是short类型
short indmid=88;
exec sql select manager_id
into :mid:indmid from s_emp where id=1;
exec sql select manager_id
into :mid indicator :indmid
from s_emp where id=1;
9.3 把id=1 的manager_id 赋值给宿主变量 mid
并且指示mid的赋值状态。
十.数组变量
10.1 数组变量的使用注意事项
proc只支持一维数组 字符除外
char var_name[30];
char var_names[50][30];
select语句中使用数组只能数组名 不能
出现下标。
proc 不支持数组指针。
数组元素个数 32767
10.2 举例
int mids[50];
char var_names[50][30];
short indmids[50];
把s_emp 表中所有的manager_id 和first_name
数据 分别放入上面的数组中。并且指示
manager_id 赋值状态。
十一.sqlca 通信区
sqlca 通信区 本质上就是一个结构体
每执行一次sql 都会把sqlca中的字段
更新一遍。所以得到一条sql语句的状态
要执行完sql时立即判断。否则会被下一次
sql覆盖掉。
sqlca.sqlerrd[2] 最近一次sql语句影响的行数
sqlca.sqlcode 得到sql语句执行状态
==0 执行正常
>0 sql执行出错
<0 数据库本身出错 或者网络错误
sqlca.sqlerrm.sqlerrmc sql出错的消息内容
一.数据库的连接:
本地连接
exec sql connect:usernameandpasswd;
exec sql connect:username identified by
userpasswd;
echo $ORACLE_SID (得到数据库服务名)
远程连接
$ORACLE_HOME/network/admin/tnsnames.ora
CAH_192.168.0.26 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.26)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = tarena)
)
)
第二种远程数据库连接方式:
database link
create database link 链接名
connect to 用户名 identified by
密码 using '数据库描述';
drop database link mydb26dblink;
create database link mydb26dblink
connect to openlab identified by
open123 using
'CAH_192.168.0.26';
select id,first_name from
s_emp@mydb26dblink where id=1;
drop database link mydb20dblink;
create database link mydb20dblink
connect to openlab identified by
open123 using
'(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.20)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = tarena)
)
)';
select id,first_name from
s_emp@mydb20dblink where id=1;
select * from
tang1_sql@mydb20dblink;
update s_emp set
salary=salary+2000 where id=1;
update s_emp@mydb26dblink set
salary=salary+2000 where id=25;
select id,salary
from s_emp@mydb26dblink where id=25;
两种远程数据库连接:
$ORACLE_HOME/network/admin/tnsnames.ora
host service_name
exec sql connect:userpasswd at:标签名
using '远程数据库描述';
exec sql connect:userpasswd at:标签名;
exec sql at:标签名 select ...;
exec sql at:标签名 update ...;
使用database link
在数据库中建立database link
create database link 链接名 connect to
用户名 identified by 密码
using '远程数据库描述';
在proc代码中使用链接 必须先登录本地
数据库。
使用时只要在操作表名后加上@链接名
exec sql connect:userpasswd;
exec sql select salary into :salary
from s_emp where id=25;
exec sql select salary into :salary
from s_emp@mydb26dblink where id=25;
exec sql update s_emp@mydb26dblink
set salary=salary+200 where id=25;
exec sql commit;
二.sqlca与错误处理
/* 局部错误处理 */
exec sql update account set money=
money-20000 where id='001';
if(sqlca.sqlcode==0){
a=1;
}else{
a=0;
}
exec sql update account set money=
money+20000 where id='002';
if(sqlca.sqlcode==0){
b=1;
}else{
b=0;
}
if(a&&b){
commit;
}else{
rollback;
}
/* 全局错误处理 */
exec sql whenever 条件 动作;
条件:sqlerror notfound sqlwarning
动作:do 函数;
do break;
continue;
stop;
goto 标签;
当程序出现问题时 程序就会向上找一个
合适的处理。如果没有找到相应的处理 则
采用默认的处理方式。
如果进行了sql语句的执行结果判断,会
先进行全局处理 后进行局部处理。
三.数据的操作
3.1 一个变量 一次只能操作单行单列
exec sql select first_name into
:var_name from s_emp where id=1;
3.2 多个变量一次 操作单行 多列
exec sql select id,first_name,salary
into :id,:var_name,:salary
from s_emp where id=1;
3.3 使用结构体操作单行多列
struct{
int id;
char name[30];
double salary;
}emp;
struct emp{
int id;
char name[30];
double salary;
};
typedef struct emp{
int id;
char name[30];
double salary;
}emp;
3.4 结构体数组 可以操作多行 多列
定义一个结构体数组 把s_emp 表中
所有的 id ,first_name,salary
放入数组。再把数组中的所有数据
放入一个提前建立好的表中。
3.5 使用游标 操作多行多列
3.5.1 非滚动游标的使用步骤
定义游标
exec sql declare 游标名 cursor
for select 语句;
打开游标
exec sql open 游标名;
提取数据
exec sql fetch 游标名 into
:宿主变量;
关闭游标
exec sql close 游标名;
3.5.2 例子
把s_emp 表中的id first_name salary
放入一个游标中。然后输出这个游标的
前两条数据。
3.5.3 滚动游标(了解)
scroll 不按照顺序提取数据
fetch last
first
prior 当前行的前一个
next 当前行的后一个
current 当前行
relative n n是正数向后
n是负数向前
absolute n 绝对的第几行
四. 动态sql
在程序运行的过程中 sql语句可以根据
条件发生改变。
4.1 只能是非select语句
不能有占位符号
(执行次数不多)
exec sql execute immediate
:sqlstr;
4.2 只能是非select语句
可以有占位符
"insert into testdsql values(
100,'test100')"
"insert into testdsql values(
101,'test101')"
"insert into testdsql values(
:b0,:b1)"
适合批量数据的处理
exec sql prepare s from :sqlstr;
exec sql execute s using :id,
:name;
4.3 能且只能是select
可以有占位符
"select id,first_name,salary
from s_emp where id>:b0"
动态sql2 和 游标的结合