码迷,mamicode.com
首页 > 其他好文 > 详细

存储过程和自定义函数

时间:2021-04-30 12:00:31      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:jdbcutil   stack   parameter   creat   upd   word   acl   取数据   where   

1. 存储过程和自定义函数概述

存储过程、存储函数:存储在数据库中供所有用户程序调用的子程序

程序过程和存储函数的相同点: 完成特定功能的程序
程序过程和存储函数的区别: 是否用return语句返回值

2. 存储过程的创建和调用

2.1 第一个存储过程

用 CREATE PROCEDURE命令建立存储过程和存储函数

语法:
	create [or replace] PROCEDURE 过程名(参数列表)
	AS
	PLSQL子程序体;

--	第一个存储过程 打印helloworld
create or replace procedure sayhelloworld
as
    -- 说明部分
begin
   dbms_output.put_line(‘Hello World‘); 
end;
/

-- 调用存储过程
方式一:	exec sayhelloworld();
方式二:	begin 
			sayhelloworld();
            end;

2.2 带参数的存储过程

-- 为指定的员工,涨100块钱的工资;并且打印涨前和涨后的薪水
create or replace procedure raisesalary(eno in number)
as
    psal emp.sal%type;
begin 
    select sal into psal from emp where empno=eno;
    
    update emp set sal=sal+100 where empno=eno;
    -- 一般不在存储过程或者存储函数中,commit和rollback.
    dbms_output.put_line(‘涨前:‘||psal);
    dbms_output.put_line(‘涨后:‘||(psal+100));
end;
/

--调用存储过程
set serveroutput on
begin 
    raisesalary(7369);
    raisesalary(7499);
    COMMIT;
end;

3. 存储函数

函数(Function)为一命名的存储程序,可带参数,并返回一计算值。
函数和过程的结构相似,但必须有一个return子句,用于返回函数值。

语法:
	create [or replace] FUNCTION 参数名(参数列表)
	return 函数值类型
	AS
	PLSQL子程序体;
	
-------------------------------------------------
-- 查询某个员工的年收入
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;
/

4. out参数

一般来讲,存储过程和存储函数的区别在于存储函数可以有一个返回值;而存储过程没有返回值。
过程和函数都可以通过out指定一个或多个输出参数。我们可以利用out参数,在过程和函数中实现返回多个值。

-- 存储过程和存储函数都可以有out参数
-- 存储过程和存储函数都可以有多个out参数
-- 存储过程可以通过out参数来实现返回值
什么时候用存储过程/存储函数
	原则:如果只有一个返回值,用存储函数;否则,就用存储过程。
	
-- 查询某个员工的姓名,月薪和职位
create or replace procedure queryempinform( eno in number,
                                            pename out varchar2,
                                            psal out number,
                                            pjob out varchar2
                                            )
as 
begin 
    select ename,sal,job into pename,psal,pjob from emp where empno=eno;
end;
/

5. 在应用中访问存储过程和存储函数

5.1 概述

在java中使用访问存储过程和存储函数
package com.xiaofeng.testoracle.utils;

import java.sql.*;

/**
 * 描述:   jdbc 工具类
 */
public class JDBCUtils {
    private static String driver="oracle.jdbc.driver.OracleDriver";
    private static String url="jdbc:oracle:thin:@127.0.0.1:1521:orcl";
    private static String user="scott";
    private static  String password="xxxx";

    //注册数据库的驱动
    static{
        try {
            Class.forName(driver);
            //DriverManager.registerDriver(driver);
        } catch (ClassNotFoundException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    //获取数据库连接
    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //释放数据库的资源
    public static void release(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;
            }
        }
    }
}

5.2 在应用程序中访问存储过程

import com.xiaofeng.testoracle.utils.JDBCUtils;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Statement;

/**
 * 描述:   测试存储过程
 */
public class TestProcedure {
    /**
     * create or replace procedure queryempinform( eno in number,
     * pename out varchar2,
     * psal out number,
     * pjob out varchar2
     * )
     */

    public void testProcedure() {
        //{call<procedure-name>[(<arg1>,<arg2>,...)]}
        String sql = "{call queryempinform(?,?,?,?)}";
        Connection conn = null;
        CallableStatement call = null;
        try {
            //得到一个连接
            conn = JDBCUtils.getConnection();
            //通过连接创建出Statement
            call=conn.prepareCall(sql);

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

            //对于out参数,声明
            call.registerOutParameter(2,java.sql.Types.VARCHAR);
            call.registerOutParameter(3,java.sql.Types.DOUBLE);
            call.registerOutParameter(4,java.sql.Types.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 (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,call,null);
        }


    }

    public static void main(String[] args) {
        TestProcedure test1 = new TestProcedure();
        test1.testProcedure();
    }

}

5.3 在应用程序中访问存储函数

import com.xiaofeng.testoracle.utils.JDBCUtils;

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

/**
 * 描述:   测试存储函数
 */
public class TestFunction {
    /**
     * create or replace function queryempincome(eno in number)
     * return number
     */
    public void testFunction() {
        //{?=call<procedure-name>[(<arg1>,<arg2>,...)]}
        String sql = "{?=call queryempincome(?)}";
        Connection conn = null;
        CallableStatement call = null;
        try {
            //得到数据库连接
            conn=JDBCUtils.getConnection();
            //基于连接创建Statement
            call=conn.prepareCall(sql);

            //对于输出参数,声明
            call.registerOutParameter(1, Types.DOUBLE);
            //对于输入参数,赋值
            call.setInt(2,7839);
            //执行调用
            call.execute();
            //取出年收入的结果
            double income=call.getDouble(1);
            System.out.println("该员工的年收入是:"+income);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(conn,call,null);
        }
    }

    public static void main(String[] args) {
        TestFunction test1=new TestFunction();
        test1.testFunction();
    }
}

6. 在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;

7. 在应用程序中访问包下的存储过程

需要带上包名

  import com.xiaofeng.testoracle.utils.JDBCUtils;


import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import oracle.jdbc.OracleCallableStatement;

/**
 * 描述:   测试plsql包
 */
public class TestCursor {
    /**
     * create or replace package mypackage as
     *     type empcursor is ref cursor;
     *     procedure queryEmpList(dno in number,empList out empcursor);
     * end mypackage
     */
    public void testCursor(){
        //{call<procedure-name>[(<arg1>,<arg2>,...)]}
        String sql="{call MYPACKAGE.queryEmpList(?,?)} ";
        Connection conn=null;
        CallableStatement call=null;
        ResultSet rs=null;
        try{
            conn=JDBCUtils.getConnection();
            call=conn.prepareCall(sql);
            call.setInt(1,10);
            call.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);
            call.execute();
            rs=((OracleCallableStatement)call).getCursor(2);
            while(rs.next()){
                int empno=rs.getInt("empno");
                String ename=rs.getString("ename");
                double sal=rs.getDouble("sal");
                String job=rs.getString("job");
                System.out.println(empno+"\t"+ename+"\t"+sal+"\t"+job);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,call,rs);
        }

    }

    public static void main(String[] args) {
        TestCursor test1=new TestCursor();
        test1.testCursor();
    }
}

存储过程和自定义函数

标签:jdbcutil   stack   parameter   creat   upd   word   acl   取数据   where   

原文地址:https://www.cnblogs.com/xiaofengrong/p/14717556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!