Oracle Database-PL/SQL

PL/SQL基础

PL/SQL(Procedure Language/SQL)
PL/SQL是Oracle对SQL语言的过程化扩展,指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。把SQL语言的数据操纵能力与过程语言的数据处理能力结合起来,使得 PLSQL面向过程但比过程语言简单、高效、灵活和实用。
因为是过程化扩展,所以
  • PL/SQL程序内支持编写SQL语言

    • 将SQL语言的数据操纵能力与过程语言的数据处理能力结合
  • PL/SQL是一门面向过程的语言

PL/SQL的官方文档

如下,可以查到DBMS_OUTPUT程序包的内容
也可以在命令行中使用desc关键字直接查看程序包的结构
如下,这种方法相当于简化的文档

PL/SQL的语法

*Java的语法

PL/SQL可以完成以下Java代码(伪)完成的功能
下面是PL/SQL实现这个功能
而PL/SQL相对JDBC实现这个更能更有效率
开发模式:SpringMVC+存储过程(PL/SQL)
Hello World
这个dbms_output是一个程序包(类似API)

declare-变量和常量的说明

注意:若没有需要说明的变量或常量,可以没有declare关键字
说明基本数据类型变量时要说明三个部分
  • 变量名
  • 数据类型
  • 数据大小
基本类型变量
与表的列的数据类型对应(意味着我们可以把表中的数据存到这些类型的变量中)
  • char
  • varchar2
  • date
  • number
  • boolean
  • long
*PL/SQL中的":="相当于Java中的"=","="相当于Java中的"=="
引用型变量
引用表中列的数据类型作为该变量的数据类型
示例:
赋值有两种方法,":="和"into"关键字
记录型变量
记录型变量引用表中的一行作为变量(s)的数据类型,换句话说,记录型变量可以存放表中的一行数据,可以理解成一个数组(或者集合),数组中的每一个元素代表这一行的记录每一列
示例:

IF语句

语法
注意elsif这个写法与Java else if不一样
示例:
-- 判断用户从键盘输入的数字并打印相应语句
-- 接收键盘输入
-- accept addr prompt 'xxx'
-- addr 是一个地址值,在该地址上保持了输入的值
accept num prompt '请输入一个数字';
declare pnum number := #-- 注意:取出存在在这个地址值的值要使用'&'符号相当于c的指针
beginif pnum = 0 then dbms_output.put_line('you input 0');else if pnum = 1 then dbms_output.put_line('you input 1');else then dbms_output.put_line('you input other number');end if;
end;

注意,这段正确的代码无法在PL/SQL Developer和命令行中运行,但可以在Oracle SQL Developer(自行下载)中运行

循环语句

语法
示例:输入数字1到10

Cursor-光标(游标)

在Java语言中有集合的概念,在PL/SQL语言中也会用到多条记录作为整体,此时我们需要用到游标,游标可以存储查询返回的多条数据
简言之,光标/游标类似Java中的ResultSet

基本语法

说明光标
CURSOR 光标名 [(参数名数据类型[,参数名数据类型]...)] IS SELECT 语句;
如:
使用步骤
fetch关键字的作用是将光标的一个值赋到变量中并将指针往后移动一位(游标的指针默认在第一个值上)
示例:

光标的属性

  • %isopen:光标是否已打开
  • %rowcount:影响的行数(即已取出的行数)
  • %found:当前指针的位置是否仍然有记录
  • %notfound:当前指针位置是否没有记录

带参数的光标

语法
示例:

例外

例外例外是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性
相当于Java中的异常

例外的分类

  • 系统定义的例外

    • No_data_found(没有找到数据)
    • Too_many_rows(select …into语句匹配多个行)
    • Zero_Divide(被零除)
    • Value_error(算术或转换错误)
    • Timeout_on_resource(在等待资源时发生超时)(分布式数据库相关)
  • 用户定义的例外

定义及处理例外

  • 在declare节中定义例外

    • out_of exception;
  • 在可行语句中引起例外
    • raise out_of;(类似Java中的throw)
  • 在exception节处理例外
    • when out_of then …;(类似Java中的try-catch)
示例:

*PL/SQL的应用

实例

declare--部门cursor cdept is select deptno from dept;pdeptno dept.deptno%type;--部门中员工的薪水cursor cemp(dno number) is select sal from emp where deptno=dno;psal emp.sal%type;--每个段的人数count1 number; count2 number; count3 number;--部门的工资总额salTotal number := 0;
begin--部门open cdept;loop--取一个部门fetch cdept into pdeptno;exit when cdept%notfound;--初始化count1:=0; count2:=0; count3:=0;--得到部门的工资总额select sum(sal) into salTotal  from emp where deptno=pdeptno;--取部门的中员工薪水open cemp(pdeptno);loop--取一个员工的薪水fetch cemp into psal;exit when cemp%notfound;--判断if psal < 3000 then count1:=count1+1;elsif psal >=3000 and psal<6000 then count2:=count2+1;else count3:=count3+1;end if;end loop;close cemp;--保存结果insert into msg values(pdeptno,count1,count2,count3,nvl(saltotal,0));end loop;close cdept;commit;dbms_output.put_line('完成');end;

编写PL/SQL程序的一般步骤
  • 需求分析
  • SQL语句:即涉及操作数据库的逻辑

    • 获取数据库中的数据

      • 使用什么类型的变量来存放获取到的数据
      • 使用什么方式来从变量中提取数据(如循环,判断等)
    • 修改数据库中的数据
  • 变量
  • 变量的初始值
  • 变量的获取方式
    • 满足什么条件就改变变量的值

PL/SQL进阶内容

存储过程和存储函数

存储过程

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

存储函数

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

*

    简言之,存储在数据库中供所有用户程序调用的由PL/SQL编写的子程序被称为存储过程或存储函数。
在Java程序中,不能直接调用PL/SQL编写好的程序,但是可以调用存储过程或存储函数。
当然,在存储过程或存储函数中也可以调用存储过程或存储函数。

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

一般来讲,过程和函数的区别在于函数可以有一个返回值:而过程没有返回值。但过程和函数都可以通过out指定一个或多个输出参数。我们可以利用out参数,在过程和函数中实现返回多个值。
通常除去return(返回)值的不同,可以认为两者相同。

使用存储过程的语法

创建存储过程
调用存储过程
示例:
示例:

使用存储函数的语法

创建存储函数
调用存储函数
示例

存储过程和存储函数中的in(输入参数)out(输出参数)

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

使用存储过程/函数的注意事项

如果只有一个返回值,用存储函数,否则,就用存储过程
尽量不在存储过程或存储函数中操作事务,因为子程序是交由其他人调用的,不应该操作事务

*Java调用存储过程/存储函数

创建测试项目,导包
包的位置位于安装Oracle的机器下的这个目录
导入项目如下
编写工具类
package demo;import java.sql.*;public class JDBCUtils {private static String driver = "oracle.jdbc.OracleDriver";private static String url = "jdbc:oracle:thin:@169.254.35.157:1521/orcl";private static String user = "scott";private static String password = "tiger";static{// 注册驱动try {Class.forName(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;}}}
}

Statement接口的子接口CallableStatement就是专门用于执行SQL存储过程的接口
其中红框内是调用存储过程的标准方式
编写测试类分别测试存储过程和存储函数

存储过程

存储过程如下
测试代码如下
 /*procedure queryEmpInformation(eno in number,pename out varchar2,psal   out number,pjob   out varchar2)*/@Testpublic void testProcedure() {String sql = "{call queryEmpInformation(?,?,?,?)}";Connection conn = null;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();// 从CallableStatement对象中取出输出out参数String name = call.getString(2);Double sal = call.getDouble(3);String job = call.getString(4);System.out.println("name:" + name + " sal:" + sal + " job:" + job);} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.release(conn, call, null);}}

输出如下

存储函数

存储过程如下
测试代码如下
    /*function queryEmpIncome(eno in number)return number*/@Testpublic void testFunction() {String sql = "{?= call queryEmpIncome(?)}";Connection conn = null;CallableStatement call = null;try {conn = JDBCUtils.getConnection();call = conn.prepareCall(sql);// 存储函数的输出参数即返回值,是第一个问号,对其注册call.registerOutParameter(1, OracleTypes.NUMBER);// 赋值输入参数call.setInt(2, 7839);call.execute();double annIncome = call.getDouble(1);System.out.println("annual income:" + annIncome);} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.release(conn, call, null);}}

输出如下

调用使用光标作为out参数的存储过程

问题:查询某个部门所有员工的所有信息
在编写PL/SQL时申明包结构
创建包
在包中可以自定义一个数据类型(下面的empcursor),引用原有的数据类型(下面引用了cursor光标类型)作为这个类型
创建包体
在包体中需要实现包头中定义的所有存储过程和存储函数
在Java中访问
使用ResultSet来接受光标参数
具体测试代码如下
    @Testpublic void testCursor() {String sql = "{call mypackage.queryemplist(?,?)}";Connection conn = null;CallableStatement call = null;try {conn = JDBCUtils.getConnection();call = conn.prepareCall(sql);call.setInt(1, 10);call.registerOutParameter(2, OracleTypes.CURSOR);call.execute();// CallableStatement是一个通用的接口,获取时获得Oracle适用的实现类对象,可以将其强制转换成Oracle适用的接口ResultSet cursor = ((OracleCallableStatement) call).getCursor(2);while (cursor.next()) {System.out.println("name:"+cursor.getString("ename"));System.out.println("hiredate:"+cursor.getDate("hiredate"));}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.release(conn, call, cursor);// 此处关闭ResultSet时同时关闭了这个光标
        }}

触发器

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

触发器的作用

  • 数据确认

    • 如:员工涨工资后的工资不能少于涨工资后的工资
  • 实施复杂的安全性检查
    • 如:禁止在非工作时间插入新员工
  • 审计,跟踪表上的数据操作(日志)
    • *Oracle中的审计有五种

      • 强制审计
      • 标准审计(配置)
      • 基于值的审计(触发器审计属于这一类
      • 细粒度审计
      • 管理员审计
  • 数据的备份和同步

触发器的类型

  • 语句级触发器
    • 在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行
      • 如:一次插入多条数据,触发器只执行一次
    • 针对的是表
  • 行级触发器
    • 触发语句作用的每一条记录都被触发
    • 在行级触发器中使用:old和:new伪记录变量,识别值的状态
    • 针对的是行

创建触发器

语法
示例:
限制非工作时间向数据库插入数据
当非工作时间插入员工执行时会报错
示例2:
确认数据(检查emp表中sal 的修改值不低于原值)
运行效果
查询触发器、过程及函数
  • select * from user_triggers;
  • select * from user_source;

行级触发器中触发语句与伪记录变量代表的值

触发器的实际应用

S

*使用PL/SQL Developer编写PL/SQL程序

Hello World

转载于:https://www.cnblogs.com/zella1996/p/9550666.html

Oracle Database-PL/SQL相关推荐

  1. 《精通Oracle Database 12c SQL PL/SQL编程(第3版)》代码下载

    <精通Oracle Database 12c SQL & PL/SQL编程(第3版)>代码下载 清华大学出版社第五事业部 检索的时候关键词写Oracle,下面几个会有12C这个版本 ...

  2. oracle导入dmp报无效的sql,oracle施用pl/sql导入数据库备份文件dmp导入失败原因

    oracle使用pl/sql导入数据库备份文件dmp导入失败原因 利用PL/SQL导入数据库备份失败: Tools→Import →Tables Import Executable选择导入工具路径 D ...

  3. 判断题:oracle自带的sql语言环境是pl/sql,Oracle之PL/SQL学习笔记之数据类型(三)

    Oracle之PL/SQL学习笔记之数据类型(三) 所有的编程语言中变量是使用最频繁的.PL/SQL作为一个面向过程的数据库编程语言同样少不了变量,利用变量可以把PL/SQL块需要的参数传递进来,做到 ...

  4. Oracle的PL/SQL编程前奏之基础技能实战一(匿名子程序)

    Oracle的PL/SQL编程之基础技能实战一 一>基础代码检查检查以bm_开头的系统初始化编码表是否有空值.与业务系统相关的编码项不能存在空值,会导致系统业务无法办理.为初始化数据表.在做测试 ...

  5. 使用oracle 的 PL/Sql 定时执行一个存储过程

    /* 使用oracle 的 PL/Sql 定时执行一个存储过程 测试目的:在表 tab 中间隔一分钟插入一条数据 实现方案: 1.通过 oracle 中 dbms_job 完成存储过程的定时调用 2. ...

  6. oracle 12c sql图形化,Oracle 12c PL/SQL程序设计终极指南

    Oracle 12c PL/SQL程序设计终极指南 作者:孙风栋;王澜;郭晓惠 出版日期:2015年06月 文件大小:11.73M 支持设备: ¥60.00在线试读 适用客户端: 言商书局 iPad/ ...

  7. Oracle(五)PL/SQL编程语言

    Oracle(五)PL/SQL编程语言 ---pl/sql编程语言 ---pl/sql语言是对sql语言的扩展,使得sql语言具有过程化编程的特性. ---pl/sql编程语言比一般的过程化编程语言, ...

  8. Oracle之PL/SQL学习笔记之有名块练习

    2019独角兽企业重金招聘Python工程师标准>>> Oracle之PL/SQL学习笔记之有名块练习 存储过程案例: 案例1: 根据雇员姓名跟新雇员工资,如果雇员不存在输出没有该雇 ...

  9. 《OCA认证考试指南(1Z0-061):Oracle Database 12c SQL基础》

    2019独角兽企业重金招聘Python工程师标准>>> <OCA认证考试指南(1Z0-061):Oracle Database 12c SQL基础> 旨在帮助读者备战Or ...

  10. 使用wrap和unwrap加密解密Oracle的PL/SQL对象(包,存储过程,函数等)代码

    使用wrap和unwrap加密解密Oracle的PL/SQL对象(包,存储过程,函数等)代码 Oracle数据库系统自带的PL/SQL对象(包,存储过程,函数等)的代码绝大部分都是使用了wrap程序加 ...

最新文章

  1. 有哪些可以免登录的视频会议软件/服务?
  2. 4kyu Domino Tiling - 3 x N Board
  3. 和大家分享一个小TIP
  4. 怎样写出健壮的CLI程序
  5. c语言程序出现错误,C语言程序错误,不能正常读写文件,求解啊
  6. Sql Server 2008将数据库导出sql脚本并导出数据
  7. 智能物联网系统安全与防御【会议】
  8. LiteOS内核源码分析:任务LOS_Schedule
  9. 网页类型定义DOCTYPE
  10. android 初学者实现 popupwindow的自动弹出,Android popupWindow弹出窗体实现方法分析
  11. 选修课期末html作业,中南大学生命科学导论选修课期末作业
  12. Pytorch 编译cpp、cuda扩展遇到的问题
  13. 黑马博客——详细步骤(一)路由跳转和抽取公共部分代码
  14. 阿里java面_我的后端Java面经、八面阿里,已拿offer!
  15. FileReader读取本地文件
  16. 项目管理:系统需求分析模板
  17. 再好的技术,再完美的规章,也无法取代人自身的素质和责任心
  18. Sketch快捷键大全 Sketch如何自定义快捷键?
  19. 2023王道数据结构P40题二.1,关于是否会断链的问题
  20. iphone13预计上市时间 苹果13多少钱

热门文章

  1. matlab重叠保留法,【matlab实现】重叠相加法与重叠保留法
  2. Linux错误:bash:finger 未找到命令...
  3. Mac OS X 通知中心彻底删除网站的通知
  4. wireshark之文件还原
  5. 虚拟服务器设置虚拟内存,vmware虚拟机关于内存的一项设置,可以提高你的虚拟机运行效能-虚拟内存怎么设置最好...
  6. lineage os android 9,LineageOS 16.0 发布,基于 Android 9
  7. MATLAB读取excel表格中指定位置的数据
  8. 樊登读书会极致读后感_【学习部落】樊登读书会可复制的领导力感悟
  9. 使用webrtc开发直播系统源码,开发音视频语聊房
  10. Java 设计模式之策略模式(Strategy Pattern)