【database】oracle触发器基础
一、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
【database】oracle触发器基础的更多相关文章
- ORACLE 触发器 基础
--触发器--语法 CREATE OR REPLACE TRIGGER TRIGGER_NAME AFTER|BEFORE|INSTEAD OF [INSERT][OR UPDATE [OF COLU ...
- Oracle数据库基础入门《二》Oracle内存结构
Oracle数据库基础入门<二>Oracle内存结构 Oracle 的内存由系统全局区(System Global Area,简称 SGA)和程序全局区(Program Global Ar ...
- oracle触发器加条件判断
oracle触发器加条件判断,如果某个字段,isnode=0,那么不执行下面的方法,数据如下: create or replace trigger tr_basestation_insert_emp ...
- Oracle 触发器在日志管理开发中的应用
摘要: 本文讨论了利用数据库中的触发器对日志管理进行设计与实现的方法, 是对原来在客户端软件中编写日志管理方法的一种改进, 并给出了 Oracle9i 中的实例演示.关键词: Oracle; 触发器; ...
- oracle触发器应用
首先给大家推荐两篇我看后的博文,我已经内容转载过来: 1.对触发器的讲解 本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建 ...
- SQL server与Oracle触发器的创建与使用
SQL Server 1创建触发器 GO BEGIN IF (object_id('WMY', 'tr') is not null) DROP trigger WMY END; GO CREATE T ...
- Oracle数据库基础入门《一》Oracle服务器的构成
Oracle数据库基础入门<一>Oracle服务器的构成 Oracle 服务器是一个具有高性能和高可靠性面向对象关系型数据库管理系统,也是一 个高效的 SQL 语句执行环境. Oracle ...
- Oracle 触发器(二)
Oracle触发器详解 触发器是许多关系数据库系统都提供的一项技术.在oracle系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块. 8.1 触发器类型 触发器在数据库里 ...
- Oracle 备份与恢复基础
Oracle 备份与恢复基础 :三思笔记 备份与恢复 A whole database backup is either a consistent backup or an inconsistent ...
随机推荐
- 重读es6, 正确了解promise中catch的用法
前言 在最近的项目中,用到了es6的promise语法,发现promise.prototype.catch 并不只是单单reject抛出的回调函数,所以今天做一些笔录,防止以后在项目中又碰到这样的问题 ...
- 《自拍教程14》Linux的常用命令
Linux操作系统, 包括我们大家熟知的Android, Ubuntu, Centos, Red Hat, UOS等. 这些常用命令先大概了解下,当然能熟练掌握并运用到实际工作中那最好不过了. 后续技 ...
- Java中类锁和对象锁
类锁 类锁 锁的其实是类的Class对象,类锁的代码写法是对类方法加synchronize,或者 synchronize(xx.class){} 对象锁 对象锁 锁的是类的实例对象,对象锁的形式有 对 ...
- pytorch之 RNN classifier
import torch from torch import nn import torchvision.datasets as dsets import torchvision.transforms ...
- pytorch之 batch_train
import torch import torch.utils.data as Data torch.manual_seed(1) # reproducible BATCH_SIZE = 5 # BA ...
- [Redis-CentOS7]Redis设置连接密码(九)
设置Redis密码 修改/etc/redis.conf 一定要强密码redis为内存存储 抗暴力破解强 requirepass password 重启服务 systemctl restart redi ...
- PHP常见代码执行后门函数
PHP常见代码执行后门函数 代码执行: 应用程序在调用一些能够将字符串转换为代码的函数(例如php中的eval中),没有考虑用户是否控制这个字符串,将造成代码执行漏洞. 常见php代码执行函数介绍 常 ...
- C#使用Environment.TickCount 自定义的定时器类
Environment.TickCount, 官网介绍:一个 32 位带符号整数,它包含自上次启动计算机以来所经过的时间(以毫秒为单位). *由于 TickCount 属性值的值是32位有符号整数,因 ...
- springcloud vue.js 微服务 分布式 activiti工作流 前后分离 shiro权限 集成代码生成器
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- MYSQL使用group by,如何查询出总记录数
比如有这样一条SQL,根据t.user_id,t.report_date两个字段统计 这样前端页面能展示数据,但往往需要一个总记录数,在有分页的情况下用到 一种解决方法是在外面套一层,然后对其coun ...