【数据库——MySQL】(14)过程式对象程序设计——游标、触发器

目录

  • 1. 游标
    • 1.1 声明游标
    • 1.2 打开游标
    • 1.3 读取游标
    • 1.4 关闭游标
    • 1.5 游标示例
  • 2. 触发器
    • 2.1 创建触发器
    • 2.2 修改触发器
    • 2.3 删除触发器
    • 2.4 触发器类型
    • 2.5 触发器示例
  • 参考书籍

1. 游标

游标一般和存储过程一起配合使用。

1.1 声明游标

要使用游标,需要用到 DECLARE CURSOR 语句:

DECLARE 游标名 CURSOR FOR SELECT语句

:一个存储过程可以声明多个游标,但是一个块中的每一个游标必须具有唯一的名字。

1.2 打开游标

要使用游标,需要用到 OPEN 语句:

OPEN 游标名;

1.3 读取游标

要使用游标,需要用到 FETCH...INTO 语句:

FETCH 游标名 INTO 变量名, ...

1.4 关闭游标

要使用游标,需要用到 CLOSE 语句:

CLOSE 游标名;

:游标使用完以后要 及时关闭

1.5 游标示例

【例】在数据库 score 中查询某个学院某门课程的成绩(方法一)

drop PROCEDURE if EXISTS p1;
delimiter $
create PROCEDURE p1(in did char(10), in lid char(10))
begindeclare stu_id char(15);declare lname char(20);declare stu_score int;declare score_count int;		# 统计记录数declare i int default 1;# 设置游标declare c_score CURSOR forselect stu.id, lesson.lessonName, score.scorefrom stu join score on stu.id = score.stuIdjoin lesson on score.LessonId = lesson.lessonidjoin department on stu.departmentId = department.idwhere stu.departmentId = did and score.LessonId = lid;select count(*) into score_countfrom (select stu.id, lesson.lessonName, score.scorefrom stu join score on stu.id = score.stuIdjoin lesson on score.LessonId = lesson.lessonidjoin department on stu.departmentId = department.idwhere stu.departmentId = did and score.LessonId = lid)a;open c_score;    # 打开游标while i <= score_count doFETCH c_score into stu_id, lname, stu_score;		# 读取游标select stu_id, lname, stu_score;		# 使用游标set i = i + 1;end while;close c_score;		# 关闭游标end $
delimiter ;# 一般在命令列界面运行可以明显看出所要查看的数据
call p1('101', '101');

如果是在可视化界面运行 call p1('101', '101');,效果如下(不方便查看,数据是一条条输出的):

在这里插入图片描述

在命令列界面运行 call p1('101', '101');,方便查看:

在这里插入图片描述

我们也尝试不用存储过程直接输出结果,发现结果是一样的(除了输出顺序不同):

select stu.id, lesson.lessonName, score.scorefrom stu join score on stu.id = score.stuIdjoin lesson on score.LessonId = lesson.lessonidjoin department on stu.departmentId = department.idwhere stu.departmentId = '101' and score.LessonId = '101';

在这里插入图片描述

2. 触发器

2.1 创建触发器

用代码创建:

CREATE TRIGGER 触发器名 触发时刻 触发事件ON 表名 FOR EACH ROW 触发器动作

不过为了方便,我们可以直接使用可视化界面创建触发器。

2.2 修改触发器

建议直接在 Navicat 上进行创建、修改、删除触发器,在设计表中点击触发器即可。

在这里插入图片描述

2.3 删除触发器

前面说了可以直接使用 Navicat 删除触发器。

下面也给出相关代码:

DROP TRIGGER [数据库名.]触发器名

2.4 触发器类型

触发器只有 3 种类型:插入更新删除。每种类型又有 2 种情况:BEFOREAFTER

每个类型每种情况的触发器在一张表只能设置 1,即一张表最多只有 6 个触发器。

对于 事件、全局锁、表锁、行锁和死锁 的内容在此不过多赘述,大家要是感兴趣可以自行了解~

2.5 触发器示例

使用 bank 数据库,创建表 info,利用触发器完成以下内容。下面会给出如何用 SQL 语句创建触发器并完成相应功能。

info 的内容如下:

在这里插入图片描述

  1. 插入存取款记录(触发器 tri_insertinfo)——需要判断用户账号是否存在。

    drop trigger if EXISTS tri_insertinfo;
    delimiter $
    create TRIGGER tri_insertinfo before insert on info for each row
    begindeclare a int;select count(*) into afrom accountwhere account.id = new.accountid;if a = 0 then SIGNAL SQLSTATE '12345' set message_text = '账号不存在';end if;if new.type = 'save' thenupdate accountset ck = ck + new.balancewhere account.id = new.accountid;elseupdate accountset ck = ck - new.balancewhere account.id = new.accountid;end if;end$
    delimiter ;
    

    查看当前所有用户存款:

    select * from account;
    

    在这里插入图片描述

    张三存入 500 元,并查看当前全部用户存款:

    insert into info values(null, '001', 'save', 500);
    select * from account;
    

    在这里插入图片描述

    李四取出 500 元:

    insert into info values(null, '002', 'load', 500);
    select * from account;
    

    在这里插入图片描述

    给用户编号为 005 (不存在用户)存入 500 元:

    insert into info values(null, '005', 'save', 500);		# 会显示账号不存在
    

    在这里插入图片描述

  2. 创建触发器 tri_deleteinfo 撤销存取款记录(info 中的记录)。

    drop trigger if EXISTS tri_deleteinfo;
    delimiter $
    create TRIGGER tri_deleteinfo after delete on info for each row
    beginif old.type = 'save' thenupdate accountset ck = ck - old.balancewhere account.id = old.accountid;elseupdate accountset ck = ck + old.balancewhere account.id = old.accountid;end if;end$
    delimiter ;
    

    撤销编号为 16 的取款操作:

    delete from info where id = 16;		# 撤销id为16的操作
    select * from account;
    

    在这里插入图片描述
    可见李四的账户从 5550 恢复到上次的 6050

    清除所有的存取款操作:

    delete from info;		# 撤销所有存取款操作,金额恢复
    select * from account;
    

    在这里插入图片描述
    可见张三的账户金额出现了负数,这其实是异常结果,所以大家可以自行在源代码里面新增报告异常的语句。

    按照道理来说不会出现这种情况,可能是我之前操作数据时改变了记录~

  3. 创建触发器 tri_updateinfo,用于修改用户存取款金额数。

    drop trigger if EXISTS tri_updateinfo;
    delimiter $
    create TRIGGER tri_updateinfo after update on info for each row
    beginif old.type = 'save' thenupdate accountset ck = ck - old.balance + new.balancewhere account.id = old.accountid;elseupdate accountset ck = ck + old.balance - new.balancewhere account.id = old.accountid;end if;end$
    delimiter ;
    

    其实这个操作基本上用不上,毕竟用户存、取多少就是多少,而且这个操作可以用前面两个触发器实现,因此这里不展示修改操作了~

参考书籍

《MySQL实用教程(第4版)》

上一篇文章:【数据库——MySQL】(13)过程式对象程序设计——存储函数、错误处理以及事务管理

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

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

相关文章

Docker基本管理

虚拟化产品&#xff1a; 1.寄居架构 2.原生架构 Docker 基本管理 docker 发展历史 https://www.cnblogs.com/rongba/articles/14782624.html -----------------Docker 概述--------------------------- Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了a…

英伟达NVIDIA驱动安装

一般&#xff0c;我们新的显卡上机或者新系统可能就需要重新安装显卡驱动。或者是我们在配置深度学习环境时候&#xff0c;需要手动安装驱动。 官网地址&#xff1a;官方高级驱动搜索 | NVIDIA 我们选择好自己需要的驱动后直接安装即可 下载的时候&#xff0c;选择自己需要的驱…

SSRF+redis未授权漏洞复现

1.SSRF漏洞简介 SSRF&#xff08;Server-Side Request Forgery&#xff09;即服务器端请求伪造&#xff0c;是一种由攻击者构造攻击链传给服务器&#xff0c;服务器执行并发起请求造成安全问题的漏洞&#xff0c;一般用来在外网探测或攻击内网服务。当网站需要调用指定URL地址…

Linux基本指令介绍系列第四篇

文章目录 前言一、Linux基本指令介绍1、more指令2、less指令3、head指令4、tail指令5、bc指令6、管道文件介绍7、与时间相关的指令 总结 前言 本文介绍Linux使用时的部分指令&#xff0c;读者如果想了解更多基本指令的使用&#xff0c;可以关注博主的后续的文章。 博主使用的实…

Shiro应用到Web Application

一、权限基础 a) 认证(你是谁&#xff1f;) 判断你(被认证者)是谁的过程。通常被认证者提供用户名和密码。 常见的认证包含如下几种&#xff1a; 匿名认证&#xff1a;允许访问资源&#xff0c;不做任何类型的安全检查。表单认证&#xff1a;访问资源之前&#xff0c;需要提…

【Linux】进程探秘

文章目录 一、什么是进程&#xff1f;1.1写一个进程 二、操作系统是如何管理的进程的呢&#xff1f;2.1描述进程-PCB2.2组织进程 三、Linux下是怎么做的&#xff1f;3.1task_struct-PCB的一种3.2task_ struct内容分类3.3linux中组织进程3.4查看进程的相关属性 &#x1f340;小结…

SpringCloud Alibaba - Seata 四种分布式事务解决方案(XA、AT)+ 实践部署(上)

目录 一、Seata 分布式事务解决方案 1.1、XA 模式 1.1.1、XA模式理论 第一阶段&#xff1a; 第二阶段&#xff1a; 1.1.2、Seata 框架中的 XA 模式 第一阶段&#xff1a; 第二阶段&#xff1a; 1.1.3、XA 模式的优缺点 1.2.4、实现Seata 的 XA 模式 a&#xff09;修改…

数组结构与算法

文章目录 数据结构与算法稀疏数组sparse队列单向链表双向链表单向环形列表&#xff1a;CircleSingleLinkedList栈递归排序算法快速排序思路 树赫夫曼树 &#xff08;HuffmanTree&#xff09;二叉排序树&#xff08;Binary sort tree&#xff09;构建二叉树遍历二叉树 平衡二叉树…

1300*B. Sort the Array(排序构造)

题意&#xff1a; 一个无重复数字的序列&#xff0c;能否反转一个区间使其成为单增序列。 解析&#xff1a; 记录每个点的值和初始下标&#xff0c;然后排序。 对于排好序的序列进行遍历&#xff0c;找出第一段和原序列下标不同的区间并且标记&#xff08;此区间即为翻转的区…

便携式脑卒中检测仪是不是离现实不远了?

摘要&#xff1a;本文介绍一个轻量级人工智能的应用--基于tinyML的便携式低成本脑部微波成像系统。参考资料为DOI&#xff1a; 10.1109/ISCAS46773.2023.10181746 医疗资源从来都是稀缺资源。 我们都经历过在医院CT和核磁共振室外排队的情况。即使您万分紧急&#xff0c;也只能…

计算机网络(六):应用层

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 应用层概述 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分 早期基于文本的应用 (电子邮件、远程登…

逐步解决Could not find artifact com:ojdbc8:jar:12

Could not find artifact com:ojdbc8:jar:12 in central (https://repo.maven.apache.org/maven2) 原因&#xff1a; ojdbc8:jar:12 属于Oracle 数据库链接的一个程序集&#xff0c;缺失的话很有可能会影响数据库链接&#xff0c;蝴蝶效应产生不可预测的BUG&#xff01;但是版…