一、oracle触发器基本语法
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.]table_name | [schema.]view_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
PL/SQL_BLOCK | CALL procedure_name;

BEFORE: 在执行触发事件前执行触发器内容;

AFTER:在执行触发事件后执行触发器内容;

(貌似还存在第3中:instead of,主要用于视图。待学习....)

FOR EACH ROW: 行级触发器,对应的还有语句级触发器。

行级触发器,只要数据行符合触发条件,就执行1次触发器;

语句级触发器,整个语句操作作为触发事件,符合触发条件,则只执行1次触发器;(这个理解还不深刻)

NEW/OLD:只存在与FOR EACH ROW中。且update:NEW、OLD,insert:NEW,delete:OLD;

二、基础demo

说明:当更新子表CHILD的时候,把其对应父表的姓名拼接”123”。

create or replace trigger TEST_TRIGGER
before update ON "CHILD" for each row
declare
old_age number;
new_age number;
v_id number;
p_id number;
--PRAGMA AUTONOMOUS_TRANSACTION; -- 自治事务,独立于触发sql的事务
begin
old_age := :old.child_age;
new_age := :new.child_age;
v_id := :new.child_id;
p_id := :new.parent_id;
dbms_output.put_line('After: old='||old_age||',new='||new_age);
if 3>2 then
-- UPDATE CHILD set child_name = child_name||'123' where CHILD_ID = 5;
UPDATE parent set parent_name = parent_name||'' where PARENT_ID = p_id;
--:new.child_name := :old.child_name || '123';
dbms_output.put_line('if scope!');
end if;end TEST_TRIGGER;

奇葩问题: 如果trigger中存在if语法,

注意demo最后 end if;end TEST_TRIGGER;  如果不这么写(分成2行),此trigger在navicat中编译是通不过的。但在pl/sql中是正确的。

三、trigger的事务、自治事务

如果trigger不用自治事务,那么触发器的事务和触发触发器事件的事务是同一个。

我在测试的时候遇到的问题:1、目的:在更新child_age后,通过触发器更新其名字child_name。2、因为我要的确实更新后,才更新chile_name,所以我用的BEFORE。

如果不用自治事务,那么表示触发器和触发事件是处于同一事务(即便是after,触发事件的事务也是没提交的。),oracle是不允许对同一行记录再次进行DML的。

但是如果使用自治事务,这明显有个问题是,如果触发事件的语句被回滚,那么触发器是确定被触发、且被提交的。所以,此处不能用自治事务(我还真没想到什么场景要用到自治事务)

如何实现?

这时就要用到BEFORE/AFTER的区别了,通过前面知道了默认触发器和触发事件是在同一事务。那么可以通过BEFORE达到目的,直接在BEFORE中修改:new对应的字段值。如demo中的:

:new.child_name := :old.child_name || '123'; 这样,其实就会更新行所对应的字段值。

四、备注

在网上查了下对触发器的看法,发现大部分的观念都不推荐触发器。观点总结:1、触发器性能不好;2、触发器太隐蔽,容易被忽略;3、移植性低,难以维护。

对于性能,不清楚程度到底怎么样。

移植性,我接触的项目都不考虑。

隐蔽性,这很关键,如果项目管理不好。可能都不知道有这个触发器的存在。

综上,我只能了解到反正大家都不怎么推荐…

这说下为什么我要用的情况:有张表table_a,存在一个状态位a.status=[1,2,3,4,5,6…];当状态位为[4,5,6]时要给客户发送短信提醒。

存在的做法:1、在所有代码中,更改status的地方判断,直接调用发送短信(或者把短信放到短信池,定时发送。这有很大却别)。  2、定时器,检测状态位,然后发送。 3、触发器。

方式1: 我觉得很蠢,你要找到现在有的所有地方。如果后面新增一个地方修改status,别人不一定知道要发短信。(而且还不止这么简单,万一这update被回滚,你直接调短信发送不雪崩?如果是放到短信池还好,都回滚了。)

方式2: 有一个问题是,你要知道这行数据是不是状态改变过,且是没发送过短信的(麻烦,我没细想这)

方式3: 触发器,检测行的status,然后符合的insert一条短信到短信池,然后在定时检测短信池发送短信。

附录

[oracle官方文档 12c]CREATE TRIGGER Statement

ORACLE PL/SQL编程之八:   把触发器说透

【database】oracle触发器基础的更多相关文章

  1. ORACLE 触发器 基础

    --触发器--语法 CREATE OR REPLACE TRIGGER TRIGGER_NAME AFTER|BEFORE|INSTEAD OF [INSERT][OR UPDATE [OF COLU ...

  2. Oracle数据库基础入门《二》Oracle内存结构

    Oracle数据库基础入门<二>Oracle内存结构 Oracle 的内存由系统全局区(System Global Area,简称 SGA)和程序全局区(Program Global Ar ...

  3. oracle触发器加条件判断

    oracle触发器加条件判断,如果某个字段,isnode=0,那么不执行下面的方法,数据如下: create or replace trigger tr_basestation_insert_emp ...

  4. Oracle 触发器在日志管理开发中的应用

    摘要: 本文讨论了利用数据库中的触发器对日志管理进行设计与实现的方法, 是对原来在客户端软件中编写日志管理方法的一种改进, 并给出了 Oracle9i 中的实例演示.关键词: Oracle; 触发器; ...

  5. oracle触发器应用

    首先给大家推荐两篇我看后的博文,我已经内容转载过来: 1.对触发器的讲解 本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建 ...

  6. SQL server与Oracle触发器的创建与使用

    SQL Server 1创建触发器 GO BEGIN IF (object_id('WMY', 'tr') is not null) DROP trigger WMY END; GO CREATE T ...

  7. Oracle数据库基础入门《一》Oracle服务器的构成

    Oracle数据库基础入门<一>Oracle服务器的构成 Oracle 服务器是一个具有高性能和高可靠性面向对象关系型数据库管理系统,也是一 个高效的 SQL 语句执行环境. Oracle ...

  8. Oracle 触发器(二)

    Oracle触发器详解   触发器是许多关系数据库系统都提供的一项技术.在oracle系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块. 8.1 触发器类型 触发器在数据库里 ...

  9. Oracle 备份与恢复基础

    Oracle 备份与恢复基础 :三思笔记 备份与恢复 A whole database backup is either a consistent backup or an inconsistent ...

随机推荐

  1. HYSBZ_2002_分块

    http://www.lydsy.com/JudgeOnline/problem.php?id=2002 分块基础题,初次接触,很巧妙. OJ好像挂了,没法提交. #include<iostre ...

  2. Go语言实现:【剑指offer】把数组排成最小的数

    该题目来源于牛客网<剑指offer>专题. 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字 ...

  3. 20200110--python学习第八天

    今日内容 进制 对于计算机而言无论是计算机存储或是网络传输输入的本质都是:二进制:例如电脑上存储的视频/图形/文件/微信/qq的表情包/小视频都是二进制. 二进制:计算机内部 八进制: 十进制: 十六 ...

  4. 动态获取bind dns日志IP脚本

    #!/usr/bin/env python #_*_coding:utf-8_*_ ''' python deny_dns_allip.py your_filelog_name 动态获取dns日志的I ...

  5. 还是端口回流问题 TCP协议解析

    还是上一篇的问题 在一内部局域网中, client  内网地址为 10.0.0.2     web  服务器内网地址为 10.0.0.1    外网地址为  211.6.15.1    域名为  xx ...

  6. LVM知识梳理

    1 LVM介绍 LVM即logical volume manager逻辑卷管理,其主要特点是:可以动态地扩大和缩小分区大小,但前提是分区的文件系统必须是LVM格式的,lvm的实现需要安装lvm2软件包 ...

  7. -bash: warning: setlocale: LC_CTYPE: cannot change locale (zh_CN.UTF-8mb4): No such file or directory

    前几天登录服务器发现出现了这些个警告,一直没时间去处理他,今天难得有空,处理一下并记录下来,希望可以帮助到有需要的朋友. 警告信息如下: Last login: Tue May :: from 192 ...

  8. Quartz.NET - 课程 6: Cron 触发器

    译者注: 目录在这 [译]Quartz.NET 3.x 教程 原文在这 Lesson 6: CronTrigger 如果你需要一个类似日历概念而不是像 SimpleTrigger 那样指定间隔来调度作 ...

  9. nginx启动报错nginx: [error] open() "/usr/local/etc/nginx/logs/nginx.pid" failed

    问题:nginx启动的时候会报丢失pid的错误 nginx: [error] open() “/usr/local/var/run/nginx.pid” failed 解决方案: sudo nginx ...

  10. MySql的命令介绍

    1,连接数据库服务器命令 mysql -u 用户名 -p 密码 mysql是连接MySql数据库的命令,-u后跟用户名,-p后跟密码,如果登陆后展示"mysql",则表示登录成功. ...