Oracle学习————【PL/SQL】

1 使用PL/SQL书写一个Hello World程序

在这里插入图片描述

1.1 什么是PL/SQL?

在这里插入图片描述

1.2 PL/SQL的语法

在这里插入图片描述

1.2.1 If语句

语法:
在这里插入图片描述
使用实例:
在这里插入图片描述

1.2.2 循环

语法:(有3种形式)
在这里插入图片描述

1.2.3 光标

在写java程序中有集合的概念,那么在pl/sql中也会用到多条记录,这时候我们就要用到游标,游标可以存储查询返回的多条数据。

在这里插入图片描述
下面是光标使用实例:(实现查询遍历表中员工的姓名和薪水并打印)
在这里插入图片描述
使用实例2:(给对应员工涨工资,总裁涨1000 经理涨800 其他涨400)
在这里插入图片描述
使用实例3:(带参数的光标使用,查询某个部门的员工姓名)
在这里插入图片描述

1.2.4 例外(异常)

异常是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性。

  • Oracle中例外有两种:一种是系统定义的例外,另一种是自定义的例外。
1.2.4.1 系统定义异常

在这里插入图片描述

  • timeout_on_resource发生的情景一般是在使用分布式数据库时会遇到。

下面展示一下如何定义使用系统异常。
在这里插入图片描述

1.2.4.2 自定义异常

在pl/sql中我们把自定义例外当成变量来处理
在这里插入图片描述
下面通过实例说明自定义异常如何使用
在这里插入图片描述

1.3 常量和变量的定义

在这里插入图片描述

1.3.1 引用型变量的使用举例

在这里插入图片描述

1.3.2 记录型变量的使用举例

在这里插入图片描述

1.3.3 常量的定义

常量声明:<变量名> CONSTANT类型 := 初始值
示例:pi constant number(5,3) := 3.14;

1.4 存储过程,函数和触发器

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

那么存储过程和存储函数有什么区别呢?存储函数能够通过return返回结果,存储过程则不能。

Java中不能直接调用plsql,但能够调用存储过程和存储函数。

1.4.1 创建存储过程

  • 用CREATE PROCEDURE命令建立存储过程。

  • 语法:
    在这里插入图片描述
    上图中AS也可以用IS替换。

1.4.1.1 使用存储过程创建一个helloworld程序

在这里插入图片描述
下面是调用存储过程:(有两种方式)
在这里插入图片描述

1.4.1.2 在plsql dev中创建存储过程

在这里插入图片描述
在这里插入图片描述

1.4.1.3 创建带参数的存储过程

在这里插入图片描述

1.4.2 创建存储函数

在这里插入图片描述
在这里插入图片描述

1.4.2.1 使用存储函数实例

在这里插入图片描述
2.填写函数名称
在这里插入图片描述
3.书写函数,并F8执行
在这里插入图片描述
F8执行后将会在Functions栏中生成。那么调用某个函数的方法就是选中该函数右键选择Test
在这里插入图片描述
在这里插入图片描述

1.4.3 过程和函数中的in和out

在这里插入图片描述
下面是存储过程中使用out参数的实例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4.3.1 什么时候用存储过程/存储函数?

在这里插入图片描述

1.4.3.2 在out参数中使用游标

问题的引出:我们知道,在存储过程中可以使用out类型参数表示返回出来的数据类型,但有时我们会存在返回多条数据,就会声明多次out类型参数,那么当数量变多时,我们在声明out类型参数就会变得很麻烦,我们需要将多条out参数以一个集合的形式声明出来。

例如这种需求:1.查询某个员工的所有信息 —> 需要些out参数太多 2.查询某个部门中的所有员工信息 —> 需要返回的是个集合。

像以上举例的这两种需求就不好再单单以out参数的形式声明返回。所以就需要在out参数中使用游标这种集合形式声明返回。

1.4.3.2.1 包头、包体

当我们想要在out参数中使用游标,我们可以使用包结构进行编写。

  • 声明包(包头)结构,包头只负责声明不负责实现。包体来负责实现表头中所声明的所有存储过程和存储函数。
    在这里插入图片描述
  • 创建包体
    在这里插入图片描述
    如何在plsql dev中创建包头或包体呢?如下
    在这里插入图片描述

1.4.4 触发器

什么是触发器?
在这里插入图片描述

1.4.4.1 如何创建并使用触发器?

语法:
在这里插入图片描述

需求:实现每当成功插入新员工后,自动打印“成功插入新员工”
在这里插入图片描述

1.4.4.2 触发器可用于
  • 数据确认
  • 实施复杂的安全性检查
  • 做审计(日志),跟踪表上所做的数据操作等
  • 数据的备份和同步
1.4.4.3 触发器的类型

在这里插入图片描述

存儲過程寫法學習

1. 根據id刪除人員數據
procedure DELETE_SURVEY_EMP_SP(
              V_ID IN VARCHAR2,
              P_RES OUT INTEGER) as
    begin
      P_RES := 0;
      delete from CDT.R_SURVEY_EMP_LIST_T  ---這裡是物理刪除
       where ID = V_ID;
      
      commit;
      
      select nvl(count(1),0) into P_RES -- 1,代表刪除成功
        from dual			-- 其實這裡使用nvl(count(1),0)只是爲了滿足下面not exists (select 1 from CDT.R_SURVEY_EMP_LIST_T where ID = V_ID);這個條件后返回1而已,其實單獨執行select count(1) from dual也會返回1
       where not exists
       (select 1 
          from CDT.R_SURVEY_EMP_LIST_T
         where ID = V_ID);
         
      exception
        when others then
          P_RES := 0; -- 0,代表刪除失敗
          rollback;
    end;
2. 得到部門及其子部門,這是層次查詢
-- 得到部門及其子部門,這是層次查詢
SELECT *
  FROM dept_info_t
 WHERE is_invalid = '0' 
CONNECT BY PRIOR id = parent_dept_id
 START WITH 
 id IN (63324);
-- 得到部門及其父部門
SELECT ID,
       dept_name,
       dept_level_id,
       bu_code_id
  FROM dept_info_t
 WHERE is_invalid = '0'
CONNECT BY PRIOR parent_dept_id = ID
 START WITH 
 ID = TO_NUMBER(31133);
4. 怎样才产生区间数字的一个列表?
---怎样才产生区间数字的一个列表?比如说,这个列表的区间设置为90~95,就要产生一个90,91,92,93,94,95这个6条记录,怎么才能做到
with t as
(select rownum rn from dual connect by rownum<=100 )
select * from t where rn between 90 and 95
5. 怎樣以select形式展示出幾個常量結果集
---怎樣以select形式展示出幾個常量結果集	   下面是展示一列3個數據:Q0011,Q0012,Q0099
select 'Q0011' AS LEAVE_TYPE from dual
union all
select 'Q0012' from dual
union all
select 'Q0099' from dual
6. oracle 表中有很多相同的记录,怎么只取满足条件的第一条?
----oracle 表中有很多相同的记录,怎么只取满足条件的第一条?
select * from dept where rownum =1
---就在条件里面加一个伪列就行了。
7. WITH 表名 AS可以接多個設置表名
例如:
WITH1 AS (SELECt * FROM table1),2 AS (SELECT * FROM table2),
	....
	表n AS (SELECT * FROM tablen)
8. 抓取時間區間數據
--------在一張上千萬條數據的表中,根據某個時間類型的字段去查詢某個時間段內的數據。
--------(這是個坑,舉個例子:現有一張表t1,裡頭有個work_time字段,是date類型,我現在想根據這個時間類型字段去查找某段時間(這裡舉個時間段2019/01/01到2019/10/01)的數據)
------在寫這個SQL的時候一開始我是這麼寫的:SELECT * FROM t1 WHERE work_time BETWEEN to_date('2019/01/01','yyyy/mm/dd') AND to_date('2019/10/01','yyyy/mm/dd');
-----這麼寫其實在表數據量不算巨大的時候執行是不會感覺太慢,但當數據量達到千萬基本的時候(正式庫裡這張t1表的數據量是8千萬條...),再去執行這樣的一條語句時結果將會在一分鐘後出。
-----那麼我的優化方式是:SELECT * FROM t1 WHERE to_char(work_time,'yyyy/mm/dd') BETWEEN '2019/01/01' AND '2019/10/01';這樣的寫法瞬間快到零點幾秒。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值