【数据库——MySQL】(15)存储过程、存储函数和事务处理习题及讲解

news2024/11/19 1:45:13

目录

  • 1. 题目
    • 1.1 存储过程
    • 1.2 存储函数
    • 1.3 事务处理
  • 2. 解答
    • 2.1 存储过程
    • 2.2 存储函数
    • 2.3 事务处理

1. 题目

1.1 存储过程

  1. 创建表 RandNumber :字段:id 自增长, data int; 创建存储过程向表中插入指定个数的随机数(1-99),但如果插入的数为 50,则终止插入。

  2. 创建存储过程,根据员工的工作时间,如果大于 6 年时,将其转到经理办公室工作,并调用该存储过程。

  3. 创建存储过程,比较两个员工的实际收入,若前者比后者高输出 1,若两者相等输出 0,若后者比前者高输出 -1,并调用该存储过程。

  4. 创建存储过程 p(in name char(10),out income decimal(7,2)),计算一个员工的实际收入,并调用该存储过程,将员工 朱骏 的实际收入保存在一个用户变量中。

  5. 创建存储过程 raise(in edu char(6),in x decimal(5,1)) 将所有某种学历的员工的收入提高 %x, 并调用该存储过程,将所有硕士学历的员工的收入提高 10%

1.2 存储函数

  1. 创建存储函数 getAver(did int),计算某个部门的平均工资(实际收入);

  2. 调用该函数,显示平均工资最高和最低的部门名称。

1.3 事务处理

设置事务处理为手动提交建立两个连接

  1. 观察 @@transaction_isolation 设置为 read-uncommited 时,脏读的情况。
    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 read-uncommited,开始事务,显示 employees 表中‘ 王林 ’员工信息;
    2)在另一个连接 B 中,修改‘ 王林 ’的 workYear10 年;
    3)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear
    4)在一个连接 B 中,回滚刚才的修改操作;
    5)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear

  2. 观察 @@transaction_isolation 设置为 read-commited 时,不可重复读的情况。
    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 read-commited
    2)开始事务,显示 employees 表中‘王林’员工信息;
    3)在另一个连接 B 中,修改‘王林’的 workYear10 年;
    4)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear
    5)在一个连接 B 中,提交刚才的修改操作;
    6)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear,提交事务。

  3. 观察 @@transaction_isolation 设置为 repeatable-read 时,幻读的情况。
    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 repeatable-read
    2)开始事务,显示 employees 表中所有员工信息,观察记录的数目;
    3)在另一个连接 B 中,在 employees 表插入一条记录,并提交事务;
    4)在连接 A 中显示 employees 表的员工信息,观察记录的数目;
    5)在连接 A 中,将所有员工的 workYear 增加一年,观察被修改的记录的数目;
    6)在连接 A 中提交事务;
    8)在连接 A 再次显示 employees 表中所有员工信息,观察记录的数目;

  4. 设置@@transaction_isolation 设置为 serializable
    重复第 3 个实验的操作,观察操作中出现的现象。

2. 解答

2.1 存储过程

use yggl;
  1. 创建表 RandNumber :字段:id 自增长, data int; 创建存储过程向表中插入指定个数的随机数(1-99),但如果插入的数为 50,则终止插入。

    drop table if EXISTS `yggl`.`RandNumber`;
    CREATE TABLE if not EXISTS`yggl`.`RandNumber`  (
      `id` int NOT NULL AUTO_INCREMENT,
      `data` int NOT NULL,
      PRIMARY KEY (`id`)
    );
    
    drop PROCEDURE if EXISTS p_RandNumber;
    delimiter $
    create procedure p_RandNumber(in n int)
    begin
    	declare temp int;
    	declare i int default(1);
    	set temp = 1 + floor(rand()*99);
    	while i <= n and temp != 50 do
    			insert into randnumber values (null, temp);
    			set temp = 1 + floor(rand()*99);
    			set i = i + 1;
    	end while;
    end$
    delimiter ;
    
    set @n=100;
    call p_RandNumber(@n);
    select * from randnumber;
    
  2. 创建存储过程,根据员工的工作时间,如果大于 6 年时,将其转到经理办公室工作,并调用该存储过程。

    drop PROCEDURE if EXISTS p2;
    delimiter $
    create procedure p2()
    begin
    	
    	declare did char(3);  # 部门编号
    	declare eid char(6);  # 员工编号
    	select departments.DepartmentID into did
    		from departments
    		where departments.DepartmentName = '经理办公室';
    		
    	select employees.EmployeeID into eid
    			from employees
    			where employees.WorkYear > 6;
    	
    	update employees
    	set DepartmentID = did
    	where employees.EmployeeID in
    	(eid);
    end$
    delimiter ;
    
    call p2();
    
  3. 创建存储过程,比较两个员工的实际收入,若前者比后者高输出 1,若两者相等输出 0,若后者比前者高输出 -1,并调用该存储过程。

    drop PROCEDURE if EXISTS p3;
    delimiter $
    create procedure p3(in mname1 char(10), in mname2 char(10))
    begin
    	declare m1 float;  # 第一个人的实际收入
    	declare m2 float;  # 第二个人的实际收入
    	declare flag int;  # 1,0,-1
    	select salary.InCome - salary.OutCome into m1
    		from salary join employees on salary.EmployeeID = employees.EmployeeID
    		where employees.`Name` = mname1;
    	select salary.InCome - salary.OutCome into m2
    		from salary join employees on salary.EmployeeID = employees.EmployeeID
    		where employees.`Name` = mname2;
    	if m1 > m2 then
    			set flag = 1;
    	elseif m1 = m2 then
    			set flag = 0;
    	else
    			set flag = -1;
    	end if;
    	select flag;
    end$
    delimiter ;
    
    call p3('王浩', '伍容华');
    
  4. 创建存储过程 p(in name char(10),out income decimal(7,2)),计算一个员工的实际收入,并调用该存储过程,将员工 朱骏 的实际收入保存在一个用户变量中。

    drop PROCEDURE if EXISTS p;
    delimiter $
    create procedure p(in `name` char(10),out income decimal(7,2))
    begin
    	select salary.InCome - salary.OutCome into income
    		from salary join employees on salary.EmployeeID = employees.EmployeeID
    		where employees.`Name` = `name`;
    	
    end$
    delimiter ;
    
    set @c=1;
    call p('朱骏', @c);
    select @c;
    
  5. 创建存储过程 raise(in edu char(6),in x decimal(5,1)) 将所有某种学历的员工的收入提高 %x, 并调用该存储过程,将所有硕士学历的员工的收入提高 10%

    drop PROCEDURE if EXISTS raise;
    delimiter $
    create procedure raise(in edu char(6), in x decimal(5,1))
    begin
    	update salary
    	set salary.InCome = salary.InCome*(1+x/100)
    	where EmployeeID in
    	(
    			select employees.EmployeeID
    				from employees
    				where employees.Education = edu);
    end$
    delimiter ;
    
    call raise('硕士', 10);
    

2.2 存储函数

  1. 创建存储函数 getAver(did int),计算某个部门的平均工资(实际收入);

    set GLOBAL log_bin_trust_function_creators = 1;    # 一共只需要设置一次
    
    drop FUNCTION if exists getAver;
    delimiter $
    create FUNCTION getAver(did int)
    returns float    # 返回某个部门的平均工资(实际收入)
    begin
    	declare aver float;
    	select AVG(salary.InCome - salary.OutCome) into aver
    	from employees join salary on employees.EmployeeID = salary.EmployeeID
    	where employees.DepartmentID = did;
    	return aver;
    end$
    delimiter ;
    
  2. 调用该函数,显示平均工资最高和最低的部门名称。

    # 平均工资最高的部门
    select departments.DepartmentName, getAver(departments.DepartmentID) as avg_salary
    from departments
    ORDER BY avg_salary desc
    limit 1;
    # 平均工资最低的部门
    select departments.DepartmentName, getAver(departments.DepartmentID) as avg_salary
    from departments
    ORDER BY avg_salary asc
    limit 1;
    

2.3 事务处理

设置事务处理为手动提交建立两个连接

set @@autocommit = 0;

在这里插入图片描述

  1. 观察 @@transaction_isolation 设置为 read-uncommited 时,脏读的情况。
    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 read-uncommited,开始事务,显示 employees 表中‘ 王林 ’员工信息;

    在这里插入图片描述

    2)在另一个连接 B 中,修改‘ 王林 ’的 workYear10 年;

    在这里插入图片描述

    3)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear

    在这里插入图片描述

    4)在一个连接 B 中,回滚刚才的修改操作;

    在这里插入图片描述

    5)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear

    在这里插入图片描述

    结论:一个事务 B 读取了另一个未提交的并行事务 A 写的数据。【脏读】

  2. 观察 @@transaction_isolation 设置为 read-commited 时,不可重复读的情况。
    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 read-commited

    在这里插入图片描述

    2)开始事务,显示 employees 表中‘王林’员工信息;

    在这里插入图片描述

    3)在另一个连接 B 中,修改‘王林’的 workYear10 年;

    在这里插入图片描述

    4)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear

    在这里插入图片描述

    5)在一个连接 B 中,提交刚才的修改操作;

    在这里插入图片描述

    6)在连接 A 中显示 employees 表的员工信息,观察‘王林’的 workYear,提交事务。

    在这里插入图片描述

    结论:一个事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过。【不可重复读】

  3. 观察 @@transaction_isolation 设置为 repeatable-read 时,幻读的情况。
    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 repeatable-read

    在这里插入图片描述

    2)开始事务,显示 employees 表中所有员工信息,观察记录的数目;

    在这里插入图片描述

    3)在另一个连接 B 中,在 employees 表插入一条记录,并提交事务;

    在这里插入图片描述

    4)在连接 A 中显示 employees 表的员工信息,观察记录的数目;

    在这里插入图片描述

    5)在连接 A 中,将所有员工的 workYear 增加一年,观察被修改的记录的数目;

    在这里插入图片描述

    6)在连接 A 中提交事务;

    在这里插入图片描述

    7)在连接 A 再次显示 employees 表中所有员工信息,观察记录的数目;

    在这里插入图片描述

    结论:一个事务重新执行一个查询,返回一套符合查询条件的行, 发现这些行因为其他最近提交的事务而发生了改变。【幻读】

  4. 设置@@transaction_isolation 设置为 serializable
    重复第 3 个实验的操作,观察操作中出现的现象,即:

    1)在一个连接 A 中,设置 @@transaction_isolation 设置为 serializable

    在这里插入图片描述

    2)开始事务,显示 employees 表中所有员工信息,观察记录的数目;

    在这里插入图片描述

    3)在另一个连接 B 中,在 employees 表插入一条记录,并提交事务;

    在这里插入图片描述

    4)在连接 A 中显示 employees 表的员工信息,观察记录的数目;

    在这里插入图片描述

    5)在连接 A 中,将所有员工的 workYear 增加一年,观察被修改的记录的数目;

    在这里插入图片描述

    6)在连接 A 中提交事务;

    在这里插入图片描述

    7)在连接 A 再次显示 employees 表中所有员工信息,观察记录的数目;

    在这里插入图片描述

    结论:对于同一个数据来说,在同一个时间段内,只能有一个会话可以访问,包括SELECT和DML,这样可以避免幻读问题。也就是说,对于同一(行)记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。【可序列化】

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

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

相关文章

UDP通信程序的详细解析

2.UDP通信程序 2.1 UDP发送数据 Java中的UDP通信 UDP协议是一种不可靠的网络协议&#xff0c;它在通信的两端各建立一个Socket对象&#xff0c;但是这两个Socket只是发送&#xff0c;接收数据的对象&#xff0c;因此对于基于UDP协议的通信双方而言&#xff0c;没有所谓的客户端…

MySql017——组合查询UNION和UNION ALL

一、UNION作用 可用UNION操作符来组合数条SQL查询。 二、UNION 使用规则 1、UNION的使用很简单。所需做的只是给出每条SELECT语句&#xff0c;在各条语句之间放上关键字UNION。2、UNION必须由两条或两条以上的SELECT语句组成&#xff0c;语句之间用关键字UNION分隔&#xff…

Hive 【Hive(七)窗口函数练习】

窗口函数案例 数据准备 1&#xff09;建表语句 create table order_info (order_id string, --订单iduser_id string, -- 用户iduser_name string, -- 用户姓名order_date string, -- 下单日期order_amount int -- 订单金额 ); 2&#xff09;装载语句 i…

代码随想录算法训练营第五十八天 | 动态规划 part 16 | 583. 两个字符串的删除操作、72. 编辑距离

目录 583. 两个字符串的删除操作思路思路2代码 72. 编辑距离思路代码 583. 两个字符串的删除操作 Leetcode 思路 dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结尾的字符串word2&#xff0c;想要达到相等&#xff0c;所需要删除元素的最少次数。递推公…

【AI视野·今日NLP 自然语言处理论文速览 第四十八期】Thu, 5 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 5 Oct 2023 Totally 50 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Retrieval meets Long Context Large Language Models Authors Peng Xu, Wei Ping, Xianchao Wu, Lawrence McA…

算法题:摆动序列

这道题是一道贪心算法题&#xff0c;如果前两个数是递增&#xff0c;则后面要递减&#xff0c;如果不符合则往后遍历&#xff0c;直到找到符合的。&#xff08;完整题目附在了最后&#xff09; 代码如下&#xff1a; class Solution(object):def wiggleMaxLength(self, nums):…

【力扣-每日一题】714. 买卖股票的最佳时机含手续费

class Solution { public:int maxProfit(vector<int>& prices, int fee) {//[i][0]-不持有 [i][1]-持有int mprices.size();vector<vector<int>> dp(m,vector<int>(2));dp[0][0]0; //初始状态dp[0][1]-prices[0];for(int i1;i<m;i){dp[i]…

光伏发电预测(LSTM、CNN_LSTM和XGBoost回归模型,Python代码)

光伏太阳能电池通过互连形成光伏模块&#xff0c;以捕捉太阳光并将太阳能转化为电能。因此&#xff0c;当光伏模块暴露在阳光下时&#xff0c;它们会产生直流电。这是目前将太阳能转化为电能的最佳方式之一。世界上许多国家已经采用了这项技术&#xff1b;然而&#xff0c;光伏…

Unity解决:安卓打包设置项目名称为中文名 packageName为英文包名

把productName改成中文名&#xff0c;然后在OtherSettings里面重写默认的包名就可以了

Android:实现手机前后摄像头预览同开

效果展示 一.概述 本博文讲解如何实现手机前后两颗摄像头同时预览并显示 我之前博文《OpenGLES&#xff1a;GLSurfaceView实现Android Camera预览》对单颗摄像头预览做过详细讲解&#xff0c;而前后双摄实现原理其实也并不复杂&#xff0c;粗糙点说就是把单摄像头预览流程写两…

抄写Linux源码(Day19:读取硬盘前的准备工作有哪些?)

回忆我们需要做的事情&#xff1a; 为了支持 shell 程序的执行&#xff0c;我们需要提供&#xff1a; 1.缺页中断(不理解为什么要这个东西&#xff0c;只是闪客说需要&#xff0c;后边再说) 2.硬盘驱动、文件系统 (shell程序一开始是存放在磁盘里的&#xff0c;所以需要这两个东…

如何在VMware workstation虚拟机中安装ensp(完美运行),解决报错40

如何在VMware workstation虚拟机中安装ensp&#xff08;完美运行&#xff09; 效果如图&#xff1a; 问题体现是ensp的路由器报错40&#xff0c;这是vbox相关的问题 在虚拟机中安装ensp的关键其实是vbox&#xff08;ensp依赖vbox&#xff09; ensp自带的vbox版本太低&#x…

想要精通算法和SQL的成长之路 - 存在重复元素

想要精通算法和SQL的成长之路 - 存在重复元素 前言一. 存在重复元素II二. 存在重复元素III2.1 基于红黑树增删改查 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 存在重复元素II 原题链接 思路&#xff1a; 我们用HashSet存储元素&#xff0c;做到去重的效果。同时存储…

防火墙的相关技术

安全技术&#xff1a;&#xff08;市场上常见的防御&#xff09; 1.入侵检测机制 阻断&#xff0c;量化&#xff0c;定位来自内外的网络的威胁情况 提供报警和事后监督。类似于监控。 2.入侵防御 以透明模式工作&#xff0c;分析数据包的内容&#xff0c;一切进入本机的内容…

windows 任务计划自动提交 笔记到github 、gitee

一、必须有个git仓库托管到git上。 这个就不用说了&#xff0c;自己在github或者码云上新建一个仓库就行了。 二、创建自动提交脚本 这个bat脚本是在windows环境下使用的。 注意&#xff1a;windows定时任务下 调用自动提交git前&#xff0c;必须先进入该git仓库目录&#x…

Windows11 安全中心页面不可用问题(无法打开病毒和威胁防护)解决方案汇总(图文介绍版)

本文目录 Windows版本与报错信息问题详细图片&#xff1a; 解决方案:方案一、管理员权限&#xff08;若你确定你的电脑只有你一个账户&#xff0c;则此教程无效&#xff0c;若你也不清楚&#xff0c;请阅读后再做打算&#xff09;方案二、修改注册表(常用方案)方案三、进入开发…

服务器or虚拟机安装SSH和虚拟机or服务器设置远程服务权限

第一步 服务器/虚拟机安装SSH工具,这是外部SSH终端连接服务器/虚拟机的第一步! sudo apt update && sudo apt upgrade#更新apt sudo apt install openssh-server#安装SSH工具 service ssh status#查看SSh运行状态 sudo systemctl enable --now ssh#运行SSH工具第二步…

基于SpringBoot的信息化在线教学平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 教师信息管理 学生成绩管理 留言板 学生注册管理 留言反馈 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已…

各平台更新根证书

windows7 windows7根证书更新 https://support.microsoft.com/en-us/topic/support-for-urgent-trusted-root-updates-for-windows-root-certificate-program-in-windows-a4ac4d6c-7c62-3b6e-dfd2-377982bf3ea5 Linux 查看证书 ls -l /etc/ssl/certs/更新根证书 update-ca…

Cocos Creator3.8 项目实战(七)Listview 控件的实现和使用

滚动列表在游戏中也很常见&#xff0c;比如排行榜 、充值记录等&#xff0c;在这些场景中&#xff0c;都有共同的特点&#xff0c; 那就是&#xff1a;数据量大 &#xff0c; 结构相同。 在cocoscreator 中&#xff0c;没有现成的 Listview 控件&#xff0c; 无奈之下&#xff…