openGauss开源数据库实战十六

文章目录

  • 任务十六 openGauss逻辑结构:触发器管理
    • 任务目标
    • 实施步骤
      • 一、测试openGauss的触发器
        • 1.创建测试表
        • 2.创建触发器对应的函数
        • 3.创建触发器
        • 4.测试触发器
      • 二、触发器的类型
        • 1.行级触发器
        • 2.语句级触发器
        • 3.AFTER触发器和 BEFORE触发器

任务十六 openGauss逻辑结构:触发器管理

任务目标

通过本任务,初步掌握各种类型触发器的管理和应用。

实施步骤

触发器是一个特殊的存储过程,与某个特定的表相关联,在对该表执行INSERT、DELETE或UPDATE语句之前或者之后,自动激活执行。
使用触发器具有以下几个好处:
1)触发器可用来实现数据完整性约束(检查列值是否在某个范围内),也可以用来实现表间的数据完整性约束(补偿不保持依赖的表分解)。
2)触发器可以基于某个表达式为列提供默认值,甚至可以为那些只能使用常量默认值进行定义的列类型提供值。
3)触发器可以在行删除或更新之前先检查行的当前内容。这种能力能完成许多任务,如记录已有行的更改情况。
要创建触发器,可以使用CREATE TRIGGER语句,其语法格式如下:

CREATE [CONSTRAINT] TRIGGER trigger_name {BEFORE | AFTER | INSTEAD OF} {event [OR…]}ON table_name[FROM referenced_table_name]{NOT DEFERRABLE | [DEFERRABLE] {INITIALLY IMMEDIATE | INITIALLY DEFERRED}}[FOR [EACH] {ROW | STATEMENT}][WHEN(condition)]EXECUTE PROCEDURE function_name(arguments);

其中event包含以下几种:

INSERT
UPDATE [OF column_name[, …]]
DELETE
RUNCATE

在创建触发器的定义里,需要指明触发它的语句类型(INSERT、UPDATE或DELETE),以及是在行被修改之前触发,还是在之后触发。

一、测试openGauss的触发器

本实验测试openGauss的触发器功能:每当往测试表test1中插入一条记录时,会在测试表test2中插入一条日志记录。

1.创建测试表

执行下面的命令和SQL语句,创建测试表test1和test2:

gsql -d studentdb -h 192.168.100.91 -U student -p 26000 -W student@ustb2020 -r
--  第一步,创建测试表,用于测试触发器
DROP TABLE IF EXISTS test1;
CREATE TABLE test1( col11  int  PRIMARY KEY,col12  char(10));
DROP TABLE IF EXISTS test2;
CREATE TABLE test2( col21  timestamp,col22  varchar(200));
2.创建触发器对应的函数

执行下面的SQL语句,创建触发器对应的函数:

--  第二步,创建触发器对应的存储函数
CREATE OR REPLACE FUNCTION testtrigger()
RETURNS TRIGGER
AS $$
BEGININSERT INTO test2 values(NOW(),'record inserted!') ;RETURN OLD;
END;
$$
LANGUAGE plpgsql;
3.创建触发器

执行下面的命令,创建触发器:

--  第三步,创建触发器
--  该触发器在往表test1每插入1条新数据时,会往表test2插入1条日志记录
CREATE TRIGGER mytrigger AFTER INSERT ON test1 
FOR EACH ROW EXECUTE PROCEDURE testtrigger();
4.测试触发器

执行下面的命令,测试刚刚创建的触发器:

--  第四步,测试触发器
select * from test1;
select * from test2;
INSERT INTO test1 values(1,'test');
select * from test1;
select * from test2;

在这里插入图片描述

二、触发器的类型

1.行级触发器

前面刚刚创建的触发器就是一个行级触发器。执行下面的语句,再次测试行级触发器:

--  再次执行下面的语句,一次插入2条记录到测试表
select * from test1;
select * from test2;
INSERT INTO test1 values(2,'test'),(3,'test');
select * from test1;
select * from test2;

从输出可以看出,在表test1中每插入一行,就会在表test2中增加一条记录。这就是行级触发器。
如果插入语句执行失败,行级触发器会怎么样呢?

--  继续执行下面的语句,该语句会违法主键约束因此会失败!
select * from test1;
select * from test2;
INSERT INTO test1 values(1,'test');
select * from test1;
select * from test2;

由于该触发器是AFTER触发器(往表成功插人行后才会执行该触发器对应的函数),因此INSERT语句执行失败(因为违反了主键约束),触发器不会被执行。
执行下面的命令,清除刚才创建的行级触发器的相关对象:

drop trigger mytrigger on test1;
drop function testtrigger;
drop table test1;
drop table test2;
\q

在这里插入图片描述

2.语句级触发器

执行下面的命令系列,创建一个语句级触发器:

gsql -d studentdb -h 192.168.100.91 -U student -p 26000 -W student@ustb2020 -r
--  第一步,创建测试表,用于测试触发器
DROP TABLE IF EXISTS test1;
CREATE TABLE test1( col11  int  PRIMARY KEY,col12  char(10));
DROP TABLE IF EXISTS test2;
CREATE TABLE test2( col21  timestamp,col22  varchar(200));

接下来,执行下面的命令,创建触发器对应的函数:

--  第二步,创建触发器对应的存储函数
CREATE OR REPLACE FUNCTION testtrigger()
RETURNS TRIGGER
AS $$
BEGININSERT INTO test2 values(NOW(),'record inserted!') ;RETURN OLD;
END;
$$
LANGUAGE plpgsql;

再接下来,执行下面的命令,创建语句级触发器:

--  第三步,创建语句级触发器
--  该触发器在往表test1插入新数据时,会记录日志到表test2中
CREATE TRIGGER mytrigger AFTER INSERT ON test1 
FOR EACH STATEMENT EXECUTE PROCEDURE testtrigger();

最后,执行下面的命令,测试语句级触发器:

--  第四步,测试语句级触发器
select * from test1;
select * from test2;
INSERT INTO test1 values(2,'test'),(3,'test');
select * from test1;
select * from test2;

在这里插入图片描述
从输出可以看到,尽管在一条INSERT语句插入了两行数据,但是语句级触发器只执行一次。
执行下面的命令,清除刚才创建的语句级AFTER触发器的相关对象:

drop trigger mytrigger on test1;
drop function testtrigger;
drop table test1;
drop table test2;
\q
3.AFTER触发器和 BEFORE触发器

前面语句测试了AFTER触发器:AFTER触发器在完成插入操作后再执行触发器动作。当语句执行失败时,AFTER触发器不会被执行。
下面是测试BEFORE触发器的步骤。
1)首先执行下面的命令创建一个BEFORE触发器:

gsql -d studentdb -h 192.168.100.91 -U student -p 26000 -W student@ustb2020 -r
--  第一步,创建测试表,用于测试触发器
DROP TABLE IF EXISTS test;
CREATE TABLE test AS
SELECT * FROM INSTRUCTOR;

2)然后执行下面的命令创建触发器对应的函数:

--  第二步,创建触发器对应的存储函数
CREATE OR REPLACE FUNCTION testtrigger()
RETURNS TRIGGER
AS $$
BEGINNEW.NAME=NEW.NAME||NEW.ID;RETURN NEW;
END;
$$
LANGUAGE plpgsql;

3)接下来执行下面的命令创建行级BEFORE触发器:

--  第三步,创建行级BEFORE触发器
--  该触发器在往表test插入新数据时,会记录日志到表test2中
CREATE TRIGGER mytrigger BEFORE INSERT ON test 
FOR EACH ROW EXECUTE PROCEDURE testtrigger();

4)最后执行下面的命令,测试建行级BEFORE触发器:

--  第四步,测试语句级BEFORE触发器
INSERT INTO test(ID,NAME,DEPT_NAME,SALARY)VALUES('88888','test','Comp. Sci.',85000);
select * from test;

在这里插入图片描述

我们发现,INSERT语句中要插人的值是“88888,test,Comp.Sci.,85000”,但实际插入到表中的值经过BEFORE触发器提前被更改为namelid。在将行插入表test之前执行触发器的动作,修改要插入的值,然后再将修改后的值插入到表test中:这只能通过 BEFORE触发器来完成。

执行下面的命令,清理数据:

delete from test where id='88888';
\q

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

键值对形式读取值

效果 学习啦&#xff01; 异步请求数据方法&#xff1a; ①async/await <script setup> import { nextTick, onMounted } from vuelet Info {}const loadData async () > {try {const response await fetch(/json/info.json)const data await response.json()data…

Java面向对像编程OOP

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 OOP总结&#xff1a; 类和对象的说明Java中有无static修饰的方法的使用区别&#xff1a;✅️有stat…

【MARL】MAT论文阅读笔记

文章目录 前言一、如何产生这个想法(TRPO -> ) PPO -> MAPPO -> HAPPO -> MAT 二、多智能体优势值分解定理三、transformer 在MAT的应用四、伪代码简述五、实验效果 前言 正好有节课让我们调研最新的自己的方向的新论文&#xff0c;找到一篇自己觉得比较可行&…

深度学习模型——双塔模型(Two-Tower Model)详解

双塔模型是一种高效、灵活的深度学习模型结构&#xff0c;广泛用于推荐系统和信息检索等场景中。其核心思想是分别为两个实体&#xff08;如用户和物品、查询和文档&#xff09;构建独立的特征表示网络&#xff08;两座塔&#xff09;&#xff0c;并在共享语义空间中通过相似性…

回溯里面的基本概念

1.深度优先遍历和深度优先搜索&#xff08;DFS) 深度优先遍历 主要思路是从图中一个未访问的顶点 V 开始&#xff0c;沿着一条路一直走到底&#xff0c;然后从这条路尽头的节点回退到上一个节点&#xff0c;再从另一条路开始走到底...&#xff0c;不断递归重复此过程&#xff…

LeetCode 热题100(十五)【动态规划】(3)

15.7最长递增子序列&#xff08;中等&#xff09; 题目描述&#xff1a;leetcode链接 300. 最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元…

springboot如何集成工作流审批流,流程设计器集成,业务表单和工作流绑定,详细步骤和实际案例参考(源码)

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;一套完整并且实际运用在多套项目中的案例&#xff0c;满足日常业务流程审批需求。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端…

02_Node.js模块化

02_Node.js模块化 知识点自测 以下代码运行的结果是多少&#xff1f; const arr [10, 20, 30] const result arr.map(val > val 1).reduce((sum, val) > sum val, 0) console.log(result) A&#xff1a;60 B&#xff1a;63 <details><summary>答案</…

vulnhub kioptirx1.2 超详细wp

探测 nmap --min-rate 10000 -p- 192.168.128.134 最小速率10000 nmap -sT -sV -sC -O 192.168.128.134 web打点 无弱口令 暴露cms寻找exp searchsploit LotusCMS -m 16982 [输入id号和参数m可以直接把东西复制到当前目录] 查看txt里面发现 都是xss没有rce github搜索到一个…

vulnhub靶场之【grotesque】三

前言 靶机&#xff1a;grotesque-3 192.168.1.44 攻击 &#xff1a;kali 192.168.1.16 都是虚拟机环境&#xff0c;桥接模式 主机发现 使用arp-scan -l或者netdiscover -r 192.168.1.1/24搜索 信息收集 使用nmap扫描 防止有遗漏&#xff0c;再扫描全端口 网站信息收集 …

大规模模型部署、推理的工具:Xinference

有没有 Xinference之前&#xff0c;如果想要部署应用一个开源模型&#xff0c;可能会面临以下一些情况和挑战&#xff1a; 自行开发推理框架&#xff1a; 需要投入大量的时间和精力来构建一个可靠且高效的推理框架&#xff0c;包括处理模型加载、资源管理、请求调度等复杂的任务…

C语言选择法排序

C语言编程&#xff0c;用选择法对数组中4个整数按由大到小排序 1、代码如下&#xff1a; #include<stdio.h> #include<math.h> #include<string.h>int main() {void sort(int array[],int n);printf("测试开始\n");int nums[] {2,3,4,1};sort(n…

SpringBoot的validation参数校验

文章目录 前言一、引入validation 依赖二、validation中的注解说明 &#xff08;1&#xff09;Validated&#xff08;2&#xff09;Valid&#xff08;3&#xff09;NotNull&#xff08;4&#xff09;NotBlank&#xff08;5&#xff09;NotEmpty&#xff08;6&#xff09;Patte…

Go的Gin比java的Springboot更加的开箱即用?

前言 隔壁组的云计算零零后女同事&#xff0c;后文简称 云女士 &#xff0c;非说 Go 的 Gin 框架比 Springboot 更加的开箱即用&#xff0c;我心想在 Java 里面 Springboot 已经打遍天下无敌手&#xff0c;这份底蕴岂是 Gin 能比。 但是云女士突出一个执拗&#xff0c;非我要…

docker学习笔记(四)--DockerFile

文章目录 一、什么是Dockerfile二、docker build命令三、dockerfile指令3.1 FROM3.2 ENV3.3 WORKDIR3.4 RUN3.5 CMD3.6 ENTRYPOINT3.7 EXPOSE3.8 ARG3.9 ADD3.10 COPY3.11 VOLUME 四、dockerfile示例 一、什么是Dockerfile Dockerfile 是用于构建 Docker 镜像的脚本文件&#…

撰写技术文档的关键步骤和核心要点

编写项目的技术文档是一个重要且细致的任务&#xff0c;它不仅有助于项目的当前开发团队理解系统的结构和工作原理&#xff0c;还为未来的维护和扩展提供了宝贵的参考资料。以下是撰写技术文档时应遵循的几个关键步骤和组成部分&#xff1a; 1. 概述 项目简介&#xff1a;简要…

Ant-Design-Vue 全屏下拉日期框无法显示,能显示后小屏又位置错乱

问题1&#xff1a;在全屏后 日期选择器的下拉框无法显示。 解决&#xff1a;在Ant-Design-Vue的文档中&#xff0c;很多含下拉框的组件都有一个属性 getPopupContainer可以用来指定弹出层的挂载节点。 在该组件上加上 getPopupContainer 属性,给挂载到最外层盒子上。 <temp…

【前端学习路线】(超详细版本)

先附上学习路线图&#xff1a;前端学习路线 第一阶段&#xff1a;前端入门&#xff08;htmlcss&#xff09; 前端最基本的知识&#xff0c;需要先将这些内容融汇贯通&#xff0c;学习后面内容才会不吃力。学习完可以做几个静态页练习一下。 推荐视频学习链接&#xff1a; 黑马程…

Vue生成类似于打卡页面

数据表格 <el-table :data"tableData" border height"calc(100vh - 240px)" :cell-style"cellFun"><el-table-column label"姓名" show-overflow-tooltip prop"name" align"center"/><el-table-co…

JVM学习《垃圾回收算法和垃圾回收器》

目录 1.垃圾回收算法 1.1 标记-清除算法 1.2 复制算法 1.3 标记-整理算法 1.4 分代收集算法 2.垃圾回收器 2.1 熟悉一下垃圾回收的一些名词 2.2 垃圾回收器有哪些&#xff1f; 2.3 Serial收集器 2.4 Parallel Scavenge收集器 2.5 ParNew收集器 2.6 CMS收集器 1.垃圾…