5.3.1 PROC

PROC

Day01

一.什么是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 获得。

​ 要注意垃圾数据的问题。

img.png)img

​ 给变长字符串数组 进行初始化

​ varchar var_name[30]={0};

​ var_name.arr[var_name.len]=’\0’;

img.png)img

七.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

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 赋值状态。

img.png)img

十一.sqlca 通信区

​ sqlca 通信区 本质上就是一个结构体

​ 每执行一次sql 都会把sqlca中的字段

​ 更新一遍。所以得到一条sql语句的状态

​ 要执行完sql时立即判断。否则会被下一次

​ sql覆盖掉。

​ sqlca.sqlerrd[2] 最近一次sql语句影响的行数

​ sqlca.sqlcode 得到sql语句执行状态

​ ==0 执行正常

​ >0 sql执行出错

​ <0 数据库本身出错 或者网络错误

​ sqlca.sqlerrm.sqlerrmc sql出错的消息内容

img.png)img

​ dev-cpp

​ bin/gcc g++

​ desc user_triggers;

Day02

一.数据库的连接:

本地连接

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)

​ )

)

img.png)img

第二种远程数据库连接方式:

database link

img.png)img

create database link 链接名

​ connect to 用户名 identified by

​ 密码 using ‘数据库描述’;

img.png)img

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)

)

)’;

img.png)img

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;

两种远程数据库连接:

img.png)img

$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语句的执行结果判断,会

先进行全局处理 后进行局部处理。

img.png)img

三.数据的操作

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

放入数组。再把数组中的所有数据

放入一个提前建立好的表中。

img.png)img

3.5 使用游标 操作多行多列

​ 3.5.1 非滚动游标的使用步骤

​ 定义游标

​ exec sql declare 游标名 cursor

​ for select 语句;

​ 打开游标

​ exec sql open 游标名;

​ 提取数据

​ exec sql fetch 游标名 into

​ :宿主变量;

​ 关闭游标

​ exec sql close 游标名;

​ 3.5.2 例子

img.png)img

​ 把s_emp 表中的id first_name salary

​ 放入一个游标中。然后输出这个游标的

​ 前两条数据。

img.png)img

​ 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;

img.png)img

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;

img.png)img

4.3 能且只能是select

​ 可以有占位符

​ “select id,first_name,salary

​ from s_emp where id>:b0”

​ 动态sql2 和 游标的结合

img.png)img


打赏

微信支付 支付宝支付

License

本作品由Simonhttp://www.uusystem.com)创作,采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。 欢迎转载,但任何转载必须保留完整文章,在显要地方显示此声明以及原文链接。如您有任何疑问或者授权方面的协商,请邮件:postmaster@uusystem.com。