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

【postgresql初级使用】视图上的触发器instead of,替代计划的rewrite,实现不一样的审计日志

instead of 触发器

专栏内容

  • postgresql使用入门基础
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • instead of 触发器
  • 概述
  • 机制原理
    • INSTEAD OF 触发器语法
    • INSTEAD OF 触发器执行步骤
    • 多触发器的优先级
  • 审计案例解析
    • 数据准备
      • 创建两张数据表
      • 创建视图
      • 创建执行函数
      • 创建触发器
    • 结果展示
      • 信息查看
      • 新员工入职
      • 变岗调薪
  • 总结
  • 结尾

概述


在postgresql 中,触发器与SQL标准相比,有一个扩展特性就是可以在视图上创建触发器。

在视图上的触发器类型是’INSTEAD OF`,可以在insert, update, delete事件的before或after进行触发,
本文就来详细分享一下,并通过一个实用的审计数据的案例来展示效果。

机制原理


下面先来介绍SQL语法,然后通过介绍它的执行过程,了解它的机制原理。

INSTEAD OF 触发器语法

视图触发器的创建语法如下:

CREATE TRIGGER trigger_name
INSTEAD OF [INSERT OR UPDATE OR DELETE]
ON table_name
FOR EACH ROW 
EXECUTE FUNCTION trigger_function;

在视图上的触发器,类型只有INSTEAT OF,而且它对应的触发器件有insert,update,delete,此处没有truncate事件。

另外,instead of 触发器也只能定义为行级触发器,这个原因下面会分析。

INSTEAD OF 触发器执行步骤

视图触发器执行的步骤如下

  • 当在视图上执行INSERT、UPDATE或DELETE操作时,如果为该视图定义了INSTEAD OF触发器,那么这些操作不会直接对视图或其基础表执行。
  • 相反地,INSTEAD OF触发器会代替这些操作执行。也就是说,对于需要修改的每一行,都会触发INSTEAD OF触发器。
  • 触发器的函数需要负责执行必要的修改到视图的基础表,并在适当的情况下返回修改后的行,以便在视图中显示。
  • 这允许开发者在不影响基础表结构的情况下,通过视图执行复杂的操作逻辑。

在这里插入图片描述

如果视图上没有INSTEAD OF触发器,那么对视图的操作必须被转换为对基础表的操作,是直接操作基础表。

多触发器的优先级

  • 除了INSTEAD OF触发器外,还可以在视图上定义在INSERT、UPDATE或DELETE操作之前或之后执行的触发器。
  • 但是,这些触发器只有在视图上也有INSTEAD OF触发器的情况下才会被触发。
  • 如果没有INSTEAD OF触发器,那么任何针对视图的SQL语句都必须被重写为影响基础表的语句,然后触发的是附加到基础表上的触发器。

审计案例解析


为了信息的安全,一般系统都会有审计这个功能,其中审计日志会把操作记录详细记录下来,会定期时行审计或者出问题时能够帮助回溯。

下面就来分享一个通过触发器实现的审计日志功能,大概设计如下:

  • 应用一般不会对物理表进行直接操作,而对给它们创建对应的视图,只看到部分数据;
  • 对于每个视图的操作事件,创建instead of类型的触发器;
  • 在视图触发器中,对于操作的类型,数据,以及操作者用户都记录到表中;

数据准备

创建两张数据表

  • 一张是数据信息表emp,记录员工的薪记信息;
  • 一张是审计数据表emp_audit, 记录操作类型,操作员,数据变动,以及时间。
CREATE TABLE emp (empname text PRIMARY KEY,salary integer
);
CREATE TABLE emp_audit(operation char(1) NOT NULL,userid text NOT NULL,empname text NOT NULL,salary integer,stamp timestamp NOT NULL
);

创建视图

CREATE VIEW emp_view AS
SELECT e.empname,e.salary,max(ea.stamp) AS last_updated
FROM emp e
LEFT JOIN emp_audit ea ON ea.empname = e.empname
GROUP BY 1, 2;

创建执行函数

  • 在delete时,先删除基础表的数据;如果删除成功,再插入审计表,操作类型为’D’,否则不操作审计表;
  • 在update时,同上,先更新基础表;如果成功,才插入审计表;
  • 在insert时,先插入基础表;然后操作审计表;
  • 每次都将操作时间更新为当前时间;
CREATE OR REPLACE FUNCTION update_emp_view() RETURNS TRIGGER AS $$
BEGINIF (TG_OP = 'DELETE') THENDELETE FROM emp WHERE empname = OLD.empname;IF NOT FOUND THEN RETURN NULL; END IF;OLD.last_updated = now();INSERT INTO emp_audit VALUES('D', current_user, OLD.*);RETURN OLD;ELSIF (TG_OP = 'UPDATE') THENUPDATE emp SET salary = NEW.salary WHERE empname = OLD.empname;IF NOT FOUND THEN RETURN NULL; END IF;NEW.last_updated = now();INSERT INTO emp_audit VALUES('U', current_user, NEW.*);RETURN NEW;ELSIF (TG_OP = 'INSERT') THENINSERT INTO emp VALUES(NEW.empname, NEW.salary);NEW.last_updated = now();INSERT INTO emp_audit VALUES('I', current_user, NEW.*);RETURN NEW;END IF;
END;
$$ LANGUAGE plpgsql;

创建触发器

在视图emp_view上创建instead of类型的触发器,使用上面定义的函数。

CREATE TRIGGER emp_auditINSTEAD OF INSERT OR UPDATE OR DELETE ON emp_viewFOR EACH ROW EXECUTE FUNCTION update_emp_view();

结果展示

测试一下审计模块的效果。

信息查看

员工管理系统中,对于薪资表结构如下:

postgres=> \d emp_viewView "senlleng.emp_view"Column    |            Type             | Collation | Nullable | Default
--------------+-----------------------------+-----------+----------+---------empname      | text                        |           |          |salary       | integer                     |           |          |last_updated | timestamp without time zone |           |          |
Triggers:emp_audit INSTEAD OF INSERT OR DELETE OR UPDATE ON emp_view FOR EACH ROW EXECUTE FUNCTION update_emp_view()

新员工入职

有新员工入职,录入新员工的薪资。

postgres=> insert into emp_view values('zhanglei', 10000);
INSERT 0 1
postgres=> insert into emp_view values('wangguo', 8000);
INSERT 0 1
postgres=> select * from emp_audit ;operation |  userid  | empname  | salary |           stamp
-----------+----------+----------+--------+----------------------------I         | senllang | zhanglei |  10000 | 2024-06-06 08:13:05.829596I         | senllang | wangguo  |   8000 | 2024-06-06 08:13:24.125127
(2 rows)

有两名新员工入职,可以看到是那个操作员录入的,并且当前录入的时间,信息都可以看到。

变岗调薪

当人员调岗时,对应的薪资也会发生变化;

或者人员离职时,需要删除对应的记录。

postgres=> update emp_view set salary = 7500 where empname='wangguo';
UPDATE 1
postgres=> delete from emp_view where empname='zhanglei';
DELETE 1
postgres=> select * from emp_audit ;operation |  userid  | empname  | salary |           stamp
-----------+----------+----------+--------+----------------------------I         | senllang | zhanglei |  10000 | 2024-06-06 08:13:05.829596I         | senllang | wangguo  |   8000 | 2024-06-06 08:13:24.125127U         | senllang | wangguo  |   7500 | 2024-06-06 08:14:30.737416D         | senllang | zhanglei |  10000 | 2024-06-06 08:14:53.089083
(4 rows)

当然审计表的权限是非常高的,只有在审计系统中才能查看,而且审计数据是不能删除的。

总结


在视图上的instead of 触发器,可以将原本的执行计划重写 替换为触发器执行,这样可以进行更为复杂的动作,这里以审计为例,演示了触发器的效果。

结尾


非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

相关文章:

【postgresql初级使用】视图上的触发器instead of,替代计划的rewrite,实现不一样的审计日志

instead of 触发器 ​专栏内容: postgresql使用入门基础手写数据库toadb并发编程 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 文章目录 inst…...

window.setInterval(func,interval)定时器

window.setInterval()是JavaScript中的方法,用于在指定的时间间隔重复执行某个函数或代码块。它接受两个参数,第一个参数是要执行的函数或代码块,第二个参数是时间间隔(以毫秒为单位)。 以下是使用window.setInterval…...

Einstein Summation 爱因斯坦求和 torch.einsum

Einstein Summation 爱因斯坦求和 torch.einsum flyfish 理解爱因斯坦求和的基本概念和语法,这对初学者来说可能有一定难度。对于不熟悉该表示法的用户来说,可能不如直接的矩阵乘法表达式易于理解。 整个思路是 向量的点积 -》矩阵乘法-》einsum 向…...

TCP攻击是怎么实现的,如何防御?

TCP(Transmission Control Protocol)是互联网协议族中的重要组成部分,用于在不可靠的网络上提供可靠的数据传输服务。然而,TCP协议的一些特性也使其成为攻击者的目标,尤其是DDoS(Distributed Denial of Ser…...

Chrome DevTools开发者调试工具

Chrome DevTools 是一个功能强大的网页开发工具,集成在谷歌浏览器中,帮助开发者调试和优化网页应用。以下是详细的功能说明和使用技巧: 1. 打开 DevTools 快捷键:按下 F12 或 CtrlShiftI(Windows/Linux)或…...

产品创新管理:从模仿到引领,中国企业的创新之路

一、引言 在全球化竞争日益激烈的今天,科技创新已成为推动国家经济增长和社会进步的关键动力。中国自改革开放四十年来,在科技创新领域取得了举世瞩目的成就,从跟踪模仿到自主研发,再到自主创新、开放创新和协同创新并举&#xf…...

Android 日志实时输出

开发中如果只是单纯的应用开发,Android studio基本上可以满足,但是如果应用和系统联调那就得用logcat实时输出了,我这里都是总结的实用经验,没那么多花里胡哨 Android 日志实时输出 1、输出 android log //分步,进入s…...

JavaEE初阶---多线程编程(一.线程与进程)

目录 🤣一.线程与进程的概念与联系: 进程的基本概念: 线程的基本概念: 进程和线程的区别与联系: 🙃代码执行实列: 1.通过继承Thread父类来实现多线程 2.通过实现Runnable接口来实现多线程…...

react+vite创建

要在本地初始化一个结合了React和Vite的项目,你可以遵循以下步骤: 1、安装Node.js: 确保你的机器上已安装了Node.js。如果未安装,请前往Node.js官网下载并安装。 2、使用终端或命令提示符: 打开你的终端(…...

软考 系统架构设计师系列知识点之杂项集萃(29)

接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(28) 第46题 以下描述中,( )不是嵌入式操作系统的特点。 A. 面向应用,可以进行裁剪和移植 B. 用于特定领域,不需要支持多任…...

[Qt开发]当我们在开发兼容高分辨率和高缩放比、高DPI屏幕的软件时,我们在谈论什么。

前言 最近在开发有关高分辨率屏幕的软件,还是做了不少尝试的,当然我们也去网上查了不少资料,但是网上的资料也很零碎,说不明白,这样的话我就做个简单的总结,希望看到这的你可以一次解决你有关不同分辨率下…...

uniapp视频组件层级太高,解决方法使用subNvue原生子体窗口

目录 前言 先看一下uniapp官网的原话: subNvue的一些参数介绍 subNvues使用方法: 绑定id 显示 subNvue 弹出层 subNvue.show() 参数信息 subNvue.hide() 参数信息 在使用subNvue 原生子体窗口 遇到的一些问题 前言 nvue 兼容性 以及使用方式 控…...

java项目使用jsch下载ftp文件

pom <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version> </dependency>demo1&#xff1a;main方法直接下载 package com.example.controller;import com.jcraft.jsch.*; im…...

指针(初阶1)

一.指针是什么 通俗的讲&#xff0c;指针就是地址&#xff0c;其存在的意义就像宾馆房间的序号一样是为了更好的管理空间。 如下图&#xff1a; 如上图所示&#xff0c;指针就是指向内存中的一块空间&#xff0c;也就相当于地址 二.一个指针的大小是多少 之前我们学习过&#x…...

MySQL实体类框架

实现mysql数据库的增删改查功能 import com.mchange.v2.collection.MapEntry; import lombok.Data; import org.junit.jupiter.api.Test;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.*; import java.sql.*; …...

数据结构之初始泛型

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 深入了解包装类 包装类的由来 装箱与拆箱 面试题 泛型 泛型的语法与使用…...

【网络编程开发】7.TCP可靠传输的原理

7.TCP可靠传输的原理 TCP实现可靠传输的原理主要基于序列号和确认应答、超时重传、滑动窗口、连接管理机制以及拥塞控制等多重机制。 TCP&#xff08;Transmission Control Protocol&#xff09;&#xff0c;即传输控制协议&#xff0c;是网络通信中的一种重要协议&#xff0…...

视觉SLAM十四讲:从理论到实践(Chapter8:视觉里程计2)

前言 学习笔记&#xff0c;仅供学习&#xff0c;不做商用&#xff0c;如有侵权&#xff0c;联系我删除即可 一、目标 1.理解光流法跟踪特征点的原理。 2.理解直接法是如何估计相机位姿的。 3.实现多层直接法的计算。 特征点法存在缺陷&#xff1a; 二、光流(Optical Flow) …...

C语言过度C++语法补充(面向对象之前语法)

目录 1. C相较于C语言新增的语法 0. C 中的输入输出 1. 命名空间 1. 我们如何定义一个命名空间&#xff1f; 2. 如何使用一个命名空间 3. 命名空间中可以定义什么&#xff1f; 4. 在 相同或者不同 的文件中如果出现 同名的命名空间 会如何&#xff1f; 5. 总结~~撒花~~…...

类和对象(二)(C++)

初始化列表 class Date{public:Date(int year, int month, int day){_year year;_month month;_day day;}private:int _year;int _month;int _day;}; 虽然上述构造函数调用之后&#xff0c;对象中已经有了一个初始值&#xff0c;但是不能将其称为对对象中成员变量的初始化…...

Chrome DevTools解密:成为前端调试大师的终极攻略

Chrome DevTools是一套内置于Google Chrome浏览器中的开发者工具&#xff0c;它允许开发者对网页进行调试、分析和优化。本文将全面介绍DevTools的功能、使用方法以及注意事项&#xff0c;帮助开发者更好地利用这些工具来提升开发效率和网页性能。 一、简介 1. DevTools是什么…...

【python】OpenCV—Cartoonify and Portray

参考来自 使用PythonOpenCV将照片变成卡通照片 文章目录 1 卡通化codecv2.medianBlurcv2.adaptiveThresholdcv2.kmeanscv2.bilateralFilter 2 肖像画cv2.divide 1 卡通化 code import cv2 import numpy as npdef edge_mask(img, line_size, blur_value):gray cv2.cvtColor(…...

制作AI问答机器人:从0到1的完整指南

在数字化转型的浪潮中&#xff0c;企业正追求更高效、智能的客户服务解决方案。AI问答机器人以其快速响应、全天候服务和持续学习的能力&#xff0c;成为了提升客户满意度和加速业务发展的关键工具。本文将深入探讨如何制作一个企业级的AI问答机器人&#xff0c;并强调其功能体…...

mysql 数据库datetime 类型,转换为DO里面的long类型后,只剩下年了,没有了月和日

解决方法也简单&#xff1a; 自定义个一个 Date2LongTypeHandler <resultMap id"BeanResult" type"XXXX.XXXXDO"><result column"gmt_create" property"gmtCreate" jdbcType"DATE" javaType"java.lang.Long&…...

信息系统项目管理师0148:输出(9项目范围管理—9.3规划范围管理—9.3.3输出)

点击查看专栏目录 文章目录 9.3.3 输出 9.3.3 输出 范围管理计划 范围管理计划是项目管理计划的组成部分&#xff0c;描述将如何定义、制定、监督、控制和确认项 目范围。范围管理计划用于指导如下过程和相关工作&#xff1a; ①制定项目范围说明书&#xff1b;②根据详细项目范…...

解决 SQLyog 连接 MySQL 8 连不上和 SQLyog Trial 试用到期的问题

今天发现 SQLyog 突然连不上 MySQL 了&#xff0c;跟之前不一样的地方就是我升级了 MySQL&#xff0c;升级到了 MySQL 8。 原来是因为 MySQL 8 引入了新的密码验证机制。在 MySQL 8 中默认的密码验证插件从 mysql_native_password 更换为 caching_sha2_password。我的 SQLYog …...

go语言内置预编译 //go:embed xxx 使用详解

在go语言里面&#xff0c;我们可以使用一个“类注释”的语法来来让编译器帮助我们在编译的时候将一些文件或者目录读取到指定的变量中来供我们使用。 go:embed语法&#xff1a; //go:embed 文件或者目录路径 var 变量名 变量类型 说明&#xff1a; 文件或者目录路径 可以…...

数据挖掘--挖掘频繁模式、关联和相关性:基本概念和方法

频繁项集、闭项集和关联规则 频繁项集&#xff1a;出现的次数超过最小支持度计数阈值 闭频繁项集&#xff1a;一个集合他的超集(包含这个集合的集合)在数据库里面的数量和这个集合在这个数据库里面的数量不一样,这个集合就是闭项集 如果这个集合还是频繁的,那么他就是极大频…...

Locust:用Python编写可扩展的负载测试

Locust&#xff1a;简化性能测试&#xff0c;让负载模拟更直观- 精选真开源&#xff0c;释放新价值。 概览 Locust是一个开源的性能和负载测试工具&#xff0c;专门用于HTTP和其他协议的测试。它采用开发者友好的方法&#xff0c;允许用户使用普通的Python代码来定义测试场景。…...

【Neo4j】Windows11使用Neo4j导入CSV数据可视化知识图谱

Windows11使用Neo4j导入CSV数据可视化知识图谱 序1. 安装JDK21&#xff08;1&#xff09;下载&#xff08;2&#xff09;安装&#xff08;3&#xff09;环境配置 2. 安装Neo4j&#xff08;1&#xff09;下载&#xff08;2&#xff09;解压安装&#xff08;3&#xff09;环境配置…...

做网站的图片需要多少钱/推广赚钱的软件

最近在做报表&#xff0c;跟数据库打交道的比较多&#xff0c;所以特意来总结一下mysql的联合查询&#xff1b; 查询常用的字句 where(条件查询)、having&#xff08;筛选&#xff09;、group by&#xff08;分组&#xff09;、order by&#xff08;排序&#xff09;、limit&am…...

哈尔滨做网站优化/加强服务保障满足群众急需i

一、RTP传输协议 二、RTCP数据传输控制协议 三、 RTSP实时流媒体协议 四、 RSVP资源预留协议 ------------------------------------------------------------------------------------------------------------------- 流媒体实现的关键技术是流式传输&#xff0c;因此&#x…...

聊城做网站信息/媒体推广

1、HBase是否支持事务&#xff0c;支持到什么程度。 2、列族的数目跟性能的关系&#xff0c;越大越好&#xff1f; 3、为什么要设计列族&#xff1f; 4、同一个列能放在不同的列族吗&#xff1f; 5、...

做网站分前台后端吗/男生技能培训班有哪些

题库第2版 包括 Java 集合、JVM、多线程、并发编程、设计模式、Spring全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、Python、HTML、CSS、Vue、React、JavaScript、Android 大数据、阿…...

江苏住房和城乡建设厅网站/合肥百度推广排名优化

前言&#xff1a;前篇介绍了mysql的备份方法&#xff0c;但备份不是越多越好&#xff0c;如果磁盘空间不够用&#xff0c;我需要保留近一个周的备份就可以了&#xff0c;那就需要删除备份脚本了&#xff0c;特别注意删除操作比较危险&#xff0c;变量传参要进行二次确认。 下面…...

如何用织梦cms做网站/新闻头条今日要闻

转自&#xff1a;https://wenku.baidu.com/view/1ef7c985b9d528ea81c779b8.html 在人像和微距摄影中经常会遇到背景虚化的手法。所谓背景虚化&#xff0c;就是说在保证被摄主体清晰的同时&#xff0c;将远处的背景模糊掉&#xff0c;从而突出被摄主体。很多人会问&#xff0c;…...