【Oracle基础】存储过程,存储函数,触发器,java调用存储过程

【Oracle基础】存储过程,存储函数,触发器,java调用存储过程

  • 1. 存储过程
  • 2. 存储函数
  • 3. 触发器
  • 4. java调用存储过程

1. 存储过程

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

简单来说:存储过程就是提前已经编译好的一段pl/sql语言,放置在数据库端,可以直接被调用。这一段pl/sql一般都是固定步骤的业务。

  • 语法
create [or replace] PROCEDURE 过程名[(参数名 in/out 数据类型)]
AS
begin
	PLSQL 子程序体;
End;

或者

create [or replace] PROCEDURE 过程名[(参数名 in/out 数据类型)]
is
begin
	PLSQL 子程序体;
End 过程名;
  • 示例
---给指定员工涨100块钱
create or replace procedure p1(eno emp.empno%type)
as
begin
  update emp set sal=sal+100 where empno=eno;
  commit;
end;
  • 调用
--测试pl
declare 

begin
  p1(7788);
end;

2. 存储函数

  • 语法
create or replace function 函数名(Name in type, Name in type, ...) return 数据类型 is
	结果变量 数据类型;
begin
	return(结果变量);
end 函数名;
  • 存储过程和存储函数的区别
    一般来讲,过程和函数的区别在于函数可以有一个返回值;而过程没有返回值。
    但过程和函数都可以通过 out 指定一个或多个输出参数。我们可以利用 out 参数,在过程和函数中实现返回多个值。
    如果存储过程想实现有返回值的业务,我们就必须使用out类型和参数。
    即便是存储过程使用了out类型的参数,其本质也不是真的有了返回值。
    而是在存储过程内部给out类型参数赋值,在执行完毕后,我们直接拿着用。
---通过存储函数实现计算指定员工的年薪
---存储过程和存储函数的参数都不能带长度
---存储函数的返回值类型不能带长度
create or replace function f_yearsal(eno emp.empno%type) return number
is
  s number(10);
begin
  select sal*12+nvl(comm,0) into s from emp where empno=eno;
  return s;
end f_yearsal;

--测试f_yearsal
---存储函数在调用的时候,返回值需要接收
declare 
  s number(10);
begin
  s := f_yearsal(7788);
  dbms_output.put_line(s);
end;

---out类型参数如何使用
---使用存储过程来算年薪
create or replace procedure p_yearsal(eno emp.empno%type,yearsal out number)
is
  s number(10);
  c emp.comm%type;
begin
  select sal*12,nvl(comm,0) into s,c from emp where empno=eno;
  yearsal := s+c;
end;

---测试p_yearsal
declare
  yearsal number(10);
begin
  p_yearsal(7788,yearsal);
  dbms_output.put_line(yearsal);
end;

--in和out类型的区别是什么?
---凡是涉及到into查询语句赋值或者:=赋值操作的参数,都必须使用out来修饰

3. 触发器

数据库触发器是一个与表相关联的、存储的 PL/SQL 程序。每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时, Oracle 自动地执行触发器中定义的语句序列

  • 触发器可用于
  1. 数据确认
  2. 实施复杂的安全性检查
  3. 做审计,跟踪表上所做的数据操作等
  4. 数据的备份和同步
  • 触发器的类型

    • 语句级触发器 : 在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行 。
    • 行级触发器(FOR EACH ROW) : 触发语句作用的每一条记录都被触发。在行级触发器中使用 old 和 new 伪记录变量, 识别值的状态。
  • 语法

CREATE [or REPLACE] TRIGGER 触发器名
	{BEFORE | AFTER}
	{DELETE | INSERT | UPDATE [OF 列名]}
	ON 表名
	[FOR EACH ROW [WHEN(条件) ] ]
begin
	PLSQL 块
End 触发器名
---触发器,就是指定一个规则,在我们做增删改操作的时候,
-------只要满足该规则,自动触发,无需调用
-------语句级触发器
-------行级触发器:包含有for each row的就是行级触发器。
-------------------加for each row是为了使用:old或者:new对象或者一行记录。

----插入一条记录,输出一个新员工入职
--语句级触发器
create or replace trigger t1
after 
insert
on person
declare
begin
  dbms_output.put_line('一个新员工入职');
end;
---触发t1
select * from person;
insert into person values(1,'小红');
commit;

--行级触发器
create or replace trigger t2
before 
update
on emp
for each row
declare
begin
  if :old.sal>:new.sal then
    raise_application_error(-20001,'不能给员工降薪');
  end if;
end;

--触发t2
update emp set sal=sal-1 where empno=7788;
commit;

--触发器实现主键自增
---分析:在用户做插入操作的之前,拿到即将插入的数据,给该数据中的主键列赋值。
create or replace trigger auid
before
insert
on person
for each row
declare
begin
  select s_person.nextval into :new.pid from dual;
end;
--使用autoid实现主键自增
insert into person(pname) values('a');
commit;

select * from person

【Oracle基础】存储过程,存储函数,触发器,java调用存储过程_第1张图片

4. java调用存储过程

首先我们可以在虚拟机中oracle 安装目录下找到 jar 包 :ojdbc14.jar
当然也可以使用maven工程导入坐标。
在这里插入图片描述

package com.siyi.oracle;

import oracle.jdbc.OracleTypes;
import oracle.jdbc.oracore.OracleType;
import org.junit.Test;

import java.sql.*;

public class OracleDemo {

    @Test
    public void javaCallOracle() throws ClassNotFoundException, SQLException {
        //加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //得到Connection连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.105:1521:orcl", "siyi", "siyi");
        //得到预编译的Statement对象
        PreparedStatement ps = connection.prepareStatement("select * from emp where empno = ?");
        ps.setObject(1,7788);
        //执行数据库查询操作
        ResultSet resultSet = ps.executeQuery();
        //输出结果
        while(resultSet.next()){
            System.out.println(resultSet.getString("ename"));
        }
        //释放资源
        resultSet.close();
        ps.close();
        connection.close();
    }

    /**
     * java调用存储过程
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    @Test
    public void javaCallProcedure() throws ClassNotFoundException, SQLException {
        //加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //得到Connection连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.105:1521:orcl", "siyi", "siyi");
        //得到预编译的Statement对象
        CallableStatement cs = connection.prepareCall("call p_yearsal(?,?)");
        cs.setObject(1,7788);
        cs.registerOutParameter(2, OracleTypes.NUMBER);
        //执行数据库查询操作
        cs.executeQuery();
        //输出结果
        System.out.println(cs.getObject(2));
        //释放资源
        cs.close();
        connection.close();
    }

    /**
     * java调用存储函数
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    @Test
    public void javaCallFunction() throws ClassNotFoundException, SQLException {
        //加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //得到Connection连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.105:1521:orcl", "siyi", "siyi");
        //得到预编译的Statement对象
        CallableStatement cs = connection.prepareCall("{?= call f_yearsal(?)}");
        cs.setObject(2,7788);
        cs.registerOutParameter(1, OracleTypes.NUMBER);
        //执行数据库查询操作
        cs.executeQuery();
        //输出结果
        System.out.println(cs.getObject(1));
        //释放资源
        cs.close();
        connection.close();
    }
}

你可能感兴趣的:(Oracle,oracle,存储过程,存储函数,触发器,java调用存储过程)