Java代码调用Oracle的存储过程Java代码调用Or

Java代码调用Oracle的存储过程,存储函数和包

java代码调用如下的存储过程和函数

create or replace procedure queryEmpinfo(eno in number,
                                         pename out varchar2,
                                         psal   out number,
                                         pjob   out varchar2)
as
begin
  select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
end;
复制代码
--查询某个员工的年收入
create or replace function queryEmpIncome(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;
复制代码
--在out参数中使用光标
查询某个部门中所有员工的所有信息


--包头
CREATE OR REPLACE PACKAGE MYPACKAGE AS

  type empcursor is ref cursor;
  procedure queryEmpList(dno in number,empList out empcursor);

END MYPACKAGE;


--包体
CREATE OR REPLACE
PACKAGE BODY MYPACKAGE AS

  procedure queryEmpList(dno in number,empList out empcursor) AS
  BEGIN
    open empList for select * from emp where deptno=dno;
  END queryEmpList;

END MYPACKAGE;
复制代码
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import oracle.jdbc.driver.OracleCallableStatement;
import oracle.jdbc.driver.OracleTypes;

import org.junit.Test;

public class TestOracle {

    /*
     * CallableStatement 接口
     *     调用存储函数,等号左边有一个返回值
     *    {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
     *  调用存储过程. 没有返回值
             {call <procedure-name>[(<arg1>,<arg2>, ...)]}

     *
     */

    /*存储过程 查询某个员工的姓名  月薪 职位
     * create or replace procedure queryEmpinfo(eno in number,
                                             pename out varchar2,
                                             psal   out number,
                                             pjob   out varchar2)
     */

    @Test
    public void testProcedure(){
        //{call <procedure-name>[(<arg1>,<arg2>,...)]}
        String sql = "{call queryEmpinfo(?,?,?,?)}";//4个问号中,第一个是输入参数,其余是输出参数
        Connection conn = null;
        //要用CallableStatement这个接口,用于执行 SQL 存储过程的接口
        CallableStatement call = null;

        try {
            conn = JDBCUtils.getConnection();
            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+"\t"+sal+"\t"+job+"\t");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.release(conn, call, null);//没有最后一个参数就传入null
        }
    }

    /*存储函数  查询某个员工的姓名,月薪和职位
     * create or replace function queryEmpIncome(eno in number)
        return number
     */
    @Test
    public void testFunction(){
        //{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
        //第一个问号是函数的返回值,第二个问号是输入参数.  返回值的作用和输出参数是一样的.
        String sql = "{?=call QUERYEMPINCOME(?)}";//这个call后面的存储过程名或者是存储函数名大写或者是小写是没有要求的.
        Connection conn = null;
        //要用CallableStatement这个接口,用于执行 SQL 存储过程的接口
        CallableStatement call = null;

        try {
            conn = JDBCUtils.getConnection();
            call = conn.prepareCall(sql);

            //对于in参数,赋值
            call.setInt(2,7839);

            //对于out参数,申明
            call.registerOutParameter(1, OracleTypes.NUMBER);
            call.execute();
            //取出结果
            //取出结果
            double income = call.getDouble(1);
            System.out.println(income);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.release(conn, call, null);//没有最后一个参数就传入null
        }


    }

    /*
        查询某个部门中所有员工的所有信息
        包头
        CREATE OR REPLACE PACKAGE MYPACKAGE AS

          type empcursor is ref cursor;
          procedure queryEmpList(dno in number,empList out empcursor);

        END MYPACKAGE;


        包体
        CREATE OR REPLACE
        PACKAGE BODY MYPACKAGE AS

          procedure queryEmpList(dno in number,empList out empcursor) AS
          BEGIN
            open empList for select * from emp where deptno=dno;
          END queryEmpList;

        END MYPACKAGE;
     */
    @Test
    public void testCursor(){
        //{call <procedure-name>[(<arg1>,<arg2>, ...)]}
        String sql = "{call MYPACKAGE.queryEmpList(?,?)}";

        Connection conn = null;
        CallableStatement call = null;
        //有游标,就有结果集
        ResultSet rest = null;
        try {
            conn = JDBCUtils.getConnection();
            call = conn.prepareCall(sql);

            //对于in参数,赋值
            call.setInt(1, 20);

            //对于out参数,申明
            call.registerOutParameter(2, OracleTypes.CURSOR);
            call.execute();
            //取出集合
            //这个地方要强转!!!OracleCallableStatement是抽象类,继承了CallableStatement
            //不强转没有getCursor()方法...
            rest = ((OracleCallableStatement)call).getCursor(2);
            while(rest.next()){
                String name = rest.getString("ename");
                double sal = rest.getDouble("sal");
                System.out.println(name+"\t"+sal);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.release(conn, call, rest);//上面打开了光标,再这个地方关闭结果集rest,也就关闭了光标
        }
    }
}
复制代码

关于Oracle中的包对象,之前的存储函数中查询的是某一个员工的信息

create or replace procedure queryEmpinfo(eno in number,
                                         pename out varchar2,
                                         psal   out number,
                                         pjob   out varchar2)
as
begin
  select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
end;
复制代码

但是①如果要查询一个员工的所有信息,而这个员工的信息对应的有几百列

在存储函数中括号的函数要把这几百列都声明出来?

②如果要查询某个部门中所有员工的所有信息...这个信息对应的是一个集合.

第二个问题解决了第一个问题也就解决了.

怎么在存储过程或者存储函数中返回一个集合.

学到现在有多少种方式可以代表一个集合?

第一个是表,第二个是select语句也可以.第三个是光标.

在out参数中使用光标.但是有一个要求,必须要声明一个包,包分为包头和包体.也是数据库的对象.跟表,视图,等是一样的是数据库的对象.

包头只负责声明,包体只负责实现.

--在out参数中使用光标
--查询某个部门中所有员工的所有信息


--包头
CREATE OR REPLACE PACKAGE MYPACKAGE AS

  type empcursor is ref cursor;
  procedure queryEmpList(dno in number,empList out empcursor);

END MYPACKAGE;


--包体
CREATE OR REPLACE
PACKAGE BODY MYPACKAGE AS

  procedure queryEmpList(dno in number,empList out empcursor) AS
  BEGIN
    open empList for select * from emp where deptno=dno;
  END queryEmpList;

END MYPACKAGE;
复制代码

分析图

参看包


包无法在plsqldeveloper和sqldeveloper等工具中右键运行....必须通过java代码应用程序来调用执行(代码在上面)