一、什么是DDL和数据库事件触发器?

DDL语句触发DDL触发器:CREATE,ALTER或DROP。
数据库事件触发器由数据库中的非SQL事件触发,例如:
•用户连接到数据库或与数据库断开连接。
•DBA启动或关闭数据库。

•用户会话中引发了特定的异常。

(1)在DDL语句中创建触发器语法

•ON DATABASE在数据库中的所有模式上触发DDL

•ON SCHEMA仅针对您自己的模式中的对象触发DDL

CREATE [OR REPLACE] TRIGGER trigger_name
Timing
[ddl_event1 [OR ddl_event2 OR ...]]
ON {DATABASE|SCHEMA}
trigger_body

(2)DDL触发器的示例

每次在模式中创建新的数据库对象时,都希望写入日志记录:

CREATE OR REPLACE TRIGGER log_create_trigg
AFTER CREATE ON SCHEMA
BEGININSERT INTO log_tableVALUES (USER, SYSDATE);
END;

只要有任何(类型)的对象被创建,触发器就会触发。 您不能创建引用特定数据库对象的DDL触发器。

(3)DDL触发器的第二个例子

防止从模式中删除任何对象。

CREATE OR REPLACE TRIGGER prevent_drop_trigg
BEFORE DROP ON SCHEMA
BEGINRAISE_APPLICATION_ERROR (-20203, 'Attempted drop – failed');
END;

只要有任何(类型)的对象被删除,触发器就会触发。 同样,您不能创建引用特定数据库对象的DDL触发器。

(4)在数据库事件语法上创建触发器

•ON DATABASE触发数据库中所有会话的事件触发器。
•ON SCHEMA仅为您自己的会话触发触发器。

CREATE [OR REPLACE] TRIGGER trigger_name
timing
[database_event1 [OR database_event2 OR ...]]
ON {DATABASE|SCHEMA}
trigger_body

二、LOGON、LOGOFF和SERVERERROR

示例1:LOGON和LOGOFF触发器

CREATE OR REPLACE TRIGGER logon_trig
AFTER LOGON ON SCHEMA
BEGIN
INSERT INTO log_trig_table(user_id,log_date,action)VALUES (USER, SYSDATE, 'Logging on');
END;
CREATE OR REPLACE TRIGGER logoff_trig
BEFORE LOGOFF ON SCHEMA
BEGIN
INSERT INTO log_trig_table(user_id,log_date,action)VALUES (USER, SYSDATE, 'Logging off');
END;

示例2:SERVERERROR触发器
想保留会话中发生的任何ORA-00942错误的日志:

CREATE OR REPLACE TRIGGER servererror_trig
AFTER SERVERERROR ON SCHEMA
BEGIN
IF (IS_SERVERERROR (942)) THENINSERT INTO error_log_table ...
END IF;
END;

三、触发器中的CALL语句

没有结束;语句,并且在CALL语句结尾处没有分号。

语法:

CREATE [OR REPLACE] TRIGGER trigger_name
timing
event1 [OR event2 OR event3]
ON table_name
[REFERENCING OLD AS old | NEW AS new]
[FOR EACH ROW]
[WHEN condition]
CALL procedure_name

例子:

CREATE OR REPLACE TRIGGER log_employee
BEFORE INSERT ON EMPLOYEESCALL log_execution

四、突变表和行触发器

突变表是一个当前正在由DML语句修改的表。

行触发器不能从变异表中选择,因为它会看到不一致的数据集(当触发器尝试读取数据时,表中的数据将会改变)。 但是,如果需要,行触发器可以从不同的表中进行选择。

此限制不适用于DML语句触发器,仅适用于DML行触发器。

突变表:例子

CREATE OR REPLACE TRIGGER check_salaryBEFORE INSERT OR UPDATE OF salary, job_id ON employeesFOR EACH ROW
DECLAREv_minsalary employees.salary%TYPE;v_maxsalary employees.salary%TYPE;
BEGINSELECT MIN(salary), MAX(salary)INTO v_minsalary, v_maxsalaryFROM employeesWHERE job_id = :NEW.job_id;IF :NEW.salary < v_minsalary OR:NEW.salary > v_maxsalary THENRAISE_APPLICATION_ERROR(-20505,'Out of range');END IF;
END;
UPDATE employees
SET salary = 3400
WHERE last_name = 'Davies';

出错:

ORA-04091: table USVA_TEST_SQL01_T01_EMPLOYEES is mutating,
trigger/function may not
see it
ORA-06512: at “USVA_TEST_SQL01_T01.CHECK_SALARY”, line 5
ORA-04088: error during execution of trigger
‘USVA_TEST_SQL01_T01.CHECK_SALARY’
3. WHERE last_name – ‘Davies’;

五、触发器的更多可能用途

不应该创建触发器来执行某些可以通过其他方式轻松完成的操作,例如通过检查约束或适当的对象权限。 但是有时你必须创建一个触发器,因为没有其他方法可以做需要的事情。
    以下示例只显示了必须创建触发器的三种情况。 还有更多!

(1)第一个例子

数据库安全性(谁可以做什么)通常由系统和对象权限控制。 例如,用户SCOTT需要更新EMPLOYEES行:

GRANT UPDATE ON employees TO scott;

但是,SCOTT被允许这样做时,单凭权限无法控制。 为此,我们需要一个触发器:

CREATE OR REPLACE TRIGGER weekdays_empBEFORE UPDATE ON employees
BEGIN
IF (TO_CHAR (SYSDATE, 'DY') IN ('SAT','SUN')) THENRAISE_APPLICATION_ERROR(-20506,'You may only change data during normal business hours.');
END IF;
END;

(2)第二个例子

数据库完整性(允许DML)通常由约束条件控制。 例如,每个员工的工资必须至少为500美元:

ALTER TABLE employees ADD CONSTRAINT ck_salary CHECK (salary >= 500);

如果一条业务规则指出员工的薪水可以提高但不降低,这个限制并不能阻止员工的薪水从700美元降低到600美元。 为此,我们需要一个行触发器。此代码显示在下一张幻灯片中。

现在我们不再需要约束了。

CREATE OR REPLACE TRIGGER check_salaryBEFORE UPDATE OF salary ON employeesFOR EACH ROWWHEN (NEW.salary < OLD.salaryOR NEW.salary < 500)
BEGINRAISE_APPLICATION_ERROR (-20508,'Do not decrease salary.');
END;

(3)第三个例子

您需要创建一个显示部门总工资单的报表。 你可以声明和使用这个游标:

...
CURSOR tot_sals ISSELECT SUM(salary)FROM employeesWHERE department_id = p_dept_id;
...

但是,如果在一个大型组织中,该部门有10,000名员工呢? 从EMPLOYEES表中抽取10,000行可能太慢。 下面展示了一个更快的方法来做到这一点。

首先,我们在DEPARTMENTS表中添加一个新列以存储每个部门的总工资单:

ALTER TABLE DEPARTMENTS ADD (total_salary NUMBER(12,2));

接下来,只填写当前总工资单的这一栏:

UPDATE departments dSET total_salary = (SELECT SUM(salary) FROM employeesWHERE department_id = d.department_id);

现在,我们必须在更改工资时保持这一新列。 这是通过使用DML行触发器完成的。

CREATE OR REPLACE PROCEDURE increment_salary(p_id IN NUMBER, p_new_sal IN NUMBER) IS
BEGINUPDATE departmentsSET total_salary = total_salary + NVL(p_new_sal,0)WHERE department_id = p_id;
END increment_salary;
CREATE OR REPLACE TRIGGER compute_salary
AFTER INSERT OR UPDATE OF salary OR DELETE
ON employees FOR EACH ROW
BEGIN
IF DELETING THEN increment_salary(:OLD.department_id,(:OLD.salary * -1));
ELSIF UPDATING THEN increment_salary(:NEW.department_id,(:NEW.salary - :OLD.salary));
ELSE increment_salary(:NEW.department_id,:NEW.salary);
END IF;
END;

Oracle入门(十四.22)之创建DDL和数据库事件触发器相关推荐

  1. java怎样用类模板创建对象_java入门(十四) | 面向对象(OOP)之类和对象

    上一期是变量,在java中变量总是无处不在,而变量其意就是可以改变的数,在一般情况下我们可以以变量类型,变量名,变量值来描述它 这一期是给面向对象(OOP)开了一个头,对他的概念,三大特征有了一个基础 ...

  2. Node学习十四 —— 使用node创建HTTP请求

    创建HTTP连接 Node擅长处理I/O操作,所以它不仅合适提供HTTP服务,也适合使用这些服务.接下来你将学习使用http模块和第三方模块执行和控制http请求. 在HTTP协议中,有两个重要的属性 ...

  3. [unreal4入门系列之十四] 在UE4中添加碰撞触发事件

    一.在HUD中显示消息 1) 在MyHUD.h中定义一个结构来表示我们的消息: #pragma once #include "GameFramework/HUD.h" #inclu ...

  4. Oracle入门(四)之查询基本信息

    一.查询基本信息 (1) 查询实例服务 SQL> show parameter instance name (2)查询数据库名字 SQL> show parameter db_name; ...

  5. Helm 3 完整教程(二十四):创建和使用子 chart

    推荐阅读 Helm3(K8S 资源对象管理工具)视频教程:https://edu.csdn.net/course/detail/32506 Helm3(K8S 资源对象管理工具)博客专栏:https: ...

  6. Oracle笔记 十四、查询XML操作、操作系统文件

    --1.随机数 select dbms_random.value from dual; select mod(dbms_random.random, 10) from dual; --0-9随机数 s ...

  7. slam入门——十四讲笔记(一)

    文章目录 第1讲 预备知识 第1部分 数学基础 第2讲 初识SLAM 2.1 引子:小萝卜的例子 2.2 经典视觉SLAM框架 2.3 SLAM问题的数学表述 2.4 实践:编程基础 1. 安装Lin ...

  8. Oracle资源管理器(二)-- 创建和使用数据库资源计划

    (参考 http://blog.csdn.net/mrluoe/article/details/7969436 -- 整理并实践通过) 第1步,创建3个用户 SQL> create user s ...

  9. 潭州课堂25班:Ph201805201 django 项目 第二十四课 文章主页 多级评论数据库设计 ,后台代码完成 (课堂笔记)...

    加载新闻评论功能 1.分析 业务处理流程: 判断前端传的新闻id是否为空,是否为整数.是否不存在 请求方法:GET url定义:'/news/<int:news_id>' 请求参数:url ...

最新文章

  1. 面试官:谈一下你对DDD的理解?我:马什么梅?
  2. 面向对象的三个基本特征 和 五种设计原则
  3. mysql日志的作用_MySQL 日志相关知识总结
  4. STM32 进阶教程 2 - micropython 使用
  5. 语音识别:时间序列的匹配算法(Needleman-Wunsch 算法)
  6. Flex, SilverLight 和 JavaFX
  7. 字符串(AC自动机(fail tree))
  8. angular8实现对象数组根据某个属性排序(多个也可以)
  9. UWP平台Taglib编译(1)
  10. linux中的rootfs/initrd/ramfs/initramfs
  11. 如何列出mongo shell中的所有集合?
  12. c语言实现字符串转16进制,C语言实现字符串中(10进制和16进制)转成十进制数(示例代码)...
  13. 跟着小甲鱼学习C语言
  14. 虚拟机linux删除文件后未释放空间,【Linux命令】删除大文件后磁盘空间未释放问题...
  15. java给word增加页码_Java 添加页码到Word文档
  16. link和import的区别,src和href的区别,css hark 以及HTML5及css3的新增特性
  17. 已经开工三天的软件测试工程师:被女足和谷爱凌感动到了
  18. instagram架构_Facebook如何收购Instagram内幕故事
  19. 适用于高级别自动驾驶的驾驶员可预见误用仿真测试
  20. epel yum 安装 trickle

热门文章

  1. [EDA]Quartus II 实验简答题
  2. [蓝桥杯][2013年第四届真题]核桃的数量-枚举(水题)
  3. 写出TREE-MINIMUM 和TREE-MAXIMUM的递归版本(算法导论第三版12.2-2)
  4. word List 10
  5. 深入理解 JVM Class文件格式(七)
  6. 基础篇--Java IO--概览
  7. P4175 [CTSC2008]网络管理(整体二分)
  8. P1829 [国家集训队]Crash的数字表格(推了好久的mobius反演)
  9. 2020 ICPC 上海 Sum of Log 数位dp + 状态剪枝
  10. P2607 [ZJOI2008]骑士