当前位置: 首页 > news >正文

Oracle中用触发器实现自动记录表数据被修改的历史信息

  标签: Oracle触发器历时记录保存
 分类:
Oracle(5) 
 

Oracle中用触发器实现自动记录表数据被修改的历史信息

有一些比较重要的表字段每次修改需要做历史记录,以后可以查询这个表中某些字段如何被修改过。由什么改成了什么等。

我们先创建一个建议的订单表:

[sql] view plain copy

CREATE TABLE "TEST"."TB_BILL" ("BILL_ID" NUMBER(10) NOT NULL,   

"BILL_NO" VARCHAR2(64) NOT NULL, "AMOUNT" NUMBER(10, 3) NOT   

NULL, "PRICE" NUMBER(10, 3) NOT NULL, "DESCRIPTION"   

    VARCHAR2(1024) NOT NULL, "CREATE_DATE" DATE NOT NULL,   

CONSTRAINT "SYS_TB_BILL_PK_BILL_ID" PRIMARY KEY("BILL_ID"))    

为了方便测试,为此表创建用于自增长的序列:

[sql] view plain copy

CREATE SEQUENCE "TEST"."SQ_TB_BILL" INCREMENT BY 1 START WITH 1   

    MAXVALUE 1.0E28 MINVALUE 1 NOCYCLE   

    CACHE 20 NOORDER  

  1. 然后创建一个历史记录信息表,来保存历时信息:
    [sql] view plain copy
    1. CREATE TABLE "TEST"."TB_BILL_HISTORY" ("HIS_ID" NUMBER(10) NOT   
    2. NULL, "BILL_ID" NUMBER(10) NOT NULL, "CONTENT" VARCHAR2(1024)  
    3. NOT NULL, "EVENT_TIME" DATE DEFAULT sysdate NOT NULL,   
    4. "USER_ID" NUMBER(10) NOT NULL,   
    5. CONSTRAINT "SYS_TB_BILL_HISTORY_PK_HIS_ID" PRIMARY   
    6. KEY("HIS_ID"))    
    同样,为这个表创建序列:
    [java] view plain copy
    1. CREATE SEQUENCE "TEST"."SQ_TB_BILL_HISTORY" INCREMENT BY 1 START WITH 1   
    2.     MAXVALUE 1.0E28 MINVALUE 1 NOCYCLE   
    3.     CACHE 20 NOORDER  
  2. 关键时刻来临,我们为TB_BILL订单表创建用于修改的触发器:
    [sql] view plain copy
    1. CREATE OR REPLACE TRIGGER "TEST"."TG_TB_BILL_UPD_FIELDS_HIS"   
    2.     BEFORE  
    3. UPDATE OF "AMOUNT", "CREATE_DATE", "DESCRIPTION", "PRICE" ON "TEST"."TB_BILL" FOR EACH ROW DECLARE /*记录提单修改过的痕迹*/  
    4.   historyText TB_BILL_HISTORY.CONTENT%TYPE; /*记录日志的主要信息*/   
    5. BEGIN  
    6.   if :OLD.AMOUNT <> :NEW.AMOUNT then /*数量*/  
    7.     historyText:=concat(historyText,'数量:');  
    8.     historyText:=concat(historyText,replace(:OLD.AMOUNT,' ',''));  
    9.     historyText:=concat(historyText,'----->');  
    10.     historyText:=concat(historyText,replace(:NEW.AMOUNT,' ',''));  
    11.     historyText:=concat(historyText,';');  
    12. end if;  
    13.   if :OLD.PRICE <> :NEW.PRICE then /*价格*/  
    14.     historyText:=concat(historyText,'价格:');  
    15.     historyText:=concat(historyText,replace(:OLD.PRICE,' ',''));  
    16.     historyText:=concat(historyText,'----->');  
    17.     historyText:=concat(historyText,replace(:NEW.PRICE,' ',''));  
    18.     historyText:=concat(historyText,';');  
    19. end if;  
    20.   if (:OLD.DESCRIPTION <> :NEW.DESCRIPTION) or ((:OLD.DESCRIPTION is not null) and (:NEW.DESCRIPTION is null) ) or ((:NEW.DESCRIPTION is not null) and (:OLD.DESCRIPTION is null) ) then /*备注*/  
    21.     historyText:=concat(historyText,'备注:');  
    22.     historyText:=concat(historyText,replace(:OLD.DESCRIPTION,' ',''));  
    23.     historyText:=concat(historyText,'----->');  
    24.     historyText:=concat(historyText,replace(:NEW.DESCRIPTION,' ',''));  
    25.     historyText:=concat(historyText,';');  
    26. end if;  
    27.   /*将修改后的信息放入历史记录信息表*/  
    28.   if lengthb(historyText) > 1 then  
    29. insert into TB_BILL_HISTORY(HIS_ID,BILL_ID,CONTENT,EVENT_TIME,USER_ID) values(SQ_TB_BILL_HISTORY.nextval,:OLD.BILL_ID,historyText,sysdate,1);  
    30. end if;  
    31. END;  
  3. 接下来我们对订单表插入一条测试数据:
    [sql] view plain copy
    1. insert into TB_BILL(BILL_ID,BILL_NO,AMOUNT,PRICE,DESCRIPTION,CREATE_DATE) values(SQ_TB_BILL.nextval,'No.1',1000,9.9,'Desc1',sysdate);  

    此时我们查询TB_BILL的数据如下:


    查询历时记录信息表的数据如下:


  4. 然后,我们对订单表的数据进行修改,会触发上边创建的触发器:
    [sql] view plain copy
    1. update TB_BILL set AMOUNT=500,PRICE=9.8,DESCRIPTION='DESC2' where BILL_ID=1  

    此时,查看一下TB_BILL表的数据如下:


    下面我们来看看历时记录表的信息:


    OK,非常完美,我们看到了订单的修改的历时信息;无论修改了多少次,都会以流水账的方式保存,只需要在应用中提供一个订单号即可查寻到。

转载于:https://www.cnblogs.com/qazwsx3170/p/5019270.html

相关文章:

  • 直接拿来用!最火的Android开源项目(完结篇)
  • 睡前小dp-codeforce414B-dp+一点点想法
  • SlidingMenu-master中的example怎样导入eclipse运行
  • echarts.js
  • 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法
  • 使用Preference保存设置
  • Android小项目蓝牙电子钟
  • 百度地图使用案例代码
  • Handler的基本使用
  • Andriod Studio Clear Project或Rebuild Project出错
  • Activity的生命周期
  • javascript实现URL不缓存的方法
  • Android Studio VS Eclipse (还在用Eclipse?你OUT了!)
  • Android之TextView灵活使用
  • Android Studio安装后Fetching android sdk component information超时的解决方案
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • CSS实用技巧
  • CSS实用技巧干货
  • ES6简单总结(搭配简单的讲解和小案例)
  • es6要点
  • Fastjson的基本使用方法大全
  • isset在php5.6-和php7.0+的一些差异
  • js
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • SpriteKit 技巧之添加背景图片
  • Tornado学习笔记(1)
  • Vim Clutch | 面向脚踏板编程……
  • 对超线程几个不同角度的解释
  • 七牛云假注销小指南
  • 前端_面试
  • 手写一个CommonJS打包工具(一)
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 译米田引理
  • 在Unity中实现一个简单的消息管理器
  • ​比特币大跌的 2 个原因
  • #13 yum、编译安装与sed命令的使用
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (三)模仿学习-Action数据的模仿
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .net framework4与其client profile版本的区别
  • .NET Standard 的管理策略
  • .Net环境下的缓存技术介绍
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • @test注解_Spring 自定义注解你了解过吗?
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)