Oracle11g学习-存储过程/存储函数

Oracle

1  存储过程与存储函数

1.1      存储过程

        存储过程是命名的pl/sql程序块,封装数据业务操作,具有模块化、可重用、可维护、更安全特点;并且可以被程序调用。一般有4类型的存储过程,分别为不带参数、带输入参数、带输出参数、带输入输出参数。

1.1.1  语法

【语法】

         CREATE [OR REPLACE] PROCEDURE <过程名>[(参数列表)] 

        IS|AS

         [局部变量声明]

         BEGIN

            可执行语句

        [EXCEPTION  异常处理语句]

         END [<过程名>];

 

OR REPLACE:如果系统已存在该存储过程,将被替换

参数列表:参数不需要声明长度,可选

参数变量的类型:in 为默认类型,表示输入; out 表示只输出;in out 表示即输入又输出;

 

 

【调用方式】

在PL/SQL块中直接使用过程名;

在PL/SQL程序外使用 exec[ute] <过程名>[(参数列表)];

1.1.2  无参存储过程

 -- 授予itcast创建存储过程的权限

grant create procedure to czy;

 

/*

使用无参存储过程,注意无参存储过程创建时不能使用()

*/

 

create or replace procedure pro_helloWorld

as

begin

 dbms_output.put_line('Hello World.');

end;

 

-- 方式一:调用存储过程,可加可不加()

begin

pro_helloWorld;

end;

 

-- 方式二:调用存储过程,可加可不加()

exec pro_helloWorld;

1.1.3  有输入参数存储过程

/*

使用有输入参存储过程

*/

createorreplaceprocedure pro_add_emp(

       p_empno in emp.empno%type,

       p_ename in varchar2,

       p_sal in number

)

as

begin

--将输入参数对应的数据插入emp

insert into emp(empno, ename,salvalues(p_empno, p_ename, p_sal);

end;

/

 

-- 调用存储过程,向emp表插入新数据

begin

 pro_add_emp(2001,'itcast2001',3000);

 pro_add_emp(2002,'itcast2002',2000);

 pro_add_emp(2003,'itcast2003',4000);

end;

1.1.4  有输出参数的存储过程

/*

使用有输出参存储过程,计算1到10的总和并通过参数返回

*/

create or replace procedure pro_1to10_sum(

       p_sum out number

)

as

 tem_sum number(4):=0;

begin

for i in1..10

loop

  tem_sum := tem_sum + i;

end loop;

 p_sum := tem_sum;

end;

/

 

-- 调用存储过程

declare

 p_sum number(4);

begin

 pro_1to10_sum(p_sum);

 dbms_output.put_line('1至10的和为:'|| p_sum);

end;

1.1.5  有输入输出参数存储过程

/*

使用有输入、输出参存储过程;根据empno查询该员工号对应的员工的姓名和工资

*/

create or replace procedure pro_query_enameAndSal_by_empno(

       s_empno in  emp.empno%type,

       s_ename out emp.ename%type,

       s_sal out emp.sal%type

)

as

begin

     select ename,sal into s_ename, s_sal from emp where empno= s_empno;

end;

/

 

-- 调用存储过程

declare

 p_ename emp.ename%type;

 p_sal emp.sal%type;

begin

--pro_query_enameAndSal_by_empno(7369, p_ename, p_sal);

 pro_query_enameAndSal_by_empno(7369, s_sal => p_sal, s_ename => p_ename);

 dbms_output.put_line('员工号为7369的员工名称为:'|| p_ename||',其工资为:'|| p_sal);

end;

1.1.6  程序中调用存储过程

package connect;

 

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

 

import oracle.jdbc.OracleTypes;

 

publicclass TestProcedure {

 

   publicstaticvoid main(String[] args) {

      Connection conn = null;

      CallableStatement call = null;

      try {

         Class.forName("oracle.jdbc.OracleDriver");

         String url = "jdbc:oracle:thin:@localhost:1521:orcl";

         conn = DriverManager.getConnection(url, "czy", "orcl");

         call = conn.prepareCall("{call pro_query_enameAndSal_by_empno(?,?,?)}");

         //设置输入型参数

         call.setInt(1, 7369);

         //注册输出型参数

         call.registerOutParameter(2, OracleTypes.VARCHAR);

         call.registerOutParameter(3, OracleTypes.NUMBER);

         //调用存储过程

         call.execute();

         //获取返回值

         String ename = call.getString(2);//员工名称

         double sal = call.getDouble(3);//员工工资

         System.out.println("员工号为7369的员工名称为:" + ename + ",工资为:" + sal);

      } catch (Exception e) {

         e.printStackTrace();

      } finally {

         try {

            if(call != null){

                call.close();

            }

            if(conn != null){

                conn.close();

            }

         } catch (SQLException e) {

            e.printStackTrace();

         }

      }

   }

 

}

1.1.7  删除存储过程

【语法】

DROP PROCEDURE <过程名>;

 

【示例】

drop procedure pro_1to10_sum;

1.2  存储函数

        存储函数与过程不同的是,存储函数有return语句;一般情况下如果在需要一个返回值时可使用存储函数

1.2.1  语法

CREATE [OR REPLACE] FUNCTION <函数名>[(参数列表)] RETURN 数据类型 IS|AS

         [局部变量声明]

         BEGIN

            可执行语句

          [EXCEPTION

            异常处理语句]

         RETURN 返回值;

         END [<函数名>];


变量的类型:in 为默认类型,表示输入; out 表示只输出;in out 表示即输入又输出;

 

【使用方式】

直接在select中使用和其它系统函数使用方式一样;

在PL/SQL块中调用使用;

1.2.2  无参存储函数

/*

使用无参存储函数;注意创建时函数名称不能使用()

但是在调用时候可加可不加()

*/

create or replace function fun_helloWorld

return varchar2

as

begin

return 'Hello World';

end;

/

 

-- 方式1:调用存储函数

select fun_helloWorld() from dual;

 

-- 方式2:调用存储函数

declare

str varchar2(20);

begin

 str :=fun_helloWorld;

 dbms_output.put_line(str);

end;

 

1.2.3  有输入参数的存储函数

/*

使用存储函数:根据员工号,查询并返回该员工的年薪

*/

create or replace function fun_get_annualSal_by_empno(p_empno emp.empno%type)

return number

as

p_sal emp.sal%type;

p_comm emp.comm%type;

begin

select sal,comm into p_sal, p_comm from emp where empno=p_empno;

return12*p_sal +nvl(p_comm,0);

end;

/

 

-- 调用存储函数

select fun_get_annualSal_by_empno(7369)from dual;

1.2.4  有输入输出参数存储函数

/*

使用具有输入输出参数的存储函数:根据员工号,查询并返回该员工的年薪,姓名,奖金

*/

createorreplacefunction fun_get_annualSal_by_empno2(

p_empno emp.empno%type,

p_ename out emp.ename%type,

p_comm out emp.comm%type

)

returnnumber

as

p_sal emp.sal%type;

begin

select ename,sal,nvl(comm,0)into p_ename,p_sal, p_comm from emp where empno=p_empno;

return12*p_sal + p_comm;

end;

/

 

-- 调用存储函数

declare

p_annualSal number(10,2);

p_ename emp.ename%type;

p_comm emp.comm%type;

begin

  p_annualSal := fun_get_annualSal_by_empno2(7499,p_ename,p_comm);

  dbms_output.put_line('员工姓名为:'||p_ename||',奖金为:'||p_comm||',年薪为:'||p_annualSal);

end;

1.2.5  程序中调用存储函数

 

package connect;

 

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

 

import oracle.jdbc.OracleTypes;

 

publicclass TestFunction {

 

   publicstaticvoid main(String[] args) {

      Connection conn = null;

      CallableStatement call = null;

      try {

         Class.forName("oracle.jdbc.OracleDriver");

         String url = "jdbc:oracle:thin:@localhost:1521:orcl";

         conn = DriverManager.getConnection(url, "czy", "orcl");

         call = conn.prepareCall("{? = call fun_get_annualSal_by_empno2(?,?,?)}");

         //注册存储函数返回值

         call.registerOutParameter(1, OracleTypes.DOUBLE);

         //设置输入参数,员工号

         call.setInt(2, 7499);

         //注册输出参数,员工姓名

         call.registerOutParameter(3, OracleTypes.VARCHAR);

         //注册输出参数,奖金

         call.registerOutParameter(4, OracleTypes.DOUBLE);

         call.execute();

         System.out.println("员工姓名为:" + call.getString(3) + ",奖金为:" + call.getDouble(4)

                + ",年薪为:" + call.getDouble(1));

      } catch (Exception e) {

         e.printStackTrace();

      } finally {

         try {

            if(call != null){

               call.close();

            }

            if(conn != null){

                conn.close();

            }

         } catch (SQLException e) {

            e.printStackTrace();

         }

      }

   }

 

}

1.2.6  删除存储函数

【语法】

DROP FUNCTION <函数名>;

 

【示例】

drop function fun_helloWorld;

drop function fun_get_annualSal_by_empno;

drop function fun_get_annualSal_by_empno2;

1.3      存储过程与存储函数的区别

        1、返回值的区别,函数一定要有1个返回值或有多个通过输出参数的返回值,而存储过程是通过输出参数返回的,可以有多个或者没有;

        2、调用的区别,函数可以在sql语句中直接调用,而存储过程必须单独调用

        3、函数一般情况下是用来计算并返回一个计算结果,而存储过程一般是用来完成特定的数据操作(比如修改、插入数据库表或执行某些DDL语句等等)

你可能感兴趣的:(Oracle)