草庐IT

Oracle 触发器详解

何以解忧,唯有.. 2023-04-15 原文

一、概念

触发器是Oracle数据库的对象,类似存储过程和函数。存储过程和函数需要用户显示调用才执行,而触发器是由一个事件来触发运行,当某个事件发生时会自动地隐式运行,不能被显示的调用。

触发器的本质是存储过程,发生特定事件时Oracle会执行触发器中的代码,它的组成可以分为三个部分:

1、触发器执行的条件,即触发器被触发的事件

2、执行触发器的时间,发生事件之前(before)或发生事件之后(after)

3、触发器要做的事情,就是触发器被触发以后具体想执行的任务(PL/SQL语句块)

Oracle的触发器分为 DML触发器、DDL触发器、替代触发器 和 系统触发器。

二、DML触发器

基于DML操作的触发器,细分又可以分为行触发器和语句触发器。

2.1、语句触发器

DML操作(insert、delete、update),不管SQL语句影响的记录是多少行,触发器只触发一次。

2.2、行级触发器

DML操作(insert、delete、update),SQL语句影响了多少行记录,触发器就触发多少次。

行级触发器用for each row关键字。

2.3、DML触发器语法:

create [or replace] trigger 用户名.触发器名
       {before|after}      
       {delete|insert|update|[of列名]}
       on 表名
       [for each row [when 条件]]
declare
  定义变量。
begin
  PL/SQL语句块。                         
end;

参数说明:

{before|after}: 指定触发器是在对表的操作发生之前触发还是之后触发。

{delete|insert|update|[of列名]}: 触发在动作,可以指定多个动作,例如:insert or update。如果是update,update of 指定一个或多个字段,仅在这些字段被更新时才会触发。update of 的应用场景极少。

[for each row]: 表示是行级触发器。

[when 条件]: 只有满足when指定的条件,才会执行触发体中的代码,应用场景极少。

2.4、触发器谓词:

创建超女基本信息表T_GIRL,插入5条测试数据。

old谓词:执行前的字段的值的名称,比如update一个表时,使用:old.columnname是指执行update操作之前的列的值。

new谓词:执行后的字段的值的名称,比如update一个表时,使用:new.columnname是指执行 update操作之后的列的值。

可以在触发器体的语句块中使用 inserting、updating、deleting谓词,这些谓词会返回相应的DML操作的布尔值,如果为true,则表示执行了相应的insert、update、delete操作。

2.5、实例说明

1)准备测试数据,创建超女基本信息表T_GIRL,插入5条测试数据。

drop table T_GIRL;
create table T_GIRL
(
  id        char(4)         not null,   -- 编号
  name      varchar2(30)    not null,   -- 姓名
  primary key(id)                       -- 指定id为表的主键
);
insert into T_GIRL(id,name) values('0101','西施');
insert into T_GIRL(id,name) values('0102','貂禅');
insert into T_GIRL(id,name) values('0103','妲已');
insert into T_GIRL(id,name) values('0104','芙蓉姐姐');
insert into T_GIRL(id,name) values('0105','神密猫女');

2)创建SQL日志表。

drop table T_SQL_LOG;
create table T_SQL_LOG
(
  tname    varchar2(10),        -- 原表的表名。
  srcrowid rowid,               -- 原表rowid。
  sqltype  number(1),           -- SQL语句的类型:1-insert、2-update、3-delete。
  trname  varchar2(10)          -- 触发器名。
);

3)创建语触发器TR_GIRL_1,如果对T_GIRL表做了insert、update和delete操作,把操作记录在T_SQL_LOG表中。

create or replace trigger TR_GIRL_1
  before update or delete or insert
  on T_GIRL
begin
  if inserting then
    insert into T_SQL_LOG(tname,srcrowid,sqltype,trname) values('T_GIRL',null,1,'TR_GIRL_1');
  end if;
  if updating then
    insert into T_SQL_LOG(tname,srcrowid,sqltype,trname) values('T_GIRL',null,2,'TR_GIRL_1');
  end if;
  if deleting then
    insert into T_SQL_LOG(tname,srcrowid,sqltype,trname) values('T_GIRL',null,3,'TR_GIRL_1');
  end if;
end;

4)创建行级语触发器TR_GIRL_2,如果对T_GIRL表做了insert、update和delete操作,把每一行的操作记录在T_SQL_LOG表中。

create or replace trigger TR_GIRL_2
  before update or delete or insert
  on T_GIRL for each row
begin
  if inserting then
    insert into T_SQL_LOG(tname,srcrowid,sqltype,trname) values('T_GIRL',:new.rowid,1,'TR_GIRL_2');
  end if;
  if updating then
    insert into T_SQL_LOG(tname,srcrowid,sqltype,trname) values('T_GIRL',:new.rowid,2,'TR_GIRL_2');
  end if;
  if deleting then
    insert into T_SQL_LOG(tname,srcrowid,sqltype,trname) values('T_GIRL',:old.rowid,3,'TR_GIRL_2');
  end if;
end;

5)执行一条delete语句,从T_GIRL表中删除两行记录。

delete from T_GIRL where id in ('0101','0102');

6)查看T_SQL_LOG表中的结果。

三、DDL 触发器

当执行DDL语句时会被触发。按照作用范围,分为schema trigger 和 database trigger。schema trigger 作用在一个用户上,database trigger 作用在整个数据库所有用户上。

常用的DDL操作有:grant(授权),revoke(撤销授权),create(创建),drop(删除),alter(修改),comment(注释),audit(审核),rename(重命名)等。

3.1、DDL触发器语法

create [or replace] trigger 用户名.触发器名
       {before|after} {DDL事件} on {database|schema}
       [when 条件]
declare
  定义变量。
begin
  PL/SQL语句块。
end;

参数说明:

{before|after}: 触发器是在DDL事件之前、之后触发。

{database|schema}: 作用在一个用户上,还是全部的用户。

[when 条件]: 只有满足when指定的条件,才会执行触发体中的代码,应用场景极少。

3.2、DDL 事件

3.3、可用属性

3.4、实例说明

限制scott用户的DLL操作,创建数据库对象时发出警告,删除数据库对象时阻止。

1)创建触发器

create or replace trigger scott.no_drop
  before ddl on schema
begin
  if ora_sysevent='CREATE' then
    dbms_output.put_line('Warning !!! You have created a '||
                         ORA_DICT_OBJ_TYPE||' called '||
                         ORA_DICT_OBJ_NAME|| '; UserName:'||
                         ORA_DICT_OBJ_OWNER||'; IP:'||
                         ORA_CLIENT_IP_ADDRESS||'; event:'||
                         ORA_SYSEVENT);
  elsif ora_sysevent='DROP' then
    RAISE_APPLICATION_ERROR(-20000,'Cannot drop the '||
                            ORA_DICT_OBJ_TYPE||' named '||
                            ORA_DICT_OBJ_NAME ||' as requested by '||
                            ORA_DICT_OBJ_OWNER);
  end if;
end;

2)测试触器(创建表),用scott用户登录。

在上面创建的触发器中用到了dbms_output,在sqlplus中要先执行set serveroutput on;才能输出内容。

3)测试删除表,用scott用户登录。

4)测试删除表,用DBA用户登录,no_drop触发器只限scott用户,不限制其它用户。

有关Oracle 触发器详解的更多相关文章

  1. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  2. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  3. ruby-on-rails - 如何在 Rails Controller Action 上触发 Facebook 像素 - 2

    我有一个ruby​​onrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素

  4. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  5. ruby-on-rails - Ruby method_added 回调不触发包括模块 - 2

    我想写一点“Deprecate-It”库并经常使用“method_added”回调。但是现在我注意到在包含模块时不会触发此回调。是否有任何回调或变通方法,以便在某些内容包含到自身时通知类“Foobar”?用于演示的小Demo:#IncludingModulswon'ttriggermethod_addedcallbackmoduleInvisibleMethoddefinvisible"Youwon'tgetacallbackfromme"endendclassFoobardefself.method_added(m)puts"InstanceMethod:'#{m}'addedto'

  6. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  7. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  8. 如何判断oracle是否启动及启动oracle数据库 - 2

    plsql连接Oracle超时,完犊子了肯定是服务器断电了。得马上检查Oracle服务器状态1、检查数据库是否启动su-oracle切换到Oracle用户,输入sqlplus/assysdba显示连接状态。如果末尾显示的状态是Connectedtoanidleinstance.证明未启动2、启动数据库startup启动数据库,末尾出现Databaseopened说明数据库启动成功3、查看数据库监听是否正常先quit;断开Oracle连接,使用lsnrctlstatus查看监听状态,如果出现TNS-开头的Nolistener、Connectionrefused等错误,说明监听未启动4、启动数据库

  9. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

  10. 【详解】Docker安装Elasticsearch7.16.1集群 - 2

    开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建

随机推荐