Oracle存储过程的实现

Oracle存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(是否给参数要看该存储过程定义的过程中是否设置了参数)来执行它。

准备工作

创建一张测试表 students

create table STUDENTS(
  id      VARCHAR2(50) default sys_guid() not null,
  name    VARCHAR2(20),
  age     NUMBER(4,1),
  school  VARCHAR2(100),
  grade   VARCHAR2(50),
  address VARCHAR2(500),
  remarks VARCHAR2(500),
  ts      CHAR(19) default to_char(sysdate,'yyyy-mm-dd hh24:mi:ss')
)

插入一条测试数据。当然,也可以插入自己想插入的内容。

insert into STUDENTS (id, name, age, school, grade, address, remarks, ts)
values ('8A17DE17428E45D6E0530100007FABEB', 'xiaoming', 20, 'Changchun University of Architecture', 'Junior', 'Changchun, Jilin', null, '2019-06-12 11:07:57');

第一个简单的存储过程

CREATE OR REPLACE PROCEDURE stu_school
AS school_name VARCHAR2(100);
BEGIN
  SELECT school INTO school_name FROM students WHERE ID='8A17DE17428E45D6E0530100007FABEB';
  dbms_output.put_line(school_name);
END;

执行存储过程,可以在PLSQL对象中看到我们刚才新创建的存储过程,并且没有报错,代表编译成功。

Oracle存储过程的实现_第1张图片

执行存储过程

CALL stu_school();

调用时,"()"是必不可少的,无论是有参数还是无参数

在SQL窗口输出页签中可以看到正确的输出内容

Oracle存储过程的实现_第2张图片

四种存储过程

存储过程有一下四种情况

  • 无参数存储过程
  • 仅有输入参数存储过程
  • 仅有输出参数存储过程
  • 既有输入又有输出存储过程

下面将对这四种存储过程分别举例说明

无参数存储过程

无参数存储过程就如上面写的那个简单的存储过程,也可以这样写:

CREATE OR REPLACE PROCEDURE stu_school
AS school_name students.school%TYPE;
BEGIN
  SELECT school INTO school_name FROM students WHERE ID='8A17DE17428E45D6E0530100007FABEB';
  dbms_output.put_line(school_name);
END;

仅有输入参数存储过程

CREATE OR REPLACE PROCEDURE stu_address(stu_id IN students.id%TYPE)
AS addr students.address%TYPE;
BEGIN
  SELECT address INTO addr FROM students WHERE ID=stu_id;
  dbms_output.put_line(addr);
END;

执行存储过程

CALL stu_address('8A17DE17428E45D6E0530100007FABEB');

Oracle存储过程的实现_第3张图片

仅有输出参数存储过程

CREATE OR REPLACE PROCEDURE stu_age(stu_age OUT students.age%TYPE)
AS
BEGIN
  SELECT age INTO stu_age FROM students WHERE ID='8A17DE17428E45D6E0530100007FABEB';
END;

需要注意的是,此种存储过程不能直接通过call来调用,需要通过一下方式执行

注意,如果通过这种方式执行存储过程,要记得在存储过程中添加输出语句,不然的话,纵然执行成功,也没有结果输出。
dbms_output.put_line(stu_age);

DECLARE
stuage students.age%TYPE;
BEGIN
  stu_age(stuage);
END;

或者通过oracle函数调用带有输出参数的存储过程

CREATE OR REPLACE FUNCTION get_stuage(stuage OUT NUMBER) RETURN NUMBER IS
BEGIN
  stu_age(stuage);
  RETURN stuage;
END;

执行函数

DECLARE
  stuage students.age%TYPE;
BEGIN
  dbms_output.put_line('return result:' || get_stuage(stuage));
END;

既有输入又有输出参数的存储过程

CREATE OR REPLACE PROCEDURE stu_name(stuid IN students.id%TYPE, stuname OUT students.name%TYPE)
AS
BEGIN 
  SELECT NAME INTO stuname FROM students WHERE ID=stuid;
END;

新建存储函数调用存储过程

CREATE OR REPLACE FUNCTION get_stuname(stuid IN students.id%TYPE, stuname OUT students.name%TYPE) RETURN VARCHAR2 IS
BEGIN
  stu_name(stuid, stuname);
  RETURN stuname;
END;

执行函数

DECLARE
  stuname students.name%TYPE;
BEGIN
  dbms_output.put_line('The student name is:' || get_stuname('8A17DE17428E45D6E0530100007FABEB', stuname));
END;

Java调用存储过程

Java调用仅有输出参数的存储过程

针对存储过程 stu_age

CREATE OR REPLACE PROCEDURE stu_age(stu_age OUT students.age%TYPE)
AS
BEGIN
  SELECT age INTO stu_age FROM students WHERE ID='8A17DE17428E45D6E0530100007FABEB';
END;

Java代码如下:

private void OnlyOutputProcedure() {
    try {
        Class.forName(DRVIER);
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        String sql = "{call stu_age(?)}";
        CallableStatement statement = connection.prepareCall(sql);
        statement.registerOutParameter(1, OracleTypes.NUMBER);
        statement.execute();
        System.out.println(statement.getInt(1));
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

Java调用既有输入参数又有输出参数的存储过程

针对存储过程 stu_name

CREATE OR REPLACE PROCEDURE stu_name(stuid IN students.id%TYPE, stuname OUT students.name%TYPE)
AS
BEGIN
  SELECT NAME INTO stuname FROM students WHERE ID=stuid;
END;

Java代码如下:

private void InAndOutputProcedure() {
    try {
        Class.forName(DRVIER);
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        String sql = "{call stu_name(?,?)}";
        CallableStatement statement = connection.prepareCall(sql);
        statement.setString(1, "8A17DE17428E45D6E0530100007FABEB");
        statement.registerOutParameter(2, OracleTypes.VARCHAR);
        statement.execute();
        System.out.println(statement.getString(2));
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

以上是有OUT输出参数的存储过程,Java在调用存储过程后还会获得存储过程返回的参数。那么如果存储过程没有OUT输出参数怎么办?

Java调用仅有输入参数的存储过程

private void OnlyInputProcedure() {
    try {
        Class.forName(DRVIER);
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        String sql = "{call stu_address(?)}";
        CallableStatement statement = connection.prepareCall(sql);
        statement.setString(1, "8A17DE17428E45D6E0530100007FABEB");
        statement.execute();
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

Java调用无参的存储过程

private void NoParameterProcedure() {
    try {
        Class.forName(DRVIER);
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        String sql = "{call stu_school()}";
        CallableStatement statement = connection.prepareCall(sql);
        statement.execute();
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

Java调用存储函数

get_stuname 存储过程为例

CREATE OR REPLACE PROCEDURE stu_name(stuid IN students.id%TYPE, stuname OUT students.name%TYPE)
AS
BEGIN
  SELECT NAME INTO stuname FROM students WHERE ID=stuid;
END;

存储函数 get_stuname 调用

CREATE OR REPLACE FUNCTION get_stuname(stuid IN students.id%TYPE, stuname OUT students.name%TYPE) RETURN VARCHAR2 IS
BEGIN
  stu_name(stuid, stuname);
  RETURN stuname;
END;

这里有一个关于Oracle存储过程的PPT文档,供大家下载学习点击下载

你可能感兴趣的:(Oracle)