一 proc 中如何调用存储过程 和 函数
1.如何调用存储过程
exec sql execute
begin
/*相当于匿名块*/
end;
end-exec;
建立一个存储过程 传入两个整数参数 然后把两个
整数参数的和放入第二个参数中。
create or replace procedure getsum(var_x number,
var_y in out number)
is
begin
var_y:=var_x+var_y;
end;
/*预编译 带过程调用的proc 代码*/
proc callprocedure.pc sqlcheck=semantics
是否存在 和 合法
2.写一个函数 传入两个整数参数 返回两个整数参数
的最大值 并且把两个参数的和 放入第二个参数中
写一个proc代码验证 函数的功能要求两个参数必须使用
宿主变量。
create or replace function getmaxandsum(
var_x number,var_y in out number)return number
is
var_temp number;
begin
var_temp:=var_y;
var_y:=var_x+var_y;
if var_x<var_temp then
return var_temp;
end if;
return var_x;
end;
二 proc 中的错误处理
exec sql whenever 条件 动作;
条件:sqlerror notfound sqlwarning
动作: do 函数();
do break;
continue;
stop;
goto 标签;
写一个proc程序 查询s_emp 表中 id=-1的first_name
如果程序出错 写一个错误处理得当出错的原因
可以使用 exec sql whenever sqlerror|notfound|sqlwarning
do 函数()|do break|continue|stop|goto 标签;
三 proc 中的数据操作
1.使用单个变量操作单行单列
exec sql select first_name into :var_name
from s_emp where id=1;
2.使用多个变量 操作 单行 多列
exec sql select first_name,salary into
:var_name,:var_salary
from s_emp where id=1;
3.使用结构体操作 单行 多列
4.数组可以操作单列 多行结构体数组 可以操作 多行 多列
把s_emp 表中id first_name salary
放入一个结构体数组中
5.游标 操作多行 多列
a.游标的使用步骤
1.定义游标
exec sql declare 游标名 cursor for sql语句;
2.打开游标
exec sql open 游标名;
3.提取数据
exec sql fetch 游标名 into :变量;
4.关闭游标
exec sql close 游标名;
写一个proc程序 把s_emp 表中的 id first_name
salary 放入一个游标中 提取前两条数据。
b.遍历游标 需要结合异常处理
1. exec sql whenever notfound do break;
while(1){
循环提取数据
c.滚动游标--------可以做到非顺序取数据
scroll
last
first
prior 当前行的前一行
next 当前行的后一行
current 当前行
relative n(+-) 相对的第几个
absolute n 绝对的第几行
四 动态sql:把一个字符串对应的sql语句当做真正sql来执行
a.只能是非select语句
不能有占位符号
exec sql insert into testdsql values(1,'test1');
exec sql insert into testdsql values(2,'test2');
适合执行次数不是很多的情况
exec sql execute immediate :sqlstr;
b.可以有占位符号
不能是select语句
char sqlstr[100]=
"insert into testdsql values(:b0,:b1)";
预处理
exec sql prepare s from :sqlstr;
exec sql execute s using :变量,:变量;
c.只能是select
可以有占位符
游标 + 动态sql2 结合 (参考游标 引用游标)
exec sql prepare s from :sqlstr;
/* 把游标关联到s上 */
exec sql declare 游标名 cursor for s;
/* 在打开游标时传入实参 */
exec sql open 游标名 using :宿主变量;
五 sql中三范式
第一范式:表中字段不可再分
第二范式:表中的所有非主属性必须完全依赖主属性。
表中的每条记录可以被唯一区分。
第三范式:在第二范式的基础上消除了传递依赖。
1.如何调用存储过程
exec sql execute
begin
/*相当于匿名块*/
end;
end-exec;
建立一个存储过程 传入两个整数参数 然后把两个
整数参数的和放入第二个参数中。
create or replace procedure getsum(var_x number,
var_y in out number)
is
begin
var_y:=var_x+var_y;
end;
/*预编译 带过程调用的proc 代码*/
proc callprocedure.pc sqlcheck=semantics
userid=openlab/open123
如果在PC源程序中内嵌了PL/SQL块, SQLCHECK应该SEMANTICS或是 FULL
当SQLCHECK的值是SEMANTICS或是 FULL时,必须设置USERID
是否存在 和 合法
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 为存储过程传参 */
int x=21;
int y=72;
exec sql end declare section;
exec sql connect:userpasswd;
/* 准备调用存储过程 */
exec sql execute
begin
getsum(:x,:y);
end;
end-exec;
printf("y=%d\n",y);
exec sql commit work release;
}
2.写一个函数 传入两个整数参数 返回两个整数参数
的最大值 并且把两个参数的和 放入第二个参数中
写一个proc代码验证 函数的功能要求两个参数必须使用
宿主变量。
create or replace function getmaxandsum(
var_x number,var_y in out number)return number
is
var_temp number;
begin
var_temp:=var_y;
var_y:=var_x+var_y;
if var_x<var_temp then
return var_temp;
end if;
return var_x;
end;
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 为函数传参 */
int x=21;
int y=75;
int res=0;
exec sql end declare section;
exec sql connect:userpasswd;
/* 准备调用函数 */
exec sql execute
begin
:res:=getmaxandsum(:x,:y);
end;
end-exec;
printf("y=%d\n",y);
printf("res=%d\n",res);
exec sql commit work release;
}
二 proc 中的错误处理
exec sql whenever 条件 动作;
条件:sqlerror notfound sqlwarning
动作: do 函数();
do break;
continue;
stop;
goto 标签;
写一个proc程序 查询s_emp 表中 id=-1的first_name
如果程序出错 写一个错误处理得当出错的原因
#include <stdio.h>
exec sql include sqlca;
void processNotFound(){
exec sql whenever notfound continue;
printf("no found emp\n");
}
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
char var_name[30];
exec sql end declare section;
exec sql connect:userpasswd;
/*错误处理*/
exec sql whenever notfound do
processNotFound();
exec sql select first_name into :var_name
from s_emp where id=-1;
exec sql commit work release;
}
可以使用 exec sql whenever sqlerror|notfound|sqlwarning
do 函数()|do break|continue|stop|goto 标签;
三 proc 中的数据操作
1.使用单个变量操作单行单列
exec sql select first_name into :var_name
from s_emp where id=1;
2.使用多个变量 操作 单行 多列
exec sql select first_name,salary into
:var_name,:var_salary
from s_emp where id=1;
3.使用结构体操作 单行 多列
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 结构体的定义推荐放入申明区
struct{
int id;
char name[30];
double salary;
}emp; */
struct emp{
int id;
char name[30];
double salary;
};
struct emp emp;
exec sql end declare section;
exec sql connect:userpasswd;
exec sql select id,first_name,salary
into :emp from s_emp where id=1;
printf("%d:%s:%lf\n",emp.id,emp.name,
emp.salary);
exec sql commit work release;
}
4.数组可以操作单列 多行结构体数组 可以操作 多行 多列
把s_emp 表中id first_name salary
放入一个结构体数组中
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 结构体的定义推荐放入申明区 */
struct emp{
int id;
char name[30];
double salary;
};
/* 使用结构体定义数组 */
struct emp datas[50];
exec sql end declare section;
exec sql connect:userpasswd;
/* 建立一张表 */
exec sql create table testemparr(
id number primary key,
name varchar2(30),
salary number);
if(sqlca.sqlcode!=0){
printf("%s\n",sqlca.sqlerrm.sqlerrmc);
}
exec sql select id,first_name,salary
into :datas from s_emp;
int i=0;
int loopcount=sqlca.sqlerrd[2];
for(i=0;i<loopcount;i++){
exec sql insert into testemparr
values(:datas[i]);
}
exec sql commit;
exec sql commit work release;
}
5.游标 操作多行 多列
a.游标的使用步骤
1.定义游标
exec sql declare 游标名 cursor for sql语句;
2.打开游标
exec sql open 游标名;
3.提取数据
exec sql fetch 游标名 into :变量;
4.关闭游标
exec sql close 游标名;
写一个proc程序 把s_emp 表中的 id first_name
salary 放入一个游标中 提取前两条数据。
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 接收游标中数据的结构变量 */
struct{
int id;
char name[30];
double salary;
}emp;
exec sql end declare section;
exec sql connect:userpasswd;
exec sql declare empcursor cursor for
select id,first_name,salary from s_emp;
exec sql open empcursor;
exec sql fetch empcursor into :emp;
printf("%d:%s:%lf\n",emp.id,emp.name,
emp.salary);
exec sql fetch empcursor into :emp;
printf("%d:%s:%lf\n",emp.id,emp.name,
emp.salary);
exec sql close empcursor;
exec sql commit work release;
}
b.遍历游标 需要结合异常处理
1. exec sql whenever notfound do break;
while(1){
循环提取数据
}
2.使用智能for循环
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 接收游标中数据的结构变量 */
struct{
int id;
char name[30];
double salary;
}emp;
exec sql end declare section;
exec sql connect:userpasswd;
exec sql declare empcursor cursor for
select id,first_name,salary from s_emp;
exec sql open empcursor;
exec sql whenever notfound do break;
for(;;){
exec sql fetch empcursor into :emp;
printf("%d:%s:%lf\n",emp.id,emp.name,
emp.salary);
}
exec sql close empcursor;
exec sql commit work release;
}
c.滚动游标--------可以做到非顺序取数据
scroll
last
first
prior 当前行的前一行
next 当前行的后一行
current 当前行
relative n(+-) 相对的第几个
absolute n 绝对的第几行
#include <stdio.h>
exec sql include sqlca;
int main(){
exec sql begin declare section;
char userpasswd[30]="openlab/open123";
/* 接收游标中数据的结构变量 */
struct{
int id;
char name[30];
double salary;
}emp;
exec sql end declare section;
exec sql connect:userpasswd;
exec sql declare empcursor scroll cursor
for select id,first_name,salary from s_emp;
exec sql open empcursor;
exec sql fetch last empcursor into :emp;
printf("%d:%s:%lf\n",emp.id,emp.name,emp.salary);
exec sql fetch first empcursor into :emp;
printf("%d:%s:%lf\n",emp.id,emp.name,emp.salary);
exec sql close empcursor;
exec sql commit work release;
}
四 动态sql:把一个字符串对应的sql语句当做真正sql来执行
a.只能是非select语句
不能有占位符号
exec sql insert into testdsql values(1,'test1');
exec sql insert into testdsql values(2,'test2');
适合执行次数不是很多的情况
exec sql execute immediate :sqlstr;
b.可以有占位符号
不能是select语句
char sqlstr[100]=
"insert into testdsql values(:b0,:b1)";
预处理
exec sql prepare s from :sqlstr;
exec sql execute s using :变量,:变量;
c.只能是select
可以有占位符
游标 + 动态sql2 结合 (参考游标 引用游标)
exec sql prepare s from :sqlstr;
/* 把游标关联到s上 */
exec sql declare 游标名 cursor for s;
/* 在打开游标时传入实参 */
exec sql open 游标名 using :宿主变量;
五 sql中三范式
第一范式:表中字段不可再分
第二范式:表中的所有非主属性必须完全依赖主属性。
表中的每条记录可以被唯一区分。
第三范式:在第二范式的基础上消除了传递依赖。