proc/c++(三)

一 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 

    userid=openlab/open123

 如果在PC源程序中内嵌了PL/SQL块, SQLCHECK应该SEMANTICS或是 FULL
 当SQLCHECK的值是SEMANTICS或是 FULL时,必须设置USERID

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中三范式
第一范式:表中字段不可再分
    
第二范式:表中的所有非主属性必须完全依赖主属性。
         表中的每条记录可以被唯一区分。
第三范式:在第二范式的基础上消除了传递依赖。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值