一、存储过程、存储函数
 
1、What's This?
①、ORACLE 提供可以把 PL/SQL 程序存储在数据库中,并可以在任何地方来运行它。这样就叫存储过程或函数。
②、存储过程、存储函数的唯一区别是存储函数有返回值,而存储过程没有返回值。
 
2、创建存储函数
eg、根据部门号返回部门总工资
CREATE OR REPLACE FUNCTION get_salary(
dep_id IN employees.department_id%TYPE DEFAULT 10, -- 输入参数, 可以设置默认值
emp_count OUT NUMBER -- 输出参数
)
RETURN NUMBER -- 返回值类型
IS
v_sum NUMBER; BEGIN SELECT sum(salary), COUNT(*) INTO v_sum, emp_count
FROM employees
WHERE department_id = dep_id;
RETURN v_sum; -- 返回值
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('No data found');
WHEN OTHERS THEN
dbms_output.put_line('Other Exception'); END;

执行、删除存储函数

-- 执行该函数
DECLARE
v_sum NUMBER;
v_count NUMBER;
BEGIN
v_sum := get_salary(80, v_count);
-- v_sum := get_salary(dep_id => 80, emp_count => v_count);
dbms_output.put_line('80号部门工资总数: ' || v_sum || ',人数:' || v_count);
END; -- 删除
DROP FUNCTION get_salary;
3、存储过程
eg、根据员号查询员工工资
CREATE OR REPLACE PROCEDURE query_emp_salary(
v_empid employees.employee_id%TYPE,
v_name OUT employees.last_name%TYPE,
v_sal OUT employees.salary%TYPE
)
AS BEGIN SELECT last_name, salary INTO v_name, v_sal
FROM employees
WHERE employee_id = v_empid;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('No data found');
WHEN OTHERS THEN
dbms_output.put_line('Other Exception'); END;
执行、删除存储过程
-- 执行该存储过程
DECLARE
v_1 employees.employee_id%TYPE;
v_2 employees.last_name%TYPE;
BEGIN
query_emp_salary(60, v_1, v_2);
dbms_output.put_line('name: : ' || v_1 || ',salary:' || v_2);
END; -- 删除
DROP PROCEDURE query_emp;
二、包的创建和应用
 
1、What's 包?
①、包是一组相关过程、函数、变量、常量和游标等 PL/SQL 程序设计元素的组合,是对这些 PL/SQL 程序设计元素的封装。(好像JAVA中的类,可以定义各种方法)
②、使用包不仅可以使程序设计模块化,还可以对外隐藏包内所使用的信息(通过使用私
用变量)
③、当程序首次调用包内函数或过程时, ORACLE 将整个包调入内存,当再次访问包内元素时, ORACLE 直接从内存中读取,而不需要进行磁盘 I/O 操作,从而使程序执行效率得到提高。
 
2、包的组成(包定义、包主体)
①、包定义(PACKAGE):声明包内数据类型、游标、函数、过程、异常,这些元素为包的公有元素。
②、包主体(PACKAGE BODY):包定义部分的具体实现,在包主体中可以定义包的私有元素
 
注意:包定义和包主体分开编译,并作为两部分分开的对象存放在数据库字典中,详见数据字典 user_source、all_source、 dba_source.
 
3、包的实现:
eg、创建的包为 demo_pack, 该包中包含一个记录变量 DeptRec、一个函数和一个过程。
包定义:
-- demo_pack 包定义:
CREATE OR REPLACE PACKAGE demo_pack
AS
deptRec departments%ROWTYPE; -- 声明游标
FUNCTION add_dept(dept_no NUMBER, dept_name VARCHAR2) -- 声明函数
RETURN NUMBER;
PROCEDURE query_dept(dept_no IN NUMBER); -- 声明存储过程
END demo_pack;
包主体:
-- demo_pack 包主体:
CREATE OR REPLACE PACKAGE BODY demo_pack
AS -- 创建 add_demp 函数
FUNCTION add_dept(dept_no NUMBER, dept_name VARCHAR2)
RETURN NUMBER
AS
empno_remaining EXCEPTION; -- 声明异常
PRAGMA exception_init(empno_remaining, -1); -- -1位违反唯一约束错误
BEGIN
INSERT INTO departments(department_id, department_name)
VALUES(dept_no, dept_name);
IF SQL%FOUND THEN
RETURN 1;
END IF;
EXCEPTION
WHEN empno_remaining THEN
RETURN 0;
WHEN OTHERS THEN
RETURN -1;
END add_dept; -- 创建 query_dept 存储过程
PROCEDURE query_dept(dept_no IN NUMBER)
AS
BEGIN
SELECT * INTO deptRec FROM departments WHERE department_id = dept_no;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no_data_found exception');
WHEN OTHERS THEN
dbms_output.put_line('Other exception');
END query_dept; BEGIN
NULL;
END demo_pack;
demo_pack 包的调用:对包内共有元素的调用格式为:包名.元素名称
DECLARE
v1 NUMBER;
BEGIN v1 := demo_pack.add_dept(900, 'dept-A'); IF v1 = -1 THEN
dbms_output.put_line(SQLCODE || ': ' || SQLERRM);
ELSIF v1 = 0 THEN
dbms_output.put_line('部门存在啊');
ELSE
dbms_output.put_line('SUCCESS');
demo_pack.query_dept(900);
dbms_output.put_line('ID: ' || demo_pack.deptRec.department_id ||
', dept-name: ' || demo_pack.deptRec.department_name );
END IF;
END;
三、触发器
 
1、What's 触发器?
①、触发器是当某个事件发生时自动地触发另一个事件。所以运行触发器就叫触发或点火(^^)。
②、ORACLE 事件指的是对数据库的表进行的INSERT、 UPDATE 及 DELETE 操作或对视图进行类似的操作。 ORACLE 将触发器的功能扩展到了触发 ORACLE,如数据库的启动与关闭等。
 
2、触发器类型
  2.1 DML 触发器
    可以在 DML 操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。
  2.2 替代触发器
    由于在 ORACLE 里,不能直接对由两个以上的表建立的视图进行操作。所以给出了替代触发器。
  2.3 系统触发器
    它可以在 ORACLE 数据库系统的事件中进行触发,如 ORACLE 系统的启动与关闭等
 
3、触发器组成:
触发事件:INSERT, UPDATE, DELETE。
触发时间:触发事件发生之前( BEFORE)还是之后(AFTER)触发
触发器本身: TRIGGER 触发之后的目的和意图
触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
 
注意:
①、语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;
行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
②、当省略 FOR EACH ROW 选项时, BEFORE 和 AFTER 触发器为语句触发器,而 INSTEAD OF 触发器则为行触发器。
 
4、创建触发器
4.1、DML 触发器
类型:
BEFORE INSERT
BEFORE INSERT FOR EACH ROW
AFTER INSERT
AFTER INSERT FOR EACH ROW BEFORE UPDATE
BEFORE UPDATE FOR EACH ROW
AFTER UPDATE
AFTER UPDATE FOR EACH ROW BEFORE DELETE
BEFORE DELETE FOR EACH ROW
AFTER DELETE
AFTER DELETE FOR EACH ROW
问题:当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列的值。
解决:   :new ------修饰符访问操作完成后列的值
      :old  ------修饰符访问操作完成前列的值

eg、把职工表被删除记录写到职工表删除日志表中:
CREATE OR REPLACE TRIGGER del_emp_trigger
BEFORE DELETE ON employees FOR EACH ROW BEGIN INSERT INTO emp_temp(employee_id, first_name, last_name)
VALUES(:old.employee_id, :old.first_name, :OLD.last_name); END;
 
4.2、替代(INSTEAD OF)触发器
①、INSTEAD OF 触发器,只能对视图和对象视图建立 INSTEAD OF触发器,而不能对表、模式和数据库建立 INSTEAD OF 触发器
②、只能对视图和对象视图建立 INSTEAD OF触发器,而不能对表、模式和数据库建立 INSTEAD OF 触发器
 
eg、删除视图emp_view 中的数据

-- 删除视图数据非法
DELETE FROM emp_view WHERE employee_id = 100 -- 解决方法: INSTEAD OF 触发器 CREATE OR REPLACE TRIGGER emp_view_del
INSTEAD OF DELETE ON emp_view FOR EACH ROW
BEGIN
DELETE FROM employees WHERE employee_id = :old.employee_id;
END emp_view_del;
 
4.3、创建系统事件触发器
  系统事件触发器可以在 DDL 或数据库系统上被触发。
  ①、DDL 指的是数据定义语言,如CREATE 、 ALTER 及 DROP 等。
  ②、数据库系统事件包括数据库服务器的启动或关闭,用户的登录与退出、数据库服务错误等。
 
4.4、触发器状态
注意: 当删除表或视图时,建立在这些对象上的触发器也随之删除。
  有效状态(ENABLE):当触发事件发生时,处于有效状态的数据库触发器 TRIGGER 将被触发。
  无效状态(DISABLE):当触发事件发生时,处于无效状态的数据库触发器 TRIGGER 将不会被触发,就跟没有这个数据库触发器(TRIGGER) 一样
FOR EXAMPLE:
ALTER TRIGGER emp_view_delete DISABLE(ENABLE);

pl/sql 笔记之存储过程、函数、包、触发器(下)的更多相关文章

  1. 【Java EE 学习 29 上】【PL/SQL】【存储过程】【存储函数】【触发器】

    一.PL/SQL简介 1.概念:PL/SQL语言是Oracle数据库专用的一种高级程序设计语言,是对标准SQL语言进行了过程化扩展的语言. 2.功能:既能够实现对数据库的操作,也能够通过过程化语言中的 ...

  2. 查看SQL SERVER 加密存储过程,函数,触发器,视图

    原文:查看SQL SERVER 加密存储过程,函数,触发器,视图 create  PROCEDURE sp_decrypt(@objectname varchar(50))ASbeginset noc ...

  3. MySQL mysqldump 导入/导出 结构&数据&存储过程&函数&事件&触发器

    ———————————————-库操作———————————————-1.①导出一个库结构 mysqldump -d dbname -u root -p > xxx.sql ②导出多个库结构 m ...

  4. 在PL/SQL中调用存储过程--oracle

    在oracle10中写好了存储过程,代码如下: CREATE OR REPLACE Procedure Proc_Insert ( sName in varchar2, sAge in int, sE ...

  5. PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验

    PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验 一.问题现象及解决方法 现象: 1.PL/SQL 无法登录64位数据库 2.在PL/SQL ...

  6. Oracle PL/SQL异常、存储过程和触发器

    一.异常 1.处理异常 (1)除数不为0 declare b number; begin b:; exception when zero_divide then dbms_output.put_lin ...

  7. oracle-游标-存储过程-函数-包

    一.存储过程 不可以在insert,update,delete中直接使用,可以有return但代表的是退出过程 过程有三种类型:不返回值,可以返回多个值,参数有三种类型,分别如下: in:只输入,不返 ...

  8. pl/sql 笔记之基础(上)

    由于公司中使用 oracle,而本人对存储过程一直也懵懵懂懂,故一周时间学习了一遍 pl/sql,在此记下笔记!!! 一.前提,pl/sql 是啥? 1.PL/SQL是一种高级数据库程序设计语言,该语 ...

  9. PL SQL笔记(三)

    loop then .. exit; end if; end loop; select to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') from dual; sel ...

随机推荐

  1. 基于 Koa平台Node.js开发的KoaHub.js连接打印机的代码

    最近好多小伙伴都在做微信商城的项目,那就给大家分享一个基于 Koa.js 平台的 Node.js web 开发的框架连接微信易联云打印机接口的代码,供大家学习.koahub-yilianyun 微信易 ...

  2. 1627: [Usaco2007 Dec]穿越泥地

    1627: [Usaco2007 Dec]穿越泥地 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 504  Solved: 325[Submit][Sta ...

  3. sqlplus入门使用

    1.如果在PL/SQL 等工具里打开的话,直接修改下面的代码中[斜体加粗部分]执行 2.确保路径存在,比如[D:\oracle\oradata\Oracle9i\]也就是你要保存文件的路径存在 /*分 ...

  4. TIME_WAIT问题总结

         最近用http_load做压测,跑出来一大串"Cannot assign requested address "的错误,查了一下,是TIME_WAIT过多导致的.因为短时 ...

  5. JavaScript重新介绍

    本文转载自 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript 引言 为什么 ...

  6. golang RWMutex读写锁分析

    RWMutex:是基于Mutex实现的读写互斥锁,一个goroutine可以持有多个读锁或者一个写锁,同一时刻只能持有读锁或者写锁 数据结构设计: type RWMutex struct { w Mu ...

  7. django进阶-4

    前言: 下篇博客写关于bootstrap... 一.如何在脚本测试django from django.db import models class Blog(models.Model): name ...

  8. Linux云自动化运维第四课

    Linux云自动化运维第四课 一.vim 1.vim光标移动 1)在命令模式下 :数字  ###移动到指定的行 G  ###文件最后一行 gg  ###文件第一行 2)在插入模式下 i  ###光标所 ...

  9. 10大支持移动“触摸操作”的JavaScript框架

    摘要:移动开发行业的发展速度让人目不暇接,也在此大势之下,推出移动网站App成为开发者必经之路,如何让触屏设备 更易使用?如何让网站对触摸手势做出反应并使触摸更友好?所有这一切,皆因JavaScrip ...

  10. 开发Nagios监控passwd文件插件

    第一步:开发脚本 [root@Admin libexec]# pwd /usr/local/nagios/libexec [root@Admin libexec]# cat check_passwd ...