oracle存储过程

存储过程

创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站制作、成都网站设计、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的迭部网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!

1、创建

create procedure 过程名(变量名 in 变量类型...变量名 out 变量类型...)is

//定义变量  注:变量类型后不需要指定大小

begin

//执行的语句

end

:项目中所用的:

CREATE OR REPLACE PROCEDURE PROC_CBBS_FILES

------存储过程说明

 --/******************************************************

  --/*Procedure     :PROC_CBBS_FILES                                                -----存储过程

  --/*Discription   :把mv_f_xinxg_files视图中的数据依次插入mv_f_cbbs_files表中    -----存储过程描述

  --/*Version      :1.0---初始版本

  --/*Author       :郝晓利

  --/*Create Date  :2014/08/26

 --/*****************************************************

 AS

  insert_str long; ----插入表语句

BEGIN

  FOR x IN(select * frommv_f_xinxg_files)

    LOOP

    -----循环

    insert_str := 'INSERT INTOmv_f_cbbs_files(MO_ID,CAPTION,TIME,FILES,PROV_ID,PROV_NAME,TACHE_NAME,BUSI_TYPE)

               VALUES(''' ||x.MO_ID || ''',''' || x.CAPTION || ''',''' || x.TIME || ''',''' ||

               x.FILES || ''','''|| x.PROV_code || ''',''' || x.PROV_NAME || ''',''' || x.TACHE_NAME || ''','''||x.busi_type|| ''',)';

    ----执行insert语句

    EXECUTE IMMEDIATE insert_str;

    COMMIT; -----提交

  END LOOP; -----结束循环

END;-----BEGIN  END

例:①无返回值的存储过程

请写一个过程,可以向 book 表添加书,要求通过 java 程序调用该过程。

--in:表示这是一个输入参数,默认为 in

--out:表示一个输出参数

Sql 代码

1. create or replace procedure sp_pro7(spBookId in number,spbookNa

me in varchar2,sppublishHouse in varchar2) is

2. begin

3. insert into book values(spBookId,spbookName,sppublishHouse);

4. end;

5. /

--在 java 中调用

Java 代码

1. //调用一个无返回值的过程

2. import java.sql.*;

3. public class Test2{

4. public static void main(String[] args){

5.

6. try{

7. //1.加载驱动

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

9. //2.得到连接

10. Connection ct = DriverManager.getConnection("jdbc:o

racle:thin@127.0.0.1:1521:MYORA1","scott","m123");

11.

12. //3.创建 CallableStatement

13. CallableStatement cs = ct.prepareCall("{callsp_pro7(?,?,?)}");

14. //4.给?赋值

15. cs.setInt(1,10);

16. cs.setString(2,"笑傲江湖");

17. cs.setString(3,"人民出版社");

18. //5.执行

19. cs.execute();

20. } catch(Exception e){

21. e.printStackTrace();

22. } finally{

23. //6.关闭各个打开的资源

24. cs.close();

25. ct.close();

26. }

27. }

28.}

②有返回值的存储过程(非列表)

例:编写一个过程,可以输入雇员的编号,返回该雇员的姓名。

Sql 代码

1. --有输入和输出的存储过程

 create or replace procedure sp_pro8(spno in number, spName out varchar2)is

 begin

 select ename into spName from empwhere empno=spno;

 end;

 /

Java代码

 import java.sql.*;

 public class Test2{

 public static void main(String[]args){

 try{

 //1.加载驱动

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

 //2.得到连接

 Connection ct =DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

 //3.创建 CallableStatement

/*CallableStatement cs = ct.prepareCall("{callsp_pro7(?,?,?)}");

//4.给?赋值

cs.setInt(1,10);

cs.setString(2,"笑傲江湖");

cs.setString(3,"人民出版社");*/

//看看如何调用有返回值的过程

//创建 CallableStatement

/*CallableStatement cs = ct.prepareCall("{call sp_pro8(?,?)}");//给第一个?赋值

cs.setInt(1,7788);

//给第二个?赋值

cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);

 //5.执行

cs.execute();

//取出返回值,要注意?的顺序

String name=cs.getString(2);

System.out.println("7788的名字"+name);

} catch(Exception e){

e.printStackTrace();

} finally{

//6.关闭各个打开的资源

cs.close();

ct.close();

}

}

}注:1、对于过程的输入值,使用setXXX,对于输出值,使用registerOutParameter,问号的顺序要对应,同时考虑类型。

2、取出过程返回值的方法是CallableStatement提供的getXXX(输出参数的位置)同时考虑输出的参数类型

案例扩张:编写一个过程,可以输入雇员的编号,返回该雇员的姓名、工资和岗位。

Sql 代码

1. --有输入和输出的存储过程

2. create or replace procedure sp_pro8

3. (spno in number, spName out varchar2,spSal out number,spJob outvarchar2) is

4. begin

5. select ename,sal,job into spName,spSal,spJob from emp where empno=spno;

6. end;

7. /

Java代码

1. import java.sql.*;

2. public class Test2{

3. public static void main(String[] args){

5. try{

6. //1.加载驱动

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

8. //2.得到连接

9. Connection ct =DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

11. //3.创建 CallableStatement

12. /*CallableStatement cs = ct.prepareCall("{callsp_pro7(?,?,?)}");

13. //4.给?赋值

14. cs.setInt(1,10);

15. cs.setString(2,"笑傲江湖");

16. cs.setString(3,"人民出版社");*/

18. //看看如何调用有返回值的过程

19. //创建 CallableStatement

20. /*CallableStatement cs = ct.prepareCall("{callsp_pro8(?,?,?,?)}");

22. //给第一个?赋值

23. cs.setInt(1,7788);

24. //给第二个?赋值

25. cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);

26. //给第三个?赋值

27. cs.registerOutParameter(3,oracle.jdbc.OracleTypes.DOUBLE);

28. //给第四个?赋值

29. cs.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);

31. //5.执行

32. cs.execute();

33. //取出返回值,要注意?的顺序

34. String name=cs.getString(2);

35. String job=cs.getString(4);

36. System.out.println("7788的名字"+name+"工作:"+job);

37. } catch(Exception e){

38. e.printStackTrace();

39. } finally{

40. //6.关闭各个打开的资源

41. cs.close();

42. ct.close();

43. }

44. }

45.}

③有返回值的存储过程(列表[结果集])

案例:编写一个过程,输入部门号,返回该部门所有雇员信息。

由于 oracle 存储过程没有返回值,它的所有返回值都是通过 out 参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage了。所以要分两部分:

返回结果集的过程

1.建立一个包,在该包中,定义类型 test_cursor,是个游标。 如下:

Sql 代码

create or replace package testpackage as

TYPE test_cursor is ref cursor;

end testpackage;

2.建立存储过程。如下:

Sql 代码

1. create or replace procedure sp_pro9(spNo in number,p_cursor outtestpackage.test_cursor) is

2. begin

3. open p_cursor for select * from emp where deptno = spNo;

5. end sp_pro9;

3.如何在 java程序中调用该过程

Java代码

1. import java.sql.*;

2. public class Test2{

3. public static void main(String[] args){

5. try{

6. //1.加载驱动

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

8. //2.得到连接

9. Connection ct =DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

11. //看看如何调用有返回值的过程

12. //3.创建 CallableStatement

13. /*CallableStatement cs = ct.prepareCall("{callsp_pro9(?,?)}");

15. //4.给第?赋值

16. cs.setInt(1,10);

17. //给第二个?赋值

18. cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);

20. //5.执行

21. cs.execute();

22. //对象强转为结果集

23. ResultSet rs=(ResultSet)cs.getObject(2);

24. while(rs.next()){

25. System.out.println(rs.getInt(1)+" "+rs.getString(2));

26. }

27. } catch(Exception e){

28. e.printStackTrace();

29. } finally{

30. //6.关闭各个打开的资源

31. cs.close();

32. ct.close();

33. }

34. }

35.}

运行,成功得出部门号是 10的所有用户

④编写分页过程

例:编写一个存储过程,要求可以输入表名、每页显示记录数、当前

页。返回总记录数,总页数,和返回的结果集。

Sql 代码

1. select t1.*, rownum rn from (select * from emp) t1 whererownum<=10;

2. --在分页时,大家可以把下面的 sql 语句当做一个模板使用

3. select * from

4. (select t1.*, rownum rn from (select * from emp) t1 whererownum<=10)

5. where rn>=6;

建立一个包,在该包中,我定义类型 test_cursor,是个游标。如下:

Sql代码

1. create or replace package testpackage as

2. TYPE test_cursor is ref cursor;

3. end testpackage;

 --开始编写分页的过程

5. create or replace procedure fenye

6. (tableName in varchar2,

7. Pagesize in number,--一页显示记录数

8. pageNow in number,

9. myrows out number,--总记录数

10. myPageCount out number,--总页数

11. p_cursor out testpackage.test_cursor--返回的记录集

12. ) is

13.--定义部分

14.--定义 sql语句字符串

15.v_sql varchar2(1000);

16.--定义两个整数

17.v_begin number:=(pageNow-1)*Pagesize+1;

18.v_end number:=pageNow*Pagesize;

19.begin

20.--执行部分

21.v_sql:='select * from (select t1.*, rownum rn from (select * from'||tableName||') t1 where rownum<='||v_end||') where rn>='||v_begin;

22.--把游标和 sql关联

23.open p_cursor for v_sql;

24.--计算 myrows和 myPageCount

25.--组织一个 sql语句

26.v_sql:='select count(*) from '||tableName;

27.--执行 sql,并把返回的值,赋给 myrows;

28.execute inmediate v_sql into myrows;

29.--计算 myPageCount

30.--if myrows%Pagesize=0 then这样写是错的

31.if mod(myrows,Pagesize)=0 then

32. myPageCount:=myrows/Pagesize;

33.else

34.myPageCount:=myrows/Pagesize+1

35.end if;

36.--关闭游标

37.close p_cursor;

38.end;

39./

--使用 java测试

//测试分页

Java代码

import java.sql.*;

public class FenYe{

public static void main(String[] args){

  try{

  //1.加载驱动

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

  //2.得到连接

  Connection ct =DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

 //3.创建 CallableStatement

 CallableStatement cs = ct.prepareCall("{callfenye(?,?,?,?,?,?)}");

 //4.给第?赋值

 cs.seString(1,"emp");

 cs.setInt(2,5);

 cs.setInt(3,2);

 //注册总记录数

 cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);

 //注册总页数

 cs.registerOutParameter(5,oracle.jdbc.OracleTypes.INTEGER);

 //注册返回的结果集

 cs.registerOutParameter(6,oracle.jdbc.OracleTypes.CURSOR);

 //5.执行

 cs.execute();

 //取出总记录数 /这里要注意,getInt(4)中 4,是由该参数的位置决定的

 int rowNum=cs.getInt(4);

 int pageCount = cs.getInt(5);

 ResultSet rs=(ResultSet)cs.getObject(6);

 //显示一下,看看对不对

 System.out.println("rowNum="+rowNum);

 System.out.println("总页数="+pageCount);

 while(rs.next()){

 System.out.println("编号: "+rs.getInt(1)+"名字:"+rs.getString(2)+"工资:"+rs.getFloat(6));

 }

 } catch(Exception e){

 e.printStackTrace();

 } finally{

 //6.关闭各个打开的资源

 cs.close();

 ct.close();

 }

 }

}

运行,控制台输出:

rowNum=19

总页数:4

编号:7369名字:SMITH工资:2850.0

编号:7499 名字:ALLEN 工资:2450.0

编号:7521 名字:WARD 工资:1562.0

编号:7566 名字:JONES 工资:7200.0

编号:7654 名字:MARTIN 工资:1500.0

--新的需要,要求按照薪水从低到高排序,然后取出 6-10

过程的执行部分做下改动,如下:

Sql 代码

begin

--执行部分

v_sql:='select * from (select t1.*, rownum rn from (select * from'||tableName||' order by sal) t1 where rownum<='||v_end||')

where rn>='||v_begin;

重新执行一次 procedure,java不用改变,运行,控制台输出:

rowNum=19

总页数:4

编号:7900名字:JAMES工资:950.0

编号:7876 名字:ADAMS 工资:1100.0

编号:7521 名字:WARD 工资:1250.0

编号:7654 名字:MARTIN 工资:1250.0

编号:7934 名字:MILLER 工资:1300.0

2、㈠在oracle客户端调用过程有两种方法:

   ①exec 过程名(参数值...)

   ②call 过程名(参数值...)

实际begin

     存储过程名;

end;(或者右击存储过程名并点击测试)

  ㈡在JAVA中调用存储过程方法:

①加载驱动:Class.forName("oracle.jdbc.driver.OracleDriver");

②得到链接:ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:数据库名","用户名","密码")

③创建CallableStatement接口对象:cs=ct.prepareCall("{call过程名(?,?)}");

④给?赋值:cs.setString(1,"haoxiaoli");//?为你插入的字段个数,与SQL语句有关

⑤执行我们的语句:cs.execute();

注:如果卡了记得在oracle中先提交commit

 

3、显示错误:

show error;

 


名称栏目:oracle存储过程
当前网址:http://ybzwz.com/article/psscop.html