Oracle的plsql 函数、存储过程

本文深入探讨了SQL中存储函数和过程的定义、声明、使用及执行方式,包括参数传递、返回类型、异常处理等内容,并通过具体示例展示了如何创建、调用以及优化存储函数与过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



---存储函数


--格式
--函数的声明(有参数的写在小括号里)
create or replace function func_name(v_param varchar2)
--返回值类型
return varchar2
is 
--PL/SQL块变量、记录类型、游标的声明(类似于前面的declare的部分)
begin
--函数体(可以实现增删改查等操作,返回值需要return)
       return 'helloworld'|| v_logo;
end;


create or replace fun_name(dept_id number,salary number)
return number
is
       --函数使用过程中,需要声明的变量,记录类型、cursor
begin
  --函数的执行体
exception
  --处理函数执行过程的异常 
end;


---函数的 helloworld: 返回一个 "helloworld" 的字符串
create or replace function hello_func
return varchar2
is
begin
       return 'helloworld';
end;


--执行函数


begin
    dbms_output.put_line(hello_func());
end;


或者: select hello_func() from dual;


---返回一个"helloworld: atguigu"的字符串,其中atguigu 由执行函数时输入。
--返回一个"helloworld: atguigu"的字符串,其中atguigu 由执行函数时输入。
--函数的声明(有参数的写在小括号里)
create or replace function hello_func(v_logo varchar2)
--返回值类型
return varchar2
is 
--PL/SQL块变量的声明
begin
--函数体
       return 'helloworld'|| v_logo;
end;


---执行函数
begin
    dbms_output.put_line(hello_func('weisg'));
end;


--或者
select hello_func('weisg') from dual;


---创建一个存储函数,返回当前的系统时间
create or replace function func1
return date
is
--定义变量
v_date date;
begin
  --函数体
  --v_date := sysdate;
       select sysdate into v_date from dual;
       dbms_output.put_line('我是函数哦');---如果这句不打印,得先把服务打开即先执行set serveroutput on;
       
       return v_date;
end;
--或者




create or replace function func1
return date
is
--定义变量
v_date date;
begin
  --函数体
  v_date := sysdate;
       --select sysdate into v_date from dual;
       --dbms_output.put_line('我是函数哦');
       
       return v_date;
end;


---定义带参数的函数: 两个数相加
create or replace function add_func(a number, b number)
return number
is
begin
       return (a + b);
end;


--执行
select add_func(12,35) from dual;


begin
    dbms_output.put_line(add_func(12, 13));
end;


----定义一个函数: 获取给定部门的工资总和, 要求:部门号定义为参数, 工资总额定义为返回值
create or replace function sum_sal(dept_id number)
       return number
       is
       
       cursor sal_cursor is select salary from employees where department_id = dept_id;
       v_sum_sal number(8) := 0;   
begin
       for c in sal_cursor loop
           v_sum_sal := v_sum_sal + c.salary;
       end loop;       


       --dbms_output.put_line('sum salary: ' || v_sum_sal);
       return v_sum_sal;
end;


---执行函数


begin
    dbms_output.put_line(sum_sal(80));
end;


---关于 OUT 型的参数: 因为函数只能有一个返回值, PL/SQL 程序可以通过 OUT 型的参数实现有多个返回值
--要求: 定义一个函数: 获取给定部门的工资总和 和 该部门的员工总数(定义为 OUT 类型的参数).
--要求: 部门号定义为参数, 工资总额定义为返回值.
--in不写默认就是in


create or replace function sum_sal(dept_id number, total_count out number)
       return number
       is
       
       cursor sal_cursor is select salary from employees where department_id = dept_id;
       v_sum_sal number(8) := 0;   
begin
       total_count := 0;


       for c in sal_cursor loop
           v_sum_sal := v_sum_sal + c.salary;
           total_count := total_count + 1;
       end loop;       


       --dbms_output.put_line('sum salary: ' || v_sum_sal);
       return v_sum_sal;
end;


---执行函数
declare 
  v_total number(3) := 0;


begin
    dbms_output.put_line(sum_sal(80, v_total));
    dbms_output.put_line(v_total);
end;




-------------------------------------------------------------------------------------------
----存储过程




---定义一个存储过程: 获取给定部门的工资总和(通过 out 参数), 要求:部门号和工资总额定义为参数
create or replace procedure sum_sal_procedure(dept_id number, v_sum_sal out number)
       is
       
       cursor sal_cursor is select salary from employees where department_id = dept_id;
begin
       v_sum_sal := 0;
       
       for c in sal_cursor loop
           --dbms_output.put_line(c.salary);
           v_sum_sal := v_sum_sal + c.salary;
       end loop;       


       dbms_output.put_line('sum salary: ' || v_sum_sal);
end;
---执行
declare 
     v_sum_sal number(10) := 0;
begin
     sum_sal_procedure(80,v_sum_sal);
end;
/*
自定义一个存储过程完成以下操作: 
对给定部门(作为输入参数)的员工进行加薪操作, 若其到公司的时间在 (? , 95) 期间,    为其加薪 %5
                                                               [95 , 98)             %3       
                                                               [98, ?)               %1
得到以下返回结果: 为此次加薪公司每月需要额外付出多少成本(定义一个 OUT 型的输出参数).
*/


create or replace procedure add_sal_procedure(dept_id number, temp out number)


is


       cursor sal_cursor is select employee_id id, hire_date hd, salary sal from employees where department_id = dept_id;
       a number(4, 2) := 0;
begin
       temp := 0;       


       for c in sal_cursor loop
           a := 0;    
       
           if c.hd < to_date('1995-1-1', 'yyyy-mm-dd') then
              a := 0.05;
           elsif c.hd < to_date('1998-1-1', 'yyyy-mm-dd') then
              a := 0.03;
           else
              a := 0.01;
           end if;
           
           temp := temp + c.sal * a;
           update employees set salary = salary * (1 + a) where employee_id = c.id;
       end loop;       
end;


create or replace function sum_user_age_like_name(username varchar2)
return number  --返回值类型
is
   cursor age_cursor is select age from mytable where user_id like '%'||username||'%';
   v_age_sum number := 0;--定义返回值并初始化
begin
  for a in age_cursor loop --for循环里存放的是记录对象,必须要通过对象去获取记录里对应的值
    v_age_sum := v_age_sum + a.age;
    dbms_output.put_line('age:'||a.age);
  end loop;--结束循环体
  return v_age_sum;--返回对应值
end;


-----

----存储过程
create or replace procedure sum_user_age_like_name_proce(username varchar2,v_age_sum out number)

is
   cursor age_cursor is select age from mytable where user_id like '%'||username||'%';
   
begin
  v_age_sum := 0;
  for a in age_cursor loop --for循环里存放的是记录对象,必须要通过对象去获取记录里对应的值
    v_age_sum := v_age_sum + a.age;
  end loop;--结束循环体
  dbms_output.put_line('sum age: ' || v_age_sum);
end;


---执行体

declare
  v_age_sum number := 0;
begin
  sum_user_age_like_name_proce('user_id',v_age_sum);
end;


package com.procedure;


import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Types;


import oracle.jdbc.OracleTypes;


import com.reflect.utils.DBUtils;


public class CallProcedure {
private static Connection conn = null; // 数据库连接对象  
    private static CallableStatement cs = null;// 存储过程执行对象  
    private static ResultSet rs = null;// 结果集对象 
public CallProcedure(){
conn = DBUtils.getConnect();
}

/** 
     *  
     *  @Discription 执行有参数,无返回值的存储过程 
     *  @return         void 
     *  @param conn 
     *  @throws Exception 
     */ 
/**
* --有参数无返回值 

* create or replace procedure update_mytable_name(v_user_id varchar2,username varchar2)
is
begin
 update mytable m set m.name=username where m.user_id=v_user_id;
end;
---plsql命令执行体
declare 
 v_user_id varchar2(32) := 'user_id_4';
 username varchar2(32) := 'weisg81';
begin
 dbms_output.put_line('存储过程开始执行。。。');
 update mytable m set m.name=username where m.user_id=v_user_id;
end;

*/
public void CallProcedure2(Connection conn){
try{
//指定调用的存储过程  
       cs = conn.prepareCall("{call update_mytable_name(?,?)}");  
       cs.setString(1, "user_id_4");//设置存储过程对应的输入参数  
       cs.setString(2, "weisg234");//对应下标从1 开始  
       //执行存储过程调用  
       cs.execute();
       System.out.println("调用CallProcedure(Connection conn)成功");
}catch(Exception e){
e.printStackTrace();
}
}
/** 
     *  
     *  @Discription 执行无参数,无返回值的存储过程 
     *  @return         void 
     *  @param conn 
     * @throws Exception  
     */
/**
* create or replace procedure insertMytableLine 
   as 
   begin 
         insert into mytable values('weisg','张三','test','管理员',34,23); 
   end;
*/
public void callProcedure(Connection conn) throws Exception  
    {  
        //指定调用的存储过程  
        cs = conn.prepareCall("{call insertMytableLine}");  
        //执行存储过程的调用  
        cs.execute();
        System.out.println("调用callProcedure(Connection conn)成功。。。");
    }


/** 
     *  
     *  @Discription 执行有参数,有返回值的存储过程 
     *  @return         void 
     *  @param conn 
     * @throws Exception  
     */ 
/**
* create or replace procedure deleteLine(v_user_id in varchar2,getCount out number) 
as 
begin 
      delete from mytable m where m.user_id = v_user_id; 
      select count(*) into getCount from mytable; 
end; 
*/
public void callProcedureYY(Connection conn) throws Exception  
    {  
        //指定调用的存储过程  
        cs = conn.prepareCall("{call deleteLine(?,?)}");  
        //设置参数  
        cs.setString(1, "user_id_8");  
        //这里需要配置OUT的参数新型  
        cs.registerOutParameter(2, OracleTypes.NUMBER);  
        //执行调用  
        cs.execute();  
        //输入返回值  
        System.out.println(cs.getString(2));  
    }

/** 
     *  
     *  @Discription 执行有参数,返回集合的存储过程 
     *  @return         void 
     *  @param conn 
     * @throws Exception  
     */

/**
* create or replace package someUtils 
as 
    type cur_ref is ref cursor; 
    procedure selectRows(cur_ref out someUtils.cur_ref); 
end someUtils; 
          
create or replace package body someUtils 
as  
  procedure selectRows(cur_ref out someUtils.cur_ref) 
    as 
      begin 
            open cur_ref for select * from mytable e; 
      end selectRows; 
end someUtils;
*/
public void callProcedureYYL(Connection conn) throws Exception  
    {  
        //执行调用的存储过程  
        cs = conn.prepareCall("{call someUtils.selectRows(?)}");  
        //设置返回参数  
        cs.registerOutParameter(1, OracleTypes.CURSOR);  
        //执行调用  
        cs.execute();  
        // 获取结果集 结果集是一个Object类型,需要进行强制转换 rs = (ResultSet)  
        rs = (ResultSet) cs.getObject(1);  
        //输出返回值  
        while(rs.next())  
        {  
            System.out.println(rs.getInt(1)+"\t"+rs.getString(2));  
        }  
    }

/** 
     *  
     *  @Discription 执行有参数,无返回值的存储过程 
     *  @return         void 
     *  @param conn 
     *  @throws Exception 
     */  
public void callProcedureY(Connection conn) throws Exception  
    {  
        //指定调用的存储过程  
        cs = conn.prepareCall("{call updateName(?,?)}");  
        cs.setInt(1, 7499);//设置存储过程对应的输入参数  
        cs.setString(2, "www");//对应下标从1 开始  
        //执行存储过程调用  
        cs.execute();  
    }  

/** 
     *  
     *  @Discription 执行有参数的函数 
     *  @return         void 
     *  @param conn 
     *  @throws Exception  
     */  
public void callProcedureFY(Connection conn) throws Exception  
    {  
        //指定调用的函数  
        cs = conn.prepareCall("{? = call useOther(?)}");  
        //配置OUT参数信息  
        cs.registerOutParameter(1, OracleTypes.CHAR);  
        //配置输入参数  
        cs.setInt(2, 1111);  
        //执行过程调用  
        cs.execute();  
        //输入返回值  
        System.out.println(cs.getString(1));  
    }  

public static void main(String[] args) {  
        CallProcedure cp = new CallProcedure();  
        try {  
            //开启事务管理  
            conn.setAutoCommit(true);
            //cp.CallProcedure2(conn);
            //cp.callProcedure(conn);  
            //cp.callProcedureY(conn);  
            //cp.callProcedureFY(conn);  
            cp.callProcedureYY(conn);  
            //cp.callProcedureYYL(conn);  
            conn.commit();  
        } catch (Exception e) {  
            e.printStackTrace();  
            try {  
                conn.rollback();  
            } catch (Exception e1) {  
                // TODO Auto-generated catch block  
                e1.printStackTrace();  
            }  
            // TODO: handle exception  
        }finally  
        {  
            DBUtils.closeConn(null, null, conn);  
        }  
    } 

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值