什么是存储过程和存储函数:指存储在数据库中供所有用户程序调用的子程序叫做存储过程、存储函数。

这个子程序是用PL/SQL写的。可以用Java程序调用,就是完成特定功能的子程序。

用create procedure命令创建存储过程。

语法:

Create [or replace] procedure 过程名(参数列表) asPLSQL子程序体;

As相当于declare,所以我们可以在as后面定义变量。As不可以省略。

--打印Hello World。

Create or replace procedure sayHelloWorld

As

--说明部分

Begin

Dbms_output.put_line(‘HelloWorld’);

End;

/

先将存储过程编译,在SQL Developer左边的树结构中的过程里就产生了这个存储过程。

如果图标上有小红叉,表示有语法错误,如果是绿叶,表示没有问题。这个存储过程的功能是打印HelloWorld。

如何调用这个存储过程呢?

第一种方式:使用execute命令

Exec sayHelloWorld();

第二种调用方式:

Begin

sayHelloWorld();

sayHelloWorld();

sayHelloWorld();

end;

/

带参数的存储过程:

--给指定员工的工资涨100元工资,并且打印涨前和涨后的薪水。

--既然是指定,就是员工会变化,所以要接收一个员工参数。

--指定参数的时候要分为输入参数和输出参数,默认是输入参数,但是显示指出比较好,用in指出。

Create or replace procedure raiseSalary(enoin number)

As

--变量

Psalemp.sal%type;

Begin

--得到涨前的薪水。

Selectsal into psal from emp where empno = eno;

--涨100元

Updateemp set sal = sal + 100 where empno = eno;

--这里不要提交事务,谁调用谁来提交事务

--打印涨前和涨后的薪水。

Dbms_output.put_line(‘涨前:’||psal||’涨后’||(psal+100));

End;

/

编译。

调用:

Begin

raiseSalary(7839);

raiseSalary(7566);

commit;

end;

/

存储过程和存储函数的区别:

存储过程没有返回值,存储函数可以有一个返回值。

存储函数:

函数为一命名的存储程序,可以带参数,并返回一个计算值。函数和过程的结构类似,但必须有一个return子句,用于返回函数值。函数说明要指定函数名、结果值的类型,以及参数类型等。

语法:

Create [or replace] function 函数名(参数列表)

Return 函数值类型

As

PLSQL子程序体;

--查询某个员工的年收入,通过函数查询,查询完将查询结果返回。

--接收一个员工参数

Create or replace functionqueryEmpIncome(eno in number)

Return number

As

--年收入与月薪和奖金有关,定义两个变量,接收月薪和奖金。

Psalemp.sal%type;

Pcommemp.comm%type;

Begin

--得到该员工的月薪和奖金

Selectsal,comm into psal,pcomm from emp where empno = eno;

--返回年收入

Returnpsal*12+nvl(pcomm,0);

End;

/

编译一下,在左边的树结构中就出现了函数的部分。

直接在图标上点右键选择运行就可以运行。

打开对话框,传参数:

控制台结果:

双击函数,可以打开一个窗口,这个窗口有debug的功能,在侧边双击可以打断点。

Debug需要权限,需要授权。

Grant DEBUG CONNECT SESSION , DEBUG ANY PROCEDUREto scott;

关于输出参数:

存储过程和存储函数都可以通过out指定一个或多个输出参数。我们可以利用out参数,在过程和函数中实现返回多个值。

原则:如果只有一个返回值,用存储函数,否则,就用存储过程。

--out参数的例子。查询并返回某个员工的姓名 月薪 职位

--因为要返回姓名,月薪,职位,就要在参数中定义为输出参数。

Create or replace procedurequeryEmpInfo(eno in number,pename out varchar2,psal out number,pjob outvarchar2)

As

Begin

Selectename,sal,empjob into pename,psal,pjob from emp where empno = eno;

End;

/

编译,在过程上刷新,右键运行。

如何在Java程序中调用存储过程或存储函数呢?

先获取Connection,在获取CallableStatement(Statement的子类)。

通过Connection的prepareCall(String sql)方法创建CallableStatement。

CallableStatement是用来执行SQL存储过程的接口。JDBCAPI提供了一个存储过程SQL转义语法,该语法允许对所有RDBMS使用标准方式调用存储过程。

调用的SQL语法:

调存储函数:?=call[(,,…)]

掉存储过程:call[(,…)]

调用示例:用PL/SQL比直接使用SQL调用效率要高。

创建工程,导入Oracle的jar包。Jar包位置如地址栏所示。

(1)JDBC工具类

Public class JDBCUtils {

Private static String driver = “oracle.jdbc.OracleDriver”;

Private static String url = “jdbc:oracle:thin:@localhost:1521:orcl”;

Private static String user = “scott”;

Private static String password = “tiger”;

Static {

Try{

Class.forName(driver);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

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; //为是么置null呢?需要垃圾回收,gc机制。

}

}

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;

}

}

}

}

Public class TestOracle {

@Test

Public void testProcedure() {

//第一个是输入参数,后三个是输出参数。

String sql = “{call queryEmpInfo(?,?,?,?)}”;

Connection conn = null;

CallableStatement call = null;

Try {

Conn = JDBCUtils.getConnection();

Call = conn.prepareCall(sal);

//对于in参数赋值

Call.setInt(1,7839);

//对于out参数。在执行后才有值。通过OracleTypes中的常量可以将Oracle的类型转换成Java的类型

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);

System.out.println(sal);

System.out.println(job);

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(conn,call,null);

}

}

@Test

Public void testFunction(){

String sql = “{?=call queryEmpIncone(?)}”;

Connection conn = null;

CallableStatement call = null;

Try {

Conn = JDBCUtils.getConnection();

Call = conn.prepareCall(sal);

//第一个参数是返回值,先处理out参数

//对于out参数。在执行后才有值。通过OracleTypes中的常量可以将Oracle的类型转换成Java的类型

Call.registerOutParameter(1,OracleTypes.NUMBER);

//对于in参数赋值

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);

}

}

}

--返回某个部门的所有员工的所有信息。这样out就太多了

--可以通过在光标中定义。

在out中使用光标,有一个要求,必须将光标和存储过程或者存储函数放到一个包里面。

什么是包?

是一个数据库对象,是包头,包头只负责声明,包体只负责实现。

声明包:

--例:根据员工的员工号查询员工信息,要求返回员工的所有信息。

Create or replace package MYPACKAGE as

--自定义一个类型empcursor,这个类型引用cursor光标类型,也就是说,设个empcursor类型就是一个光标

Type empcursoris ref cursor;

--在out中使用自定义的光标类型

Procedurequeryemp(eid in number,empinfo out empcursor);

End MYPACKAGE;

什么是包体?

也是一个数据库对象,包体要实现存储过程和存储函数。

CREATE OR REPLACE

PACKAGE BODY MYPACKAGE AS

PROCEDUREqueryemp(eid in number,empinfo out empcursor) AS

BEGIN

Openempinfo for select * fro emp where empno = eid;

ENDqueryemp;

END MYPACKAGE;

--返回某个部门的所有员工的所有信息

CREATE OR REPLACE

PACKAGE MYPACKAGE AS

Typeempcursor is ref cursor;

ProcedurequeryEmpList(dno in number,empList out empcursor);

END MYPACKAGE;

--编译好后,在左边的树结构中的程序包节点中就有了刚定义的包。右键,可以选择创建包体。

--会将包头中所有需要实现的程序都列出来。

CREATE OR REPLACE

PACKAGE BODY MYPACKAGE AS

ProcedurequeryEmpList(dno in number,empList out empcursor) AS

BEGIN

--这里open了光标,并没有关闭光标,其实光标关闭了,

--因为在返回rs结果集后,程序关闭了rs,关闭了rs也就关闭了光标。

OpenempList for select * from emp where deptno = dno;

ENDqueryEmpList;

END MYPACKAGE;

//编写测试程序

@Test

Public void testCursor() {

String sql = “{call MYPACKAGE.queryEmpList(?,?)}”;

Connection conn = null;

CallableStatement call = null;

ResultSet rs = null;

Try{

Conn = JDBCUtils.getConnection();

Call = conn.prepareCall(sql);

//对于in参数赋值。部门号

Call.setInt(1,10);

//对于out参数,所有员工的所有信息。

Call.registerOutParameter(2,OracleTypes.CURSOR);

//执行。

Call.execute();

//取出该部门中的员工的信息。Call中没有getCursor,需要转成OracleCallableStatement

Rs = (OracleCallableStatement)call.getCursor(2);

While(rs.next()) {

String name = rs.getString(“ename”);

double sal = rs.getDouble(“sal”);

System.out.println(name + “ ” + sal);

}

} catch(Exception e) {

e.printStackTrace();

} finally {

JDBCUtils.release(conn,call,rs);

}

}

上面的程序可以在MySQL中跑吗?不可以,因为实现的是Oracle的接口。

oracle as 不可以省略,Oracle:存储过程,存储函数相关推荐

  1. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表.---查询语句创建表 create table emp as ...

  2. 视图存储过程存储函数

    文章目录 视图 常见数据库对象 视图概述 为什么使用视图? 视图的理解 创建视图 创建单表视图 创建多表联合视图 基于视图创建视图 查看视图 更新视图的数据 一般情况 不可更新的视图 修改.删除视图 ...

  3. Day463.视图存储过程存储函数 -mysql

    视图 1. 常见的数据库对象 对象 描述 表(TABLE) 表是存储数据的逻辑单元,以行和列的形式存在,列就是字段,行就是记录 数据字典 就是系统表,存放数据库相关信息的表.系统表的数据通常由数据库系 ...

  4. WebDay18 MySQL存储过程 存储函数 触发器 事务

    MySQL存储过程 存储函数 触发器 事务 一.MySQL存储过程和函数 1.存储过程和函数的概念 2.存储过程和函数的好处 3.存储过程和函数的区别 4.创建存储过程 5.调用存储过程 6.查看存储 ...

  5. MySQL 案例实战--MySQL数据库 存储过程 存储函数

    MySQL数据库 存储过程 & 存储函数 前言 一.什么是存储过程 & 存储函数 二.存储过程的创建和调用 三.存储函数的创建和调用 前言 本环境是基于 Centos 7.8 系统构建 ...

  6. Oracle 中重新编译无效的存储过程, 或函数、触发器等对象(转)

    Oracle 中的存储过程在有些情况下会变成失效状态,在 PL/SQL Developer 中该存储过程的图标左上角显示一把小红叉叉.比如储过程所引用的对象失效,dblink 出问题啦都可能引起用到它 ...

  7. [mysql]存储过程/存储函数

    [Stored Procedure /Stored Function] 存储过程 定义 语法分析: 调试 效果比较 存储函数 应用 语法分析: 两者对比 存储过程和函数的查看.修改.删除 查看 修改 ...

  8. 存储过程存储函数得简记(转)

    oracle中的存储过程和存储函数的区别 (尊重劳动成果,转载请注明出处:https://blog.csdn.net/qq_39778516/article/details/84033710 cons ...

  9. mysql 函数 局部变量_MySQL 存储过程 存储函数 局部变量 游标 概念示例

    一个存储过程是一个可编程的函数,它可以在MySQL中创建并保存.它是由一些SQL语句和一些特殊的控制结构语句组成. 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定的功能时,存储过程是一个非 ...

最新文章

  1. shardingjdbc全局表_sharding-jdbc实现按年分库按月分表
  2. 想学python有什么用-Python为什么这么火?学习python有什么用?
  3. Python 【抖音】短视频的自动上传与发布实例演示,同时支持快手、哔哩哔哩、小红书、微视、西瓜视频、微信视频号等平台的视频自动化同步发布
  4. 阿里云ECS服务器搭建wordpress个人博客网站【详细图文教程】
  5. 机器人学中的一些概念3——雅克比矩阵
  6. 行政管理对计算机的要求,信息技术对行政管理的影响.doc
  7. PL/SQL Developer 登录 Oracle 12c和Win10下安装Oracle 11g
  8. win11玩游戏怎么样 windows11玩游戏的具体性能介绍
  9. 堆叠顺序的误区和z-index
  10. 【HDOJ】1071 The area
  11. Atitit nlp 自然语言处理的艺术 attilax著作 v2 t55.docx Atitit nlp 自然语言处理attilax总结 目录 1.1. 主要范畴 1 1.2. 研究难点
  12. EtherCAT总线运动控制学习笔记(RXXW_Dor)
  13. ubuntu安装openpose
  14. Excel将汉字与英文分开
  15. r5 5500u和r5 4600u区别有多大 r55500u和r54600u哪个好
  16. 10万行代码电商项目
  17. 文本分类 之 基于BertForSequenceClassification模型的金融知道 最佳答案推荐
  18. python中numpy函数ftt_语音MFCC提取:librosa python_speech_feature(2019.12)
  19. IDX20803: Unable to obtain configuration from: ‘[PII is hidden
  20. c语言学生学籍管理程序,C语言实现简单学籍管理系统

热门文章

  1. 紫金农商银行java面试_【应届本科生求职】我的南京紫金农商行面试之路
  2. python写excel文件出错_【求教】xlutils修改中文Excel文件出错
  3. private访问权限java_Java之访问权限
  4. 由MAC地址在18字节及6字节之间的转换引发越界问题讨论
  5. 国际计算机语言,国际标准的5种PLC编程语言简介
  6. aliyun maven 添加jar_gradle添加阿里云maven库
  7. cpci检索为什么那么慢_索引原理与慢查询优化
  8. logic回归是一种线性回归
  9. php 跳转网页 变量,php变量与JS变量实现不通过跳转直接交互的方法
  10. word 段显示在页面最下方_Word你说的白是什么白