青少年编程与数学 02-007 PostgreSQL数据库应用 14课题、触发器的编写

青少年编程与数学 02-007 PostgreSQL数据库应用 14课题、触发器的编写

  • 一、触发器
  • 二、创建
      • 1. 创建触发器函数
      • 2. 创建触发器
      • 3. 示例
  • 三、用途
  • 四、触发器和存储过程的区别和联系
      • 区别:
      • 联系:
  • 五、应用示例
      • 步骤 1: 创建员工表
      • 步骤 2: 创建审计日志表
      • 步骤 3: 创建触发器函数
      • 步骤 4: 创建触发器
      • 完整示例说明
      • 测试触发器

课题摘要: 本课题介绍了PostgreSQL中触发器的编写和应用。触发器是数据库对象,用于在特定表上的数据操作前或后自动执行代码,如自动更新数据、维护审计日志等。触发器的特点包括事件驱动、行级操作、自动执行等。创建触发器涉及定义触发器函数和触发器本身,触发器函数需返回trigger类型并接受特定参数。触发器的用途包括确保数据完整性、自动更新相关数据、审计和日志记录等。触发器和存储过程的区别在于触发时机、用途、执行上下文、参数、返回值和事务管理。应用示例展示了如何创建触发器以自动记录员工信息更新到审计日志表。触发器是自动化数据库操作的强大工具,但需谨慎使用以避免性能问题和复杂性。


一、触发器

在PostgreSQL中,触发器是一种数据库对象,它允许用户定义在特定数据库表上的行级操作之前或之后自动执行的代码。触发器可以用来执行各种任务,如自动更新数据、维护审计日志、检查数据完整性等。

触发器的主要特点包括:

  1. 事件驱动:触发器是由特定的数据库事件触发的,如INSERT、UPDATE或DELETE操作。

  2. 行级操作:触发器可以在每行数据上执行,这意味着它们可以在数据被插入、修改或删除之前或之后对每行数据进行操作。

  3. 自动执行:触发器不需要显式调用,它们会在定义的事件自动发生时执行。

  4. 灵活性:触发器可以定义为在操作之前(BEFORE)或之后(AFTER)执行,也可以定义为INSTEAD OF触发器,完全替代原始操作。

  5. 嵌套触发器:一个表可以有多个触发器,它们可以嵌套,即在一个触发器内部调用另一个触发器。

  6. 限制:触发器不能返回值,它们只能执行一些副作用,如更新其他表或记录日志。

触发器的创建和使用需要谨慎,因为不当的触发器可能会影响数据库性能,并且可能会使数据库逻辑变得复杂和难以维护。在PostgreSQL中,触发器通常使用PL/pgSQL(PostgreSQL的过程语言)来编写。

二、创建

在PostgreSQL中创建触发器涉及几个步骤,包括定义触发器函数和创建触发器本身。以下是创建触发器的基本步骤:

1. 创建触发器函数

首先,你需要创建一个函数,这个函数将包含触发器要执行的代码。这个函数必须返回trigger类型,并且必须接受特定的参数。

CREATE OR REPLACE FUNCTION function_name()
RETURNS TRIGGER AS $$
BEGIN-- 在这里编写触发器逻辑-- 例如,更新另一张表的数据INSERT INTO audit_log(table_name, operation, row_data)VALUES (TG_TABLE_NAME, TG_OP, row_to_json(NEW));-- 对于INSERT或UPDATE触发器,可以使用NEW变量-- 对于DELETE触发器,可以使用OLD变量RETURN NEW; -- 对于INSERT或UPDATE触发器RETURN OLD; -- 对于DELETE触发器
END;
$$ LANGUAGE plpgsql;

2. 创建触发器

创建了触发器函数之后,你需要定义触发器本身,指定触发器的名称、触发事件、触发时机(BEFORE、AFTER或INSTEAD OF)以及关联的表和触发器函数。

CREATE TRIGGER trigger_name
BEFORE INSERT OR UPDATE ON table_name
FOR EACH ROW
EXECUTE FUNCTION function_name();

这里的参数解释如下:

  • trigger_name:你为触发器指定的名称。
  • BEFORE INSERT OR UPDATE:指定触发器在插入或更新操作之前触发。
  • table_name:触发器关联的表。
  • FOR EACH ROW:指定触发器对每一行操作都触发。
  • EXECUTE FUNCTION function_name():指定触发器函数的名称。

3. 示例

假设你有一个名为employees的表,你想要在每次更新或插入员工信息时,自动记录这些更改到一个名为audit_log的日志表中。以下是如何实现:

-- 创建触发器函数
CREATE OR REPLACE FUNCTION log_employee_changes()
RETURNS TRIGGER AS $$
BEGINIF TG_OP = 'INSERT' THENINSERT INTO audit_log(employee_id, operation, change_data)VALUES (NEW.id, 'INSERT', row_to_json(NEW));ELSIF TG_OP = 'UPDATE' THENINSERT INTO audit_log(employee_id, operation, change_data)VALUES (NEW.id, 'UPDATE', row_to_json(NEW));END IF;RETURN NEW;
END;
$$ LANGUAGE plpgsql;-- 创建触发器
CREATE TRIGGER track_employee_changes
AFTER INSERT OR UPDATE ON employees
FOR EACH ROW
EXECUTE FUNCTION log_employee_changes();

在这个例子中,log_employee_changes函数会在每次对employees表进行插入或更新操作后执行,将更改记录到audit_log表中。触发器track_employee_changes会在每次插入或更新操作后触发这个函数。

三、用途

在PostgreSQL中,触发器有多种用途,它们可以帮助自动化数据库中的各种操作和维护任务。以下是触发器的一些常见用途:

  1. 数据完整性

    • 确保数据的一致性和完整性,例如,通过检查数据值的范围或格式来防止无效数据的插入或更新。
    • 强制执行业务规则,比如,自动设置或计算某些字段的值。
  2. 自动更新相关数据

    • 在一个表中更新数据时,自动更新另一个表中相关联的数据,例如,更新库存数量时自动更新订单状态。
  3. 审计和日志记录

    • 记录数据的变更历史,包括插入、更新或删除操作,这对于跟踪数据变化和进行审计非常有用。
    • 记录用户操作,用于安全监控和合规性检查。
  4. 数据同步

    • 在多个表或数据库之间同步数据,确保数据的一致性。
  5. 复杂业务逻辑

    • 实现复杂的业务逻辑,这些逻辑可能涉及多个表和字段,不适合在应用程序层面处理。
  6. 数据清洗和转换

    • 在数据被插入或更新到数据库之前,对其进行清洗和转换,以确保数据符合特定的格式或标准。
  7. 权限和安全

    • 检查用户权限,确保只有授权用户才能执行特定的数据库操作。
    • 监控和记录对敏感数据的访问。
  8. 性能优化

    • 通过触发器自动维护索引,以优化查询性能。
  9. 数据备份和恢复

    • 在数据被删除之前,自动将其备份到另一个表或数据库中,以便在需要时可以恢复。
  10. 事件驱动的数据处理

    • 触发器可以作为事件驱动架构的一部分,响应数据库事件并触发其他系统或服务的操作。

触发器提供了一种强大的机制来自动化数据库操作,但它们也应谨慎使用,因为不当的触发器可能会导致性能问题、复杂的调试问题以及难以追踪的数据流。因此,在设计数据库和应用程序时,应仔细考虑是否需要使用触发器,以及如何有效地实现它们。

四、触发器和存储过程的区别和联系

在PostgreSQL中,触发器(Trigger)和存储过程(Stored Procedure)都是数据库中用于封装SQL代码和逻辑的数据库对象,但它们在用途、行为和触发方式上有所不同。以下是触发器和存储过程之间的区别和联系:

区别:

  1. 触发时机

    • 触发器:自动触发,通常在INSERT、UPDATE、DELETE等数据操作之前或之后自动执行。
    • 存储过程:需要显式调用,可以通过应用程序代码或SQL语句直接执行。
  2. 用途

    • 触发器:用于自动响应和处理数据库表上的数据变更事件,如自动更新数据、维护审计日志等。
    • 存储过程:用于封装复杂的业务逻辑,可以包含一系列的SQL语句和控制流语句,用于执行更复杂的任务。
  3. 执行上下文

    • 触发器:总是在数据库服务器上执行,并且通常与特定的表相关联。
    • 存储过程:可以在数据库服务器上执行,也可以在客户端应用程序中调用。
  4. 参数

    • 触发器:有预定义的参数,如NEW和OLD,分别代表触发操作的新旧行数据。
    • 存储过程:可以自定义参数,根据需要传递给存储过程。
  5. 返回值

    • 触发器:可以返回一个值(如NEW或OLD),这个值将被用作触发操作的结果。
    • 存储过程:可以返回一个结果集或单个值,也可以不返回任何内容。
  6. 事务管理

    • 触发器:通常在触发它们的操作的同一个事务中执行,这意味着如果触发器失败,整个事务将回滚。
    • 存储过程:可以控制自己的事务,可以决定在何处开始和结束事务。

联系:

  1. 代码封装:两者都是封装SQL代码和逻辑的方式,使得代码更加模块化和可重用。

  2. 数据库对象:触发器和存储过程都是数据库中的一等公民,可以被管理和维护。

  3. 执行SQL语句:两者都可以执行SQL语句,如SELECT、INSERT、UPDATE和DELETE。

  4. 控制流:存储过程和触发器(尤其是使用PL/pgSQL编写的触发器)都可以使用控制流语句,如IF条件语句、循环等。

  5. 性能优化:两者都可以用来优化数据库操作,通过减少网络往返和在数据库层面处理逻辑来提高性能。

  6. 安全性和权限:两者都可以设置权限,限制谁可以执行它们。

  7. 调试和维护:两者都需要适当的调试和维护,以确保它们按预期工作。

总的来说,触发器和存储过程在数据库设计和应用开发中扮演着不同的角色,它们可以相互补充,共同提高数据库操作的效率和安全性。

五、应用示例

当然,这里提供一个PostgreSQL中触发器的完整应用示例。假设我们有一个employees表,我们需要在每次有员工信息被更新时,自动将这次更新记录到employee_audit表中。

步骤 1: 创建员工表

首先,我们需要一个employees表来存储员工信息。

CREATE TABLE employees (id SERIAL PRIMARY KEY,name VARCHAR(100),department VARCHAR(100),salary NUMERIC
);

步骤 2: 创建审计日志表

接下来,创建一个employee_audit表来存储员工信息变更的审计日志。

CREATE TABLE employee_audit (id SERIAL PRIMARY KEY,employee_id INT,operation_type VARCHAR(10),operation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,changed_data JSONB
);

步骤 3: 创建触发器函数

创建一个触发器函数,用于在更新操作发生时,将变更信息插入到employee_audit表中。

CREATE OR REPLACE FUNCTION log_employee_update()
RETURNS TRIGGER AS $$
BEGIN-- 检查操作类型IF TG_OP = 'UPDATE' THEN-- 将变更信息插入到审计日志表中INSERT INTO employee_audit (employee_id, operation_type, changed_data)VALUES (NEW.id, TG_OP, jsonb_build_object('name', NEW.name,'department', NEW.department,'salary', NEW.salary));END IF;RETURN NEW;
END;
$$ LANGUAGE plpgsql;

步骤 4: 创建触发器

创建触发器,指定在employees表上执行更新操作时触发log_employee_update函数。

CREATE TRIGGER track_employee_update
AFTER UPDATE ON employees
FOR EACH ROW
EXECUTE FUNCTION log_employee_update();

完整示例说明

  1. employees表:存储员工基本信息。
  2. employee_audit表:存储员工信息变更的审计日志。
  3. log_employee_update函数:触发器函数,用于在更新操作发生时,将变更信息插入到employee_audit表中。
  4. track_employee_update触发器:在employees表上执行更新操作后触发log_employee_update函数。

测试触发器

现在,我们可以测试触发器是否按预期工作。

-- 插入一个员工记录
INSERT INTO employees (name, department, salary) VALUES ('John Doe', 'Finance', 50000);-- 更新员工记录
UPDATE employees SET salary = 55000 WHERE name = 'John Doe';-- 查询审计日志
SELECT * FROM employee_audit;

执行上述SQL语句后,你应该能在employee_audit表中看到一条记录,记录了John Doe的薪水从50000更新到55000的操作。

这个示例展示了如何使用触发器自动记录数据库表的变更信息,这对于维护数据完整性和审计跟踪非常有用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/6866.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言进阶——3字符函数和字符串函数(2)

8 strsrt char * strstr ( const char *str1, const char * str2);查找子字符串 返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回 null 指针。匹配过程不包括终止 null 字符,但会在此处停止。 8.1 库函数s…

python学opencv|读取图像(四十二)使用cv2.add()函数实现多图像叠加

【1】引言 前序学习过程中,掌握了灰度图像和彩色图像的掩模操作: python学opencv|读取图像(九)用numpy创建黑白相间灰度图_numpy生成全黑图片-CSDN博客 python学opencv|读取图像(四十)掩模:三…

基于C语言的数组从入门到精通

简介:本篇文章主要介绍了一维数组,二维数组,字符数组的定义,数组的应用,数组的核心代码解析,适用于0基础的初学者. C语言数组 1.一维数组 1.1定义 1.1.1声明 语法:数据类型 数组名[数组大小];示例:int arr[5]; 1.1.2初始化 a.静态初始化 完全初始化:int arr[5] {1…

【kong gateway】5分钟快速上手kong gateway

kong gateway的请求响应示意图 安装 下载对应的docker 镜像 可以直接使用docker pull命令拉取,也可以从以下地址下载:kong gateway 3.9.0.0 docker 镜像 https://download.csdn.net/download/zhangshenglu1/90307400, postgres-13.tar http…

python 安装插件 requests 下载免费简历(自学7)

安装 requests 库: 他们三个 按一个就行 pip install requests 或者 pip3 install requests 或者 conda install requests 代码 每次只可以下载一页的 简历模板 需要手动修改 id ### import requests from lxml import etree import osif __name__ "__…

西门子【Library of General Functions (LGF) for SIMATIC S7-1200 / S7-1500】

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 通用函数库 (LGF) 扩展了 TIA Portal 中用于 PLC 编程的 STEP 7 指令(数学函数、时间、计数器 等)。该库可以不受限制地使用,并包含 FIFO 、搜索功能、矩阵计算、 astro 计…

最新最详细的配置Node.js环境教程

配置Node.js环境 一、前言 (一)为什么要配置Node.js?(二)NPM生态是什么(三)Node和NPM的区别 二、如何配置Node.js环境 第一步、安装环境第二步、安装步骤第三步、验证安装第四步、修改全局模块…

黑龙江锅包肉:酸甜香酥的东北经典

黑龙江锅包肉:酸甜香酥的东北经典 黑龙江锅包肉,作为东北菜的代表之一,尤其在黑龙江省哈尔滨市享有极高的声誉。这道美食不仅承载着丰富的历史文化内涵,更以其鲜明的地域特色,成为了黑龙江省乃至整个东北地区的标志性菜肴。 历史渊源 锅包肉的历史可以追溯到清朝光绪年间,其…

linux——网络基础

文章目录 目录 文章目录 踏入网络世界:探索 Linux 网络的无垠天地 一、网络发展 早期单机处理模式 网络发展的需求催生 网络发展后的优势对比 二、局域网or广域网 典型局域网架构 广域网连接多个局域网 二者关系 三、协议 语言层与汉语协议 通信设备层与电话机协议 …

挖掘机的市场现状和发展前景:全球增长潜力,重塑基础设施建设新篇章

引言:工程机械的心脏,挖掘机的崛起之路 在现代化建设的浪潮中,挖掘机作为工程机械领域的核心设备,正以其强大的作业能力和广泛的应用场景,成为推动全球基础设施建设不可或缺的力量。从高速公路到大型矿场,…

tkinter绘制组件(44)——浮出ui控件

tkinter绘制组件(44)——浮出ui控件 引言布局函数结构ui框架对齐方向绑定已有控件出现和隐藏逻辑出现和隐藏动画完整代码函数 效果测试代码最终效果 github项目pip下载 引言 TinUI的浮出ui控件(flyout)其实是一个之间创建在UI框架…

【Unity3D】《跳舞的线》游戏的方块单方向拉伸实现案例

通过网盘分享的文件:CubeMoveMusic.unitypackage 链接: https://pan.baidu.com/s/1Rq-HH4H9qzVNtpQ84WXyUA?pwda7xn 提取码: a7xn 运行游戏点击空格动态创建拉伸的方块,由Speed控制速度,新方向是随机上下左右生成。 using System.Collect…

新版IDEA创建数据库表

这是老版本的IDEA创建数据库表,下面可以自己勾选Not null(非空),Auto inc(自增长),Unique(唯一标识)和Primary key(主键) 这是新版的IDEA创建数据库表,Not null和Auto inc可以看得到,但Unique和Primary key…

jmeter中对接口进行循环请求后获取相应数据

1、工作中遇到一个场景就是对某个单一接口进行循环请求,并需要获取每次请求后返回的相应数据; 2、首先就在jmeter对接口相关组件进行配置,需要组件有:循环控制器、CSV数据文件设置、计数器、访问接口、HTTP信息头管理器、正则表达…

【含代码】逆向获取 webpack chunk 下的__webpack_require__ 函数,获悉所有的模块以及模块下的函数

背景 Webpack 打包后的代码是不会直接暴露 __webpack_require__ 函数,目的是为了避免污染全局变量同时也为了保护 webpack 的打包后的模块都隐藏在闭包函数里,达到数据的安全性。 而有时我们为了测试某个函数,想直接获取这个内置函数&#…

最新常见的图数据库对比,选型,架构,性能对比

图数据库排名 地址:https://db-engines.com/en/ranking/graphdbms 知识图谱查询语言 SPARQL、Cypher、Gremlin、PGQL 和 G-CORE 语法 / 语义 / 特性 SPARQL Cypher Gremlin PGQL G-CORE 图模式匹配查询 语法 CGP CGP CGP(无可选)1 CGP CGP 语义 子…

CentOS7使用源码安装PHP8教程整理

CentOS7使用源码安装PHP8教程整理 下载安装包解压下载的php tar源码包安装所需的一些依赖扩展库安装前的配置修改配置文件1、进入php8的安装包 配置环境变量开机自启启动服务创建软连接常见问题1、checking for icu-uc > 50.1 icu-io icu-i18n... no2、configure: error: Pa…

php-phar打包避坑指南2025

有很多php脚本工具都是打包成phar形式,使用起来就很方便,那么如何自己做一个呢?也找了很多文档,也遇到很多坑,这里就来总结一下 phar安装 现在直接装yum php-cli包就有phar文件,很方便 可通过phar help查看…

博睿数据获中国信通院泰尔终端实验室致谢!

近日,博睿数据收到中国信息通信研究院(以下简称“中国信通院”)的感谢信,信中对博睿数据积极参与信通院牵头的“铸基计划——高质量数字化转型推进行动”,并在新技术研究、标准建设、课题共创、专家智库等多项工作中提…

分布式理解

分布式 如何理解分布式 狭义的分布是指,指多台PC在地理位置上分布在不同的地方。 分布式系统 分布式系**统:**多个能独立运行的计算机(称为结点)组成。各个结点利用计算机网络进行信息传递,从而实现共同的“目标或者任…