PLSQL语法及存储过程

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的异常

PLSQL语法及存储过程_第1张图片
image.png
因为dbms_output 的默认值是20000

处理方式1:


PLSQL语法及存储过程_第2张图片
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个游标

PLSQL语法及存储过程_第3张图片
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语法及存储过程)