plsql(二)

一 动态sql:把一个字符串对应sql 当做sql语句来执行
    1.DDL的动态sql
declare
         sqlstr   varchar2(100);
     begin
         sqlstr:=
	'create  table  testdsql(id  number)';
	dbms_output.put_line(sqlstr);
	execute  immediate  sqlstr;
     end

    2.DML 的动态sql
     /*为了解决字符串拼接的问题 使用占位符
       简化拼接 占位符冒号开头 使用using 替代
       占位符号*/
      declare
          var_id    number:=1001;
         var_name  varchar2(30):='test1111';
         sqlstr    varchar2(100);
      begin 
          sqlstr:='insert into testdsql9527 
          values(:b0,:b1)';
          dbms_output.put_line(sqlstr);
          execute  immediate sqlstr using 
          var_id,var_name;
          commit;
     end; 
    3.select  语句的动态sql 
      能且只能返回一个结果
      declare
          sqlstr  varchar2(100);
          var_name  s_emp.first_name%type;
      begin
          sqlstr:='select first_name from s_emp
         where id=1';
         execute immediate sqlstr 
         into var_name;
         dbms_output.put_line(var_name);
      end;
------------------------------------------------
二 游标:用来处理多行数据的一个数据类型
     一条sql语句 可以认为是匿名游标
a.游标的语法
  1.声明游标
    cursor  游标名  is  sql语句;
  2.打开游标
    open    游标名;
  3.提取数据
    非滚动游标  提取数据必须是顺序的
    fetch   游标名  into   变量名;
  4.关闭游标
    close   游标名; 
/*把s_emp 表中所有的数据 放入一个游标中
  输出前两条的 id  first_name salary */
  declare
      cursor  empcursor is select * from s_emp;
      /*根据sql语句定义一个变量*/
      var_emp  empcursor%rowtype;
  begin
      open    empcursor;
      fetch   empcursor into var_emp;
      dbms_output.put_line(var_emp.id||':'||
      var_emp.first_name||':'||var_emp.salary);
      fetch   empcursor into var_emp;
      dbms_output.put_line(var_emp.id||':'||
      var_emp.first_name||':'||var_emp.salary);
      close   empcursor; 
  end;
b.遍历游标中的所有数据
  1.游标的属性
  %found      是否发现新数据
              游标必须处于打开状态 如果没有
     打开游标使用则返回非法游标。
     游标至少被fetch过一次 如果没
     fetch 则返回NULL值。
     发现了新数据 就返回true 
     否则返回false
  %notfound   是否 没有发现新数据
              游标必须处于打开状态 否则是
     非法游标。
     没有fetch 则返回NULL值。
     发现了新数据就返回false
     没有发现新数据就返回true
  %isopen     游标是否打开
              打开就返回true 否则返回false
     打开的游标不能再打开
     关闭的游标不能再关闭
  %rowcount   游标指针偏移量
              
  2.结合notfound属性 和  简单循环遍历游标
    declare
        cursor empcursor is select * from s_emp;
	var_emp empcursor%rowtype;
    begin
        open   empcursor;
        loop
       		fetch  empcursor into var_emp;
/*退出循环的条件是发现不了新数据*/
		exit  when  empcursor%notfound;
		dbms_output.put_line(var_emp.id||':'||
       		 var_emp.first_name||':'||var_emp.salary);
	end loop;
        close  empcursor;
    end;
   3.结合while 循环 和 found属性
    declare
        cursor empcursor is select * from s_emp;
	var_emp empcursor%rowtype;
    begin
        open   empcursor;
	fetch  empcursor into var_emp;
        while  empcursor%found loop
	dbms_output.put_line(var_emp.id||':'||
        var_emp.first_name||':'||var_emp.salary);
	fetch  empcursor into var_emp;
	end loop;
        close  empcursor;
    end;
   4.思考for循环如何遍历上面的游标
     智能循环(自动打开游标 自动提取数据
     自动关闭游标)
    declare
        cursor empcursor is select * from s_emp;
    begin       
        for var_emp in empcursor loop
        dbms_output.put_line(var_emp.id||':'||
        var_emp.first_name||':'||var_emp.salary);
        end loop;      
    end;   
----------------------------------------------
c 带参游标
    1.语法
    cusor  游标名(参数名 参数类型,参数名 
    参数类型)  is  sql语句;
    需要在打开游标时传入实参.
    2.把id>n 所有的员工信息放入一个带参游标中
    /* plsql中的参数不能加任何长度修饰
       但是可以使用%type*/
    declare
        cursor  empcursor(var_id s_emp.id%type)
        is  select * from s_emp where id>var_id;
        var_emp  empcursor%rowtype;
    begin
        /* 打开游标时传入实参 */
        open    empcursor(10);
        loop
        fetch  empcursor into var_emp;
        exit when  empcursor%notfound;
        dbms_output.put_line(var_emp.id||
         ':'||var_emp.salary);
        end loop;
	close   empcursor;
    end;
    3.for 循环可以遍历带参游标
   declare
        cursor  empcursor(var_id s_emp.id%type)
        is  select * from s_emp where id>var_id;
    begin
          for    var_emp in empcursor(15) loop
          dbms_output.put_line(var_emp.id||
          ':'||var_emp.salary);
          end loop;
    end;
-----------------------------------------
d 参考游标  引用游标
ref  cursor
    a.使用步骤
      1.定义参考游标类型
        type  参考游标类型名 is  ref cursor;
      2.使用类型定义变量
        游标名    参考游标类型;
      3.打开参考游标 把游标关联到一个字符串上
        open   游标名  for sql字符串;
    b.把字符串'select * from s_emp' 关联到游标
      declare
          type  empcursortype is ref cursor;
 	empcursor  empcursortype;
 /*定义一个变量接收游标中的数据*/
          var_emp    s_emp%rowtype;
 /*和游标关联的字符串*/
          sqlstr     varchar2(100); 
      begin
          sqlstr:='select * from s_emp';
          /*打开游标时 把游标关联到字符串*/
 	open   empcursor  for sqlstr;
          loop
              fetch  empcursor into var_emp;
   	     exit when empcursor%notfound;
  	     dbms_output.put_line(var_emp.id||
   	     ':'||var_emp.salary);
 	end loop;
 	close  empcursor;
    end;
     c.字符串中 有占位符  :b0
          sqlstr:='select * from s_emp where id>:b0';
          /*打开游标时 把游标关联到字符串*/
 	open   empcursor  for sqlstr using var_id;
三  exception    运行时错误
1.如何使用系统预定义异常
  declare
  begin
  exception
      when  预定义异常名  then
          /*相应的异常处理*/
  end;

常见异常

ACCESS_INTO_NULL

未定义对象
CASE_NOT_FOUND
CASE 中若未包含相应的 WHEN ,并且没有设置 ELSE 时
COLLECTION_IS_NULL
集合元素未初始化
CURSER_ALREADY_OPEN   ####
游标已经打开
DUP_VAL_ON_INDEX      ####
唯一索引对应的列上有重复的值
INVALID_CURSOR       ####    
在不合法的游标上进行操作
INVALID_NUMBER       ####
内嵌的 SQL 语句不能将字符转换为数字
NO_DATA_FOUND        ####
使用 select into 未返回行,或应用索引表未初始化的元素时
TOO_MANY_ROWS       ####   
执行 select into 时,结果集超过一行
ZERO_DIVIDE         ####
除数为 0
SUBSCRIPT_BEYOND_COUNT
元素下标超过嵌套表或 VARRAY 的最大值
SUBSCRIPT_OUTSIDE_LIMIT
使用嵌套表或 VARRAY 时,将下标指定为负数
VALUE_ERROR
赋值时,变量长度不足以容纳实际数据
LOGIN_DENIED
PL/SQL 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码
NOT_LOGGED_ON
PL/SQL 应用程序在没有连接 oralce 数据库的情况下访问数据
PROGRAM_ERROR
PL/SQL 内部问题,可能需要重装数据字典& pl./SQL 系统包
ROWTYPE_MISMATCH
宿主游标变量与 PL/SQL 游标变量的返回类型不兼容
SELF_IS_NULL     ####
使用对象类型时,在 null 对象上调用对象方法
STORAGE_ERROR
运行 PL/SQL 时,超出内存空间
SYS_INVALID_ID
无效的 ROWID 字符串
TIMEOUT_ON_RESOURCE
Oracle 在等待资源时超时

例子:
  declare
      var_name   s_emp.first_name%type;
  begin
      select  first_name into var_name
          from s_emp where id>1;
      dbms_output.put_line('app continue!');
  exception
      when   too_many_rows  then
      dbms_output.put_line('too many emps');
      when   no_data_found  then
      dbms_output.put_line('no found emp id=-1');
  end;
2.用户自定义异常
  1.定义用户异常
    异常变量名   exception;
  2.根据条件 抛出异常
    raise    异常变量名; 
  3.捕获异常
    when    异常变量名  then
  4.处理异常
  declare
      too_many_emps    exception;
  begin
      if  1=1  then
          raise  too_many_emps;
      end if;
  exception    
      when  too_many_emps then
      dbms_output.put_line('user exception');
      /*其它异常 一定是出现在异常处理的最后*/
      when  others    then
      dbms_output.put_line('other exception');
  end;

四 存储过程与函数

a 存储过程

   1.如何建立存储过程

    create  or replace  procedure  
    过程名(参数  参数的类型,参数 参数的类型)
    is
       /*申明区*/
    begin
       /*执行区*/    
    end;
    2.设计一个存储过程 传入一个整数参数
      根据参数 从1 输出到 这个参数的值
    create   or  replace  procedure 
    getnumn(var_n in number)
    is
    begin
        for var_i in 1..var_n  loop
   dbms_output.put_line(var_i);
end loop;
    end;
    3.查看存储过程 准备调用
    desc  存储过程名;
    desc   getnumn;
    ---------------- ------- ------     --------
     VAR_N           NUMBER    IN  
    参数名字        参数的类型 参数的模式  参数的缺省值
    参数的模式
    in    负责给存储过程传入值 默认的模式
    out   负责给存储过程传出值 
    in out 即负责传入值 又负责传出值
   4.调用存储过程
     call   getnumn(5);
     exec   getnumn(5);
     /*在匿名块或者有名块中调用存储过程*/
     begin
         getnumn(5);
     end;

5 查看过程源码 select text from user_source where name='GETMAX'; --名字要大写

b  函数

函数 和 存储过程的区别
1.关键字不同  procedure      function
2.函数有返回值类型  和 返回值
3.存储过程可以直接在plsql中调用
  函数必须组成表达式才能调用
--设计一个函数  传入两个整数参数 返回最大值
create  or replace function getmaxfun
(x in number,y in number)return  number   
is
begin
    if  x<y  then
        return  y;
    end if;
        return  x;
end;
查看函数
desc  getmaxfun;
使用函数
select getmaxfun(1,2) from dual;
或者
declare
    var_res   number;
begin
    var_res:=getmaxfun(1,10086);
    dbms_output.put_line(var_res);
end;
参数的默认值
    create  or  replace  function  printNum(var_n
    in  number:=10)return  number 
    is 
    begin
        return  var_n;
    end;

    select  printNum()  from dual;
    select  printNum(90)  from dual;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值