【MySQL】游标和触发器

news2024/11/16 10:27:43

一、游标

1.1 什么是游标

1、使用背景
在我们使用update或者delete操作数据时,一般都会根据条件语句查询出很多条记录组成的数据集,然后一次性批量操作

假设我们想要对这个结果集中的数据 一行一行的进行操作,比如某个条件满足后,就不继续往下操作了,这个时候就要用到游标了

游标可以在存储过程和函数中使用

2、使用步骤

  • 声明游标(位置放在变量声明语句的后面,因为变量声明必须紧跟begin)
    MySQL、DB2、SQL server和Maria DB中的声明语法为
    DECLARE cursor_name CURSOR FOR 查询语句;
    Oracle、Postgresql中的声明语法为
    DECLARE cursor_name CURSOR IS 查询语句;
  • 打开游标
    OPEN cursor_name;
  • 使用游标:从游标中获取数据(注意:var_name必须在声明游标之前就定义好)
    FETCH cursor_name INTO var_name,var_name2...;
    这句话的作用是使用cursor_name来读取当前行,并将数据保存到变量var_name中,游标指针指向下一行,如果读取的数据行有多个字段,那就在INTO关键字后赋值给多个变量
  • 关闭游标
    CLOSE cursor_name;

3、使用案例
新建一个博客表t_blog_view,设定一个值num
看看最少需要累加多少篇博客的浏览量才能达到这个值(根据浏览量做一个降序排列)

CREATE TABLE `t_blog_view`  (
  `blog_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客名称',
  `blog_author` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客作者',
  `blog_views` int(20) NOT NULL COMMENT '博客浏览量'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;


INSERT INTO `t_blog_view` VALUES ( 'Mybatis系列', 'Decade0712', 2000);
INSERT INTO `t_blog_view` VALUES ( 'Spring系列', 'Decade0712', 4000);
INSERT INTO `t_blog_view` VALUES ( '设计模式系列', 'Decade0712', 6000);
INSERT INTO `t_blog_view` VALUES ( 'JVM系列', '十年', 8000);
INSERT INTO `t_blog_view` VALUES ( 'MySQL基础', 'Decade0712', 4000);
INSERT INTO `t_blog_view` VALUES ( 'Java8新特性', '十年', 5500);

我们定义一个存储过程进行测试

DELIMITER //

CREATE PROCEDURE test_cursor(IN num DOUBLE,OUT res_count INT)
BEGIN
	# 声明局部变量
	DECLARE sum_views DOUBLE DEFAULT 0.0; # 记录累加浏览量
	DECLARE current_views DOUBLE;  # 记录当前博客浏览量
	DECLARE blog_count INT DEFAULT 0; # 记录累加博客数
	
	# 1、声明游标
	DECLARE blog_cursor CURSOR FOR SELECT blog_views from t_blog_view ORDER BY blog_views DESC;
	
	# 2、打开游标
	OPEN blog_cursor;
	
	# 3、使用游标,因为要累加所以使用循环语句
	REPEAT
		FETCH blog_cursor INTO current_views;
		
		SET sum_views = sum_views + current_views;
		SET blog_count = blog_count + 1;
		UNTIL sum_views >=  num
	END REPEAT;
	
	# 把累加的博客数赋值给输出变量
	SET res_count = blog_count;

	# 4、关闭游标
	CLOSE blog_cursor;
END //

DELIMITER ;

# 进行调用
CALL test_cursor(10086,@res_count);
SELECT  @res_count;

# 删除存储过程
DROP PROCEDURE test_cursor;

结果如下
在这里插入图片描述
4、优缺点

  • 优点:使用游标,能够逐条读取结果集中的数据
  • 缺点:使用游标,会对数据进行加锁,在业务并发量大时,会影响业务的效率,并且会消耗系统内存资源

二、触发器

1、使用场景
假设我们现在有2张表商品表和库存表,我们新引入一种商品时,除了要修改商品表的数据,还要修改库存表的数据

为了保证不遗漏任何一个动作,我们一般使用事务将其包裹起来,使这两个动作成为一个原子操作

或者使用触发器,让商品表数据插入的动作自动触发库存表数据插入的动作

2、概述
触发器是由事件来触发某个操作,包括INSERT、UPDATE、DELETE事件。事件就是指用户的动作或者触发某项行为。如果定义了触发程序,当数据库执行这些语句的时候就相当于事件发生了,就会自动激发触发器去执行相应的操作

3、触发器的创建

CREATE TRIGGER 触发器名
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名
FOR EACH ROW
触发器执行的语句块;
  • 表名:触发器监控的对象
  • BEFORE|AFTER:表示触发的时间,是在事件发生之前还是发生之后
  • INSERT|UPDATE|DELETE:表示触发的事件,是插入数据事件、更新数据事件还是删除数据事件
  • FOR EACH ROW:每操作一条表中的数据,就激发一次触发器
  • 触发器执行的语句块:可以是单条语句块,也可以是BEGIN...END包裹的复杂语句块

4、举例
我们新建2张表,test_triggle和test_triggle_log,每当我们要向test_triggle中插入数据时,先在test_triggle_log中记录日志

CREATE TABLE test_triggle(
id INT PRIMARY KEY AUTO_INCREMENT,
t_note VARCHAR(30)
);

CREATE TABLE test_triggle_log(
id INT PRIMARY KEY AUTO_INCREMENT,
t_log VARCHAR(30)
);

创建触发器

DELIMITER //
CREATE TRIGGER test_trigger_tir
BEFORE INSERT ON test_triggle
FOR EACH ROW
BEGIN
	INSERT INTO test_triggle_log(t_log)
	VALUES('before insert to...');
END //
DELIMITER ;

INSERT INTO test_triggle(t_note)
VALUES('test insert DEMO1...');

SELECT * FROM test_triggle;
SELECT * FROM test_triggle_log;

结果如下,test_triggle_log表中自动增加了一条记录
在这里插入图片描述
案例二:我们向表test_triggle中插入数据前,需要先对这条记录的id做一个判断,如果是双数,就报错,否则就正常插入

注意:我们使用NEW表示INSERT要插入的那条数据,要获取某个字段,使用NEW.column即可
使用OLD表示DELETE要删除的那条数据

DELIMITER //
CREATE TRIGGER test_trigger_tir_single_num
BEFORE INSERT ON test_triggle
FOR EACH ROW
BEGIN
	# 创建一个变量,将当前记录的id对2取余的结果赋值给它,以便于后续做单双数的判断
	DECLARE is_single INT;
	SELECT NEW.id % 2 INTO is_single;
	
	IF is_single = 0 THEN
		SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = 'id为双数无法插入';
	END IF;
END //
DELIMITER ;

# 测试
INSERT INTO test_triggle(id,t_note) VALUES(1,'test insert DEMO1...');
INSERT INTO test_triggle(id,t_note) VALUES(2,'test insert DEMO2...');

# 查看test_triggle表是否正常插入数据
SELECT * from test_triggle;

结果如下,id为双数时,无法插入数据
在这里插入图片描述
在这里插入图片描述

5、查看触发器

# 查看所有触发器的定义
SHOW TRIGGERS;

# 查看指定触发器的定义
SHOW CREATE TRIGGER 触发器名称;

# 从系统库information_schema中查看触发器的定义
SELECT * FROM information_schema.TRIGGERS;

6、删除触发器

DROP TRIGGER IF EXISTS 触发器名称;

7、触发器的优缺点

  • 优点:
    • 可以保证数据的完整性
    • 可以通过触发器帮助我们记录数据的操作日志
    • 可以在操作数据前,对数据的合法性做一个检验
  • 缺点:
    • 可读性差
    • 相关数据的变更,可能会导致触发器报错

8、注意点
如果在子表中定义了外键约束,且子表的中又定义了基于此表UPDATE或者DELETE操作的触发器
如果父表数据修改引发了子表的数据变化,在这种情况下并不会激发触发器

如有错误,欢迎指正!!!

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

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

相关文章

Redis安装及基本类型详解

目录 一、Redis概念 二、Redis的应用场景 三、Redis的特点 四、redis访问数据为什么快? 五、Ubuntu下安装redis 五、全局命令(针对任意类型value都可使用) 1、keys (1)keys * (2)keys pattern 2、exists 3、…

从0到1搭建文档库——sphinx + git + read the docs

sphinx git read the docs 目录 一、sphinx 1 sphinx的安装 2 本地构建文件框架 1)创建基本框架(生成index.rst ;conf.py) conf.py默认内容 index.rst默认内容 2)生成页面(Windows系统下&#xf…

uniapp vue2 时钟 循环定时器

效果展示: 时钟 写在前面:vue2有this指向,没有箭头函数 实验操作:封装一个时钟组件 uniapp vue2 封装一个时钟组件 核心代码: this指向的错误代码,在下: start() { this.myTimer setInterval(…

11.内建函数对象_算数、关系、逻辑仿函数

文章目录 算数仿函数代码工程运行结果 关系仿函数代码工程运行结果 逻辑仿函数代码工程运行结果 算数仿函数 需要添加#include<functional>头文件使用 代码工程 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<functional>using namespace…

顶象全系列产品升级,对抗AI带来的新威胁

4月2日&#xff0c;在顶象CSDN直播间&#xff0c;最新一期“业务安全大讲堂”上&#xff0c;顶象数据科学家翼龙与资深解决方案专家鳯羽&#xff0c;围绕当前备受关注的AI威胁、人脸风险进行深入分享&#xff0c;并详细介绍针对AI威胁的最新反欺诈技术与安全产品。 AI威胁带来的…

开发项目接单报价快速计算,报价量化程序

定制化开发&#xff0c;如何计算项目预算&#xff0c;是程序开发者头疼的一个问题。 项目费用谈得过低&#xff0c;就天天加班累死赚不到钱&#xff1b;谈得过高&#xff0c;会导致顾客流失&#xff0c;信誉受损。 项目费用量化可见是多么重要。 下面是一段量化的程序&#…

【教程】VOC数据集制作

语义分割任务中VOC数据集的制作&#xff0c;任务中只有一种标签&#xff1a;gas 文章目录 1、由黑白图像识别为txt标签2、txt转json3、数据集转VOC格式 1、由黑白图像识别为txt标签 由于使用CycleGAN网络进行风格迁移学习&#xff0c;生成了大量伪标签图像&#xff0c;因此需…

阿里云ICP备案工信部短信核验详细流程,1分钟搞定教程!

网站ICP备案或APP备案通过云厂商的备案初审后&#xff0c;需要在工信部完成短信核验操作&#xff0c;本文云服务器吧yunfuwuqiba.com以阿里云备案为例&#xff0c;来详细说明工信部短信核验详细流程&#xff0c;非常简单&#xff1a; 阿里云备案提交到阿里云初审&#xff0c;初…

学习操作系统之OS的作用

OS是用户与计算机硬件之间的接口 OS处于用户和硬件系统之间,用户通过OS来使用计算机硬件系统.即用户可以在OS的帮助下方便、快捷、可靠的操作计算机硬件和运行自己的程序。 下图是我对于操作系统的简单理解 OS是计算机系统资源的管理者 一个计算机系统包含四类硬件资源&…

angular—mooc课学习笔记

1.angular工程目录 2.设置标签元素样式 3.fex布局 4.事件绑定 5. 双向数据传输 6. 键盘实现方法 7.内置指令拉选框 8. ngFor指令

RocketMQ建Topic

# 查看集群状况 ./mqadmin clusterList -n localhost:9876 # 创建topic ./mqadmin updateTopic -b localhost:10911 -t my_topic -n localhost:9876 # 查看所有topic ./mqadmin topicList -n localhost:9876参考 Admin Tool

ESP32S3网络编程学习笔记(1)—— Wi-Fi扫描实验

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘湖南区域日常实习生&#xff0c;任何区域的暑假Linux驱动/单片机/RTOS的实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &#xff…

计算机服务器中了helper勒索病毒怎么办,helper勒索病毒解密流程步骤

随着网络技术在企业中的不断应用&#xff0c;越来越多的企业离不开网络&#xff0c;网络为企业提供了极大便利&#xff0c;大大提升了生产运营效率&#xff0c;由此而产生的网络数据安全问题也成为了企业关心的主要话题。近期&#xff0c;云天数据恢复中心接到多家企业的求助&a…

在虚拟机尝试一次用启动盘重装系统

在虚拟机尝试一次用启动盘重装系统 没有自己重装过系统&#xff0c;也不敢对自己的笔记本下手&#xff0c;用虚拟机重装玩玩试试。 先设置成u盘启动 从boot中选择相应的创建的硬盘即可&#xff08;刚刚突然发现图片不能上传了&#xff0c;经过乱七八糟的尝试后&#xff0c;开一…

90天玩转Python—06—基础知识篇:Python中的七大基础数据类

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…

js的qq换肤效果

文章目录 1. 演示效果2. 分析思路3. 代码实现3.1. 方式一3.2. 方式二3.3. 整体代码 1. 演示效果 2. 分析思路 先编写样式&#xff0c;弄好布局和排版。遍历这个集合&#xff0c;对每个图片元素&#xff08;img&#xff09;添加一个点击事件监听器。可以使用 for 或者 forEach …

计算机毕业设计java 基于Android的拼图游戏app

当今社会&#xff0c;随着电子信息技术的发展&#xff0c;电子游戏也成为人们日常生活的一部分。这种娱乐方式结合了日新月异的技术&#xff0c;在游戏软件中结合了多种复杂技术。拼图游戏流行在各种电子产品上&#xff0c;从计算机&#xff0c;掌上游戏机到如今的手机&#xf…

番茄 短abogus补环境

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章…

849. Dijkstra求最短路 I

tips&#xff1a; 采用0x3f3f3f3f作为一个极大值&#xff1a; 1061109567 //是一个很大的数&#xff0c;可以用来代表∞&#xff1b; 在memset里0x3f表示为0x3f3f3f3f memset(a, 0x3f, sizeof a); //0x是十六进制的意思&#xff1b; memset()是对char操作&#xff0c;即一个…

Vue3组件基础示例

组件是vue中最推崇的&#xff0c;也是最强大的功能之一&#xff0c;就是为了提高重用性&#xff0c;减少重复性的开发。 如何使用原生HTML方法实现组件化 在使用原生HTML开发时&#xff0c;我们也会遇到一些常见的功能、模块&#xff0c;那么如何在原生HTML中使用组件化呢&am…