Oracle数据库之触发器(二)

DML触发器
是指在进行insert、update或delete操作时触发的程序体。如果你想在用户对数据进行操作时,记录或限制其操作,就可以用DML触发器。
举例来说,我想统计我的网站用户的注册、注销或者更新个人信息等情况,我们就可以写如下一个触发器,每当有用户进行上述操作时,触发器会自动执行,并在log日志表中存储这些信息。

代码:
create or replace trigger user_log
before delete or insert or update
on users
for each row
declare
id number;
begin
select count(*)+1 into id from ts_log_users t;
if inserting then insert into ts_log_users t values (id,sysdate,(select count(*)+1 from ts_log_users t where t.class=‘create‘),‘create‘,:new.username);
elsif deleting then insert into ts_log_users t values (id,sysdate,(select count(*)-1 from ts_log_users where class=‘create‘),‘delete‘,:new.username);
else insert into ts_log_users t values (id,sysdate,(select t.count from ts_log_users t where create_date=(select max(t.create_date) from ts_log_users t)),‘update‘,:new.username);
end if;
end;

第一行定义触发器名字为user_log,create or replace意思是建立或如果存在一样名字的触发器则覆盖。

第二行关键字可以选择before和after,即操作前和操作后。
比如我想查看用户登录的ip情况,这时我们需要在用户成功登录后触发触发器,所以需写after。
而这里要对用户的增删改敏感,所以选择before。后面是操作定义,即什么样的操作会触发触发器。

第三行on后面接表名,即当用户对这个表进行操作时,触发触发器。
另外,操作为update时,可写成before update of 列名 on 表名,来使限制更加具体化。

第四行将触发器定义为行级触发器,即每当一行数据发生变化时,就触发一次触发器。
比如我一下更新了三个用户的信息,那么log日志表中就会生成三条数据。
如果不写这句话,则触发器只会在上述操作时,触发一次,形成一条数据。

第五行声明变量,用于存储和操作一些可用数据。

从begin到end为程序主体,读起来也很容易理解,主要有两个操作,
一是将log日志的数据量+1作为数据id赋值给之前定义的id变量。赋值用into完成。
第二个操作是一个if操作,分别完成了对增删改不同情况的处理。
处理主要为想log日志表插入数据,
如果是新建用户的话,则向log日志表插入数据id(上面得到的)、系统时间、
目前用户数量(即count下log日志中是create操作的数据)、
操作类别(此处为create)以及操作的用户名(:new.的意思就是新修改的数据,对比:old.使用,这两个字段在更新操作时会经常用到。
例如将更新前的数据插入到另一表中,则用:old.表示,新插入的数据则用:new.操作)。后两个是对delete和update的操作,类似上面不在赘述。

替代触发器
这类触发器仅仅应用在视图上。我举个例子就明白这个触发器的用处了。比如说,我提供给初级管理员老张一个视图,只显示用户的基本注册信息,如用户名、性别、民族等,而隐藏了用户密码、身高、体重这些私密信息(这些信息存在表中,老张看不到,因为我没给他看表的权限)。但有一天有个走后门的找老张想把自己的信息加到我数据库中,于是老张就对视图进行插入操作。可是问题来了,当插入一条关系户数据到表中时,我们需要其用户密码、身高体重等(设置了不为空),而老张看不到因此插不进去,因此报错无法操作。所以这时我们就可以写一个替代触发器,即如果老张对视图操作时,后面的表会自动插入一些随机密码等,以完成老张的视图操作。触发器定义格式类似于上面,这里不再赘述(因为我没用视图,所以没写)。

系统触发器
是在进行系统操作如startup、drop、alter、logon等时才会触发的。
下面我写一个,因为我的数据库给了好多人使用,老张、老王等,而他们经常在别的时间和地点登录数据库,我想看看这些登录情况,因此我写一个登录的触发器:

代码:create or replace trigger oracle_user_log
after logon
on database
declare
id number;
begin
select count(*)+1 into id from ts_o_log_users t;
insert into ts_o_log_users values (id,sys.login_user,sysdate,ora_client_ip_address);
end;

另附一些参考代码:

create or replace trigger testtrigger
 after insert on test1trige
 for each row
 declare v_flag number:=0;
 begin
 select count(0) into v_flag from test2trige where xh_id = :new.xh;
 if v_flag = 0 then
 insert into test2trige(xh_id,xsxm)  values(:new.xh,:new.xm);
 end if;
 end;
 
 
create or replace trigger trig_jzg_RYLX after insert or update
on GXJG_JZGRYLXGX for each row
declare
  v_sqlerrm varchar(4000);
  v_count_n number:=0;
begin
   
   select COUNT(0) into V_COUNT_n from [email protected]_zfoa  where yhm=:new.yhm and xydm in (‘20140503‘,‘20140504‘,‘20140505‘,‘20140506‘);
   if V_COUNT_n >0 and :new.yhlx not in(‘009‘,‘001‘) then
       update [email protected]_zfoa set  xydm=decode(:new.yhlx,‘2‘,‘20140503‘,‘006‘,‘20140504‘,‘008‘,‘20140505‘,‘004‘,‘20140506‘)--,‘009‘,‘20140503‘)
             where yhm=:old.yhm and xydm=decode(:old.yhlx,‘2‘,‘20140503‘,‘006‘,‘20140504‘,‘008‘,‘20140505‘,‘004‘,‘20140506‘);   
       update [email protected]_zfoa set  xydm=decode(:new.yhlx,‘2‘,‘20140503‘,‘006‘,‘20140504‘,‘008‘,‘20140505‘,‘004‘,‘20140506‘)--,‘009‘,‘20140503‘)
             where yhm=:new.yhm and xydm=(select xydm from [email protected]_zfoa where yhm=:new.yhm and xydm in (‘20140503‘,‘20140504‘,‘20140505‘,‘20140506‘));   
    
     --else
       -- insert into [email protected]_zfoa
               -- --  (xydm, jsdm, yhm, sjlsh)
               -- values
                --  (decode(:new.yhlx,‘2‘,‘20140503‘,‘006‘,‘20140504‘,‘008‘,‘20140505‘,‘004‘,‘20140506‘), ‘7‘, :new.yhm, ‘1‘);
   end if;
   
   select COUNT(0) into V_COUNT_n from [email protected]_zfoa  where yhm=:new.yhm and xydm in (‘20140503‘,‘20140504‘,‘20140505‘,‘20140506‘);
   if V_COUNT_n =0  then
       insert into [email protected]_zfoa
                  (xydm, jsdm, yhm, sjlsh)
                values
                  (decode(:new.yhlx,‘2‘,‘20140503‘,‘006‘,‘20140504‘,‘008‘,‘20140505‘,‘004‘,‘20140506‘), ‘7‘, :new.yhm, ‘1‘);
  end if;

select COUNT(0) into V_COUNT_n from [email protected]_zfoa  where yhm=:new.yhm;
   if  V_COUNT_n >0  then
       update [email protected]_zfoa set  zdm=decode(:new.yhlx,‘2‘,‘02‘,‘004‘,‘05‘,‘006‘,‘03‘,‘008‘,‘04‘,‘009‘,‘01‘,‘001‘,‘01‘) where yhm=:old.yhm;
      
   end if;
   
 --异常处理
Exception
  WHEN OTHERS Then
    v_sqlerrm := (Sqlerrm || chr(10) || dbms_utility.format_error_backtrace);
    Insert Into XT_ERRLOG
    Values
      (‘办公系统‘,
       ‘bmryxxbrylx‘,
       ‘yhm:‘ || :NEW.yhm,
       v_sqlerrm,
       to_char(sysdate, ‘yyyyMMddhh24miss‘));
end;

----异常处理表结构

-- Create table
create table XT_ERRLOG
(
  YWXTMC VARCHAR2(100),
  YWXTBM VARCHAR2(100),
  CWZDXX VARCHAR2(500),
  CWSJ   VARCHAR2(1000),
  GXBJ   VARCHAR2(22)
)
tablespace ZFDXC
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 448
    next 1
    minextents 1
    maxextents unlimited
  );
-- Add comments to the table
comment on table XT_ERRLOG
  is ‘系统错误日志表‘;
-- Add comments to the columns
comment on column XT_ERRLOG.YWXTMC
  is ‘业务系统名称(例:数据中心)‘;
comment on column XT_ERRLOG.YWXTBM
  is ‘业务系统表名(例:ZYDMB)‘;
comment on column XT_ERRLOG.CWZDXX
  is ‘显示会导致报错的字段(例如: XH:200010,BJDM:,ZYDM:5200)‘;
comment on column XT_ERRLOG.CWSJ
  is ‘错误时间(例:YYYYMMDDHH24MISS)‘;
comment on column XT_ERRLOG.GXBJ
  is ‘更新标记U/I‘;

时间: 2024-10-04 08:55:45

Oracle数据库之触发器(二)的相关文章

ORACLE数据库常用查询二

ORACLE数据库常用查询 1.查看表空间对应数据文件情况: SQL> SELECT TABLESPACE_NAME,FILE_NAME,BYTES/1024/1024 MB,AUTOEXTENSIBLE FROM DBA_DATA_FILES; TABLESPACE_NAME FILE_NAME MB AUTOEXTENSIBLE ------------------------------ ---------------------------------------------------

MySQL/Oracle数据库的基础(二)

MySQL/Oracle数据库 Oracle数据库管理系统是管理数据库访问的计算机软件,由Oracle数据库与Oracle实例构成 Oracle数据库:一个相关的操作系统文件集合,这些文件组织在一起,成为一个逻辑整体,即为Oracle数据库.Oracle数据库必须要与内存实例合作,才能对外提供数据管理服务. Oracle实例:位于物理内存里的数据结构,它由操作系统的多个后台进程和一个共享的内存池所组成,共享的内存池可以被进程锁访问. Oracle用它们来管理数据库访问 Oracle实例就是平常所

Oracle 数据库 体系结构 (二):服务器结构

目录 前言 Oracle 内存结构 Oracle 进程结构 文章总结 前言 上一篇文章体现了 Oracle 数据库的一些基本结构和存储结构,这篇文章将会讲到Oracle的服务器结构,实际上就是主要讲实例的结构.需要把这些底层的结构了解,在生产环境或是对Oracle才会有一些了解. Oracle服务器是由Oracle实例+Oracle数据库组成. Oracle实例是有SGA+后台进程组成. 每一个Oracle实例都有自己的SGA和独立的Oracle进程集. Oracle 内存结构 以上图很好说明了

教师信息管理系统(方式一:数据库为oracle数据库;方式二:存储在文件中)

方式一: 运行截图 数据库的sql语句: /*Navicat Oracle Data TransferOracle Client Version : 12.1.0.2.0 Source Server : ORCZYTSource Server Version : 120100Source Host : localhost:1521Source Schema : C##ZYT Target Server Type : ORACLETarget Server Version : 120100File

Oracle数据库配置方式二--使用Net Manager配置数据库

在Oracle安装配置中使用Net Configuration配置了数据库,今天给大家介绍第二种配置方式,Net Manager配置. 先找到我们的Net Manager的快捷方式,如下面截图 这个就是进入Net Manager的界面,点击服务命名,如图, 然后点击最左边的绿色的+ 号 起个网络服务名,就叫 myorcl吧 协议仍然选择TCP/IP,下一步 主机名填:localhost,端口号:1521 要访问的服务名是ORCL,是安装时填写的那个,连接类型如图所示 点击测试,测试一下 测试成功

Oracle数据库——触发器的创建与应用

一.涉及内容 1.理解触发器的概念.作用和类型. 2.练习触发器的创建和使用. 二.具体操作 (实验) 1.利用触发器对在scott.emp表上执行的DML操作进行安全性检查,只有scott用户登录数据库后才能向该表中执行DML操作.(第1题中,user是系统函数,返回当前用户.字符串中使用两个单引号表示一个单引号.) 要求:分别以system用户和scott用户对emp 表执行DML操作,试验触发器的运行效果. (1)在scott用户下创建触发器 语句: create or replace t

基于ORACLE数据库的循环建表及循环创建存储过程的SQL语句实现

一.概述 在实际的软件开发项目中,我们经常会遇到需要创建多个相同类型的数据库表或存储过程的时候.例如,如果按照身份证号码的尾号来分表,那么就需要创建10个用户信息表,尾号相同的用户信息放在同一个表中. 对于类型相同的多个表,我们可以逐个建立,也可以采用循环的方法来建立.与之相对应的,可以用一个存储过程实现对所有表的操作,也可以循环建立存储过程,每个存储过程实现对某个特定表的操作. 本文中,我们建立10个员工信息表,每个表中包含员工工号(8位)和年龄字段,以工号的最后一位来分表.同时,我们建立存储

学习oracle数据库引航二——后台进程

from 谭怀远--数据库领航 后台进程 一.system monitor(SMON) (非正常关闭后的)实例恢复 二.process monitor(PMON) 回滚事务 释放锁及其它资源 重启死掉的调度器.(在共享服务器中用).分配用户连到哪个服务器上. 在监听器中注册服务信息 三.DBWn和LGWR DBWRn下写入磁盘文件 四.check point(CKPT) 喊DBWn写脏数据 完后会更新DATAFILE的HEADER和控制文件的HEADER.而HEADER中有同步所需要的信息,即C

Oracle数据库PL/SQL存储过程游标触发器

创建一个添加FOOD的存储过程 create or replace procedure add_food_pro (name in varchar,price in number,description in varchar) as  begin insert into food (f_name,f_price,description)values(name,price,description); commit; end; --下面的代码是调用存储过程 begin add_food_pro('糖