美文网首页
PLSQL语法及存储过程

PLSQL语法及存储过程

作者: 极客123 | 来源:发表于2020-09-11 10:14 被阅读0次

    pl/sql 的程序结构

      declare  
              说明部分(变量说明,光标申明 , 例外说明 )
      begin 
              语句序列 (DML语句)
      exception
              例外处理语句
       end;
       /
    

    说明部分

       1,定义基本变量
                 类型包括: char,varchar2,date ,number , boolean , long 
                * 举例: 
                             var1     char(15);    定义了一个字符  ,长度是15
                             married    boolean : = true ;    布尔值定义 需要 :=   赋值
                             psal           number(7,2);  定义了一个数字,且有两位小数
       2,   引用型变量
            
                 
    

    --打印一些简单变量并对日期进行简单加减
    declare
    -- Local variables here
    pnumber number(7,2);
    --字符串变量
    pname varchar2(20);
    --日期
    pdate date;
    begin
    -- Test statements here
    pnumber :=1;
    pname:= 'Tom';
    pdate := sysdate;
    dbms_output.put_line(pname);
    dbms_output.put_line(pnumber);
    dbms_output.put_line(pdate+2);
    end;

    关于plsql工具的使用:
    https://www.cnblogs.com/luzhanshi/p/11017780.html

    例子1: 循环打印出表中的数据项(id和name)

    --认识游标(光标/结果集)
    -- cursor   光标名[( 参数名 , 参数类型[,参数名,参数类型])]  is    select  (查询语句)
    /**
       光标的属性:
              1,%found   取到值为true    %notfound  取到值为fale     
    **/
    declare
       --定义一个光标 
       cursor cstaff  is select fname,fid from t_human_staff;
       --为光标定义一个变量来取值用   这里引用表中的类型,通过%来引用
       sta_name t_human_staff.fname%type;
       sta_id t_human_staff.fid%type;
    begin
      --打开光标
      open cstaff;
      --循环loop
      LOOP
      --取一条记录放到定义好的变量中
      fetch cstaff into sta_name,sta_id;
      --思考 1,循环退出条件 2, fetch 不一定取出数据    when循环是在条件值到达某个值时跳出,下面的例子是大于200时跳出
      exit when sta_id > 200;
      dbms_output.put_line(sta_name||'的id是 :'||sta_id);
      --结束循环
      end LOOP;
      --关闭光标
      close cstaff;
    end;
    

    例子2 : 布尔值打印

    -- Created on 2020/9/11 by ADMINISTRATOR 
    declare 
      f boolean :=true;
      sh number :=1000;
    begin
      sh := sys.diutil.bool_to_int(f);
      dbms_output.put_line(sh);
    end;
    

    例子3:结合例子1,打印出游标的布尔属性

    
    declare
       --定义一个光标 
       cursor cstaff  is select fname,fid from t_human_staff;
       --为光标定义一个变量来取值用   这里引用表中的类型,通过%来引用
       sta_name t_human_staff.fname%type;
       sta_id t_human_staff.fid%type;
       flag boolean;
       i number  :=111;
    begin
      --打开光标
      open cstaff;
      --循环loop
      LOOP
      --取一条记录放到定义好的变量中
      fetch cstaff into sta_name,sta_id;
      flag := cstaff%found;
      exit when sta_id > 200;
      --对布尔值打印进行处理后
      i := sys.diutil.bool_to_int(flag);
      dbms_output.put_line('的flag是 :'||i);
      --结束循环
      end LOOP;
      --关闭光标
      close cstaff;
    end;
    

    对于查询数据的时候有可能会造成overflow的异常

    image.png
    因为dbms_output 的默认值是20000

    处理方式1:


    image.png

    处理方式2:


    image.png
    追加一条命令:
    DBMS_OUTPUT.ENABLE (buffer_size=>null);

    表示不限制数据大小

    PLSQL 更新符合某个条件的数据

    /**
       
    */
    declare
       --定义一个光标 
       cursor cstaff  is select fname,fid from t_human_staff;
       --为光标定义一个变量来取值用   这里引用表中的类型,通过%来引用
       sta_name t_human_staff.fname%type;
       sta_id t_human_staff.fid%type;
       flag boolean;
       i number  :=111;
    begin
      --打开光标
      open cstaff;
      --循环loop
      LOOP
      --取一条记录放到定义好的变量中
      fetch cstaff into sta_name,sta_id;
      flag := cstaff%found;
      exit when sta_id > 200  ;
           
      if sta_name = '111' then
           dbms_output.put_line('修改数据行是 :'||sta_id);
           update t_human_staff set fname = '赵爱民' where fid = sta_id;
      else dbms_output.put_line('正常数据:'||sta_name);
      end if;
      
      --DBMS_OUTPUT.ENABLE (buffer_size=>null);
      --结束循环
      end LOOP;
      --关闭光标
      close cstaff;
      commit;
    end;
    

    针对游标的属性笔记

    --光标属性笔记
    declare 
      --定义一个游标  接收select查询语句查出的结果集,并定义两个变量来在plsql中逻辑处理
     cursor cc  is select fname,fid from t_human_staff;
     sta_name t_human_staff.fname%type;
     sta_id t_human_staff.fid%type;
    begin
     --打开光标
     open cc;
     if cc%isopen then dbms_output.put_line('游标是开启的');
     elsif not cc%isopen then dbms_output.put_line('游标是关闭的');
     end if;
     --关闭游标
     close cc; 
     if cc%isopen then dbms_output.put_line('游标是开启1的');
     elsif not cc%isopen then dbms_output.put_line('游标是关闭1的');
     end if;
    end;
    

    %ROWCOUNT
      这个属性记录了游标取过记录的行数,也可以理解为当前游标所在的行数。这个属性在循环的时候十分有效.

    无论是显式游标还是隐式游标都会有四个属性分别是:%ISOPEN、%FOUND、%NOTFOUND、%ROWCOUNT 下

    默认情况下,oracle数据库只允许在一个会话中,打开300个游标

    image.png

    异常处理

    --常见异常处理
    declare 
      --定义一个带参数的光标
     cursor cc(cno number)  is select fname ,fid from t_human_staff where fid=cno;
     sta_name t_human_staff.fname%type;
     sta_id t_human_staff.fid%type;
     num number;
     --自定义异常
     no_data exception;
    begin
       --数据库中没有的数据查询并绑定到定义的属性中  
       --select fname into sta_name from t_human_staff where fe
       --多数据匹配异常
       --select fname into sta_name from t_human_staff t where t.fdepartmentid = 234;
       --被0除异常   
       --num := 2/0;
       --系统例外
       --num := 'abc';
       
       
       --自定义异常
       --打开游标
       open cc(123123);
       fetch cc into sta_name,sta_id;
       if cc%notfound then 
         --抛出异常
         raise no_data;
       end if;
       --关闭游标
       close cc;
     exception
       --未找到结果异常      no_data_found
       when no_data_found then  dbms_output.put_line('没找到数据');
        --多数据匹配异常     too_many_rows
       when too_many_rows then  dbms_output.put_line(' 多数据匹配异常');
       --被0除异常             zero_divide
       when zero_divide then  dbms_output.put_line('被0除异常');
       --系统异常:数据转换
       when value_error then  dbms_output.put_line('数据类型转换异常');  
        --自定义异常
       when no_data then  dbms_output.put_line('自定义异常:无结果');
       when others then dbms_output.put_line('其他异常');
       --系统遇到异常后跳到exception语句后    而close 游标的指令却没有执行,这个时候oracle会自动启动pemon(process monitor)进程   关闭游标,清理垃圾
    end;
    

    针对循环语句 wheil和when 小例子:

    declare
    n number:=0;
    
    nn number:=0;
    begin
    while n<=5 loop
    n:=n+1;
    dbms_output.put_line('n='||n);
    end loop;
    dbms_output.put_line('---------');
    
    loop
      exit when nn>5;
      nn :=nn+1;
      dbms_output.put_line('nn='||nn);
      end loop;
    
    end;
    
    /**
       loop循环  : while   条件为false跳出循环    true继续loop循环     
                    when    条件为true跳出循环     false继续循环
    */
    

    存储过程

    -- 用create  procedure  创建存储过程和存储函数、
    /*
     创建或者替换一个存储过程  
     create [or replace]  procedure   过程名(参数列表)   as  PLSQL子程序体;
     
     as相当于plsql中的 declare
      
    */
    
    create or replace procedure  sayhello
    --说明部分
    as 
    begin 
        dbms_output.put_line('hello plsqls');
    end;
    
    /*
        执行后就创建成功了,可以再plsql工具中的Procedures文件夹下找到
    */
    
    
    /*
       调用存储过程两种方式: 
       1,execute(缩写为: exec)      sayhello();   进行调用,格式为:    exec  函数名 ;  --注意分号结束
       2,在另外的plsql中调用   
                begin
                      --调用存储过程
                      sayhello();
                      sayhello();
                      sayhello();
                  end;
    */
    

    存储函数

    --查询某个员工的年收入
    create or replace function cxempsals(eno in number)
    return number
    as
      --月薪和奖金
      psal   emp.sal%type;
      pcomm  emp.comm%type;
    begin
      select sal,comm into psal,pcomm from emp where empno=eno;
      --返回年收入
      return psal*12+nvl(pcomm,0);
    end;
    /*
    存储过程和函数中输入和输出参数   in 和 out
    一般来讲,存储过程:无返回值
              存储函数:有返回值
              二者都可以通过out 指定返回一个或者多个值
              存储过程本身不可以有返回值,但有了out之后就可以有返回值
    */
    

    java调用 存储过程

    package com.ysu.drgs.proxy.stafftest;
    
    import java.sql.*;
    
    import org.junit.Test;
    
    import oracle.jdbc.driver.OracleTypes;
    import oracle.jdbc.oracore.OracleType;
    
    
    
    
    public class OracleTestProcedure {
        private static String driver = "oracle.jdbc.OracleDriver";
        private static String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        private static String username ="";
        private static String pwd ="";  
        
        /**
         * 获取数据库驱动
         */
        static{
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }   
        }
        
        /**
         * 获取数据库连接
         * @return 
         */
        public static Connection getConn (){
            
            try {
                return DriverManager.getConnection(url, username, pwd);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /**
         * 释放资源
         */
        public static void closeAll(Connection conn , Statement st ,ResultSet rs ){
            if(rs!=null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally{
                    rs=null;
                }
            }
            if(st!=null){
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally{
                    st=null;
                }
            }
            if(conn!= null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally{
                    conn=null;
                }
            }
        }
        /**
         * java调用存储过程
         * @param args
         */
        
        @Test
        public  void test() {
            //Connection conn = getConn();
            //System.out.println(conn == null);
            Connection conn  = null;
            CallableStatement call = null; //访问存储过程
            try {
                //? 占位符        {call 存储过程的名字(?,?,?,?)}
                String sql = "{call cxempinfo(?,?,?,?)}";
                conn = getConn();
                call= conn.prepareCall(sql);
                //对in赋值
                call.setInt(1, 7839);
                //out输出参数需要声明   
                call.registerOutParameter(2, OracleTypes.VARCHAR);
                call.registerOutParameter(3, OracleTypes.NUMBER);
                call.registerOutParameter(4, OracleTypes.VARCHAR);
                //调用存储过程
                call.execute();
                
                String name = call.getString(2);
                double sal = call.getDouble(3);
                String job = call.getString(4);
                System.out.println(name);
                System.out.println(sal);
                System.out.println(job);
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                closeAll(conn, call, null);
            }
        }
        
    }
    
    

    相关文章

      网友评论

          本文标题:PLSQL语法及存储过程

          本文链接:https://www.haomeiwen.com/subject/dmhosktx.html