• MySQL | 存储《康师傅MySQL从入门到高级》笔记


    🐒自己重新梳理一遍,也是一个消化的过程。学习一定要注重输入和输出,如果只输入的话,很多时候只是大脑此刻懂了,但并未记住。这样在实际做题或应用时,就无从下笔了。


    存储 Stored

    存储过程存储函数可以将复杂的SQL逻辑封装在一起应用程序无需关注存储过程和函数内部复杂的SQL逻辑,只需要简单地调用存储过程和函数即可。

    1. 存储过程 PROCEDURE

    思想

    • 一组经过预先编译的SQL语句的封装

    执行过程

    • 存储过程预先存储在MySQL服务器上
    • 需要执行的时候,客户端只需要向服务器发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列SQL语句全部执行。

    优点:

    • 可以一次编译多次使用——减少开发人员的压力
    • 良好的封装性——减少失误,提高效率
    • 减少网络传输量
    • 存储过程的安全性强——减少SQL语句暴露的风险

    缺点:

    • 可移植性差
    • 调试困难
    • 存储过程的版本管理很困难
    • 不适合高并发的场景

    使用

    • 像使用函数一样简单

    存储过程没有返回值

    (1)创建存储过程

    DELIMITER $  -- 新的结束标记
    
    CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型, IN|OUT|INOUT 参数名 参数类型, ...)
    
    	[characteristics ...]  -- 存储过程的约束条件
    	--LANGUAGE SQL
    	--| [NOT] DETERMINISTIC
    	--| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
    	--| SQL SECURITY { DEFINER | INVOKER }  -- 安全级别(定义者可以调用 | 有权限就可以调用),默认为DEFINER
    	--| COMMENT 'string'
    
    	BEGIN
    		查询语句
    	END $
    
    DELIMITER ;  -- 恢复结束标记
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 常用的两种结束标记:$//
    • SET:赋值语句,对变量进行赋值。
    • SELECT INTO:将赋值语句的查询结果存放到变量中,也就是为变量赋值。
    • 五种输入参数

      ①没有参数(无参数无返回)
      IN(由参数无返回)
      OUT(无参数有返回)
      IN和OUT(有参数有返回)
      INOUT(有参数有返回)

    (2)调用存储过程

    CALL 存储过程名(实参列表)
    
    • 1

    (3)查看存储过程

    ①查看存储过程的创建信息

    SHOW CREATE PROCEDURE 存储过程名
    
    • 1

    ②查看存储过程的状态信息

    SHOW PROCEDURE STATUS [LIKE '...']
    
    • 1

    在这里插入图片描述

    (4)修改存储过程

    ALTER PROCEDURE 存储函数名
    
    • 1

    (5)删除存储过程

    DROP PROCEDURE IF EXIST 存储函数名;
    
    • 1

    2. 存储函数 FUNCTION

    • 用于查询

    • 有且仅有一个返回值

    (1)创建存储函数

    DELIMITER //
    
    CREATE FUNCTION 存储函数名(参数名, 参数类型)
    	RETURNS 返回值类型
    			# 为了避免报错,需要加上下面三行
    	        DETERMINISTIC  --
    	        CONTAINS SQL -- 包含SQL
    	        READS SQL DATA
    	
    	BEGIN
    		RETURN(SELECT查询语句);
    	END //
    
    DELIMITER;  --把结束符号重新设为`;`
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    # 为避免报错,需要加这一句
    SET GLOBAL log_bin_trust_function_creators = 1;
    
    DELIMITER //
    
    CREATE FUNCTION 存储函数名(参数名1 参数类型, 参数名2 参数类型, ...)
    	RETURNS 返回值类型
    
    	BEGIN
    		RETURN(SELECT查询语句);
    	END //
    
    DELIMITER;  --把结束符号重新设为`;`
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (2)调用存储函数

    SELECT 存储函数名();  -- 调用函数
    
    • 1
    SET @emp_id := 102;  -- 定义变量
    # SET @emp_id = 102;  `:=`和`=`都可以
    SELECT 存储函数名(@emp_id);  --调用函数
    
    • 1
    • 2
    • 3

    巧记:因为存储函数适用于查询,所以调用它也用SELECT

    (3)查看存储函数

    ①查看存储函数的创建信息

    SHOW CREATE FUNCTION 存储函数名
    
    • 1

    ②查看存储函数的状态信息

    SHOW FUNCTION STATUS [LIKE '...']
    
    • 1

    (4)修改存储函数

    ALTER FUNCTION 存储函数名
    
    • 1

    (5)删除存储函数

    DROP FUNCTION IF EXIST 存储函数名;
    
    • 1

    存储的补充知识

    1. 变量

    两种赋值符号都可以,效果一样

    • =
    • :=

    (1)系统变量

    系统变量用@@开头

    两种默认值

    • 编译MySQL时参数的默认值
    • my.iniMySQL配置文件中的参数值

    修改系统变量的值

    • 在MySQL服务运行期间,使用SET命令重新设置系统变量的值。
    • 修改my.iniMySQL配置文件,继而修改MySQL系统变量的值(该方法需要重启MySQL服务)

    默认为会话系统变量

    ①全局系统变量(简称:全局变量)

    global关键字

    • max_connections:只能是全局系统变量,限制服务器的最大连接数
    • 查看所有全局变量SHOW GLOBAL VARIABLES;
    • 查看满足条件的部分全局变量SHOW GLOBAL VARIABLES LIKE '%标识符%';
    • 查看指定全局变量SELECT @@global.变量名;

    为全局变量赋值

    • 方式1
      SELECT @@global.变量名;
      SET GLOBAL 变量名=变量值;
      
      • 1
      • 2
    • 方式2
      SELECT @@global.变量名;
      SET @@global.变量名=变量值;
      
      • 1
      • 2

    ②会话系统变量(简称:local变量)

    session关键字

    • 会话系统变量的初始值是全局系统变量值的复制。

    • pseudo_thread_id:作用于只能是当前会话,用于标记当前会话的MySQL连接ID。

    • 查看所有会话变量SHOW SESSION VARIABLES;SHOW VARIALBLES;(因为变量默认是会话系统变量

    • 查看满足条件的部分会话变量SHOW SESSION VARIABLES LIKE '%标识符%';

    • 查看指定会话变量SELECT @@session.变量名;SELECT @@变量名;

    为会话变量赋值

    • 方式1
      SELECT @@session.变量名;
      SET SESSION 变量名=变量值;
      
      • 1
      • 2
    • 方式2
      SELECT @@session.变量名;
      SET @@session.变量名=变量值;
      
      • 1
      • 2

    (2)用户自定义变量

    用户自定义变量用@开头:会话用户变量(不用指明类型),局部变量(需要指明类型)

    ①会话用户变量

    • 定义与赋值需要加@,不需要指定类型
      1.手动赋值

      SET @用户变量 = 值;
      SET @用户变量 := 值;
      
      • 1
      • 2

      2.赋表中的字段值

      SELECT @用户变量 := 表达式 [FROM 等字句];
      SELECT 表达式 INTO @用户变量 [FROM 等字句];
      
      • 1
      • 2
    • 作用域
      只对当前会话有效
      可以加在会话的任何地方

    • 查看用户变量

      SELECT @用户变量
      
      • 1

    ②局部变量

    • 定义需要指定类型

      DECLARE 局部变量名 类型 [default];
      # 如果没有default子句,初始值为NULL
      
      • 1
      • 2
    • 赋值不需要加@
      1.手动赋值

      SET 变量名=SET 变量名:=
      • 1
      • 2

      2.赋表中的字段值

      SELECT 字段名或表达式 INTO 变量名 FROM;
      
      • 1
    • 作用域

      只在BEGIN和END语句块中有效,且只能放在第一句
      只能在存储过程和函数中使用

    • 使用变量

      SELECT 局部变量名
      
      • 1
    DELIMITER //
    
    CLEAR PROVEDURE/FUNCTION 存储过程名/存储函数名
    
    BEGIN
    	# 声明局部变量
    	DECLARE 局部变量名 类型 DEFAULT 默认值;
    
    	# 为局部变量赋值
    	SET 局部变量名 =;
    	SELECT 字段名 INTO 局部变量名 FROM 表名 WHERE 筛选条件;
    	
    	# 查看局部变量的值
    	SELECT 变量1, 变量2, ...;
    END
    
    DELIMITER ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2. “异常”处理

    为了避免程序一报错就停止运行,可以实现将可能发生的错误列出来,当错误出现时,只用报相应的错误代码,而保证程序能够顺利执行完毕。

    (1)定义条件

    即:实现定义程序执行过程中可能遇到的问题命名。将一个错误名字指定的错误条件关联起来。

    # MySQL_error_code
    DECLARE 错误名 CONDITION FOR 数值类型错误码
    
    # sqlstate_value
    DECLARE 错误名 CONDITION FOR SQLSTATE 字符串类型错误码
    
    • 1
    • 2
    • 3
    • 4
    • 5

    例:在ERROR 1418(HY000)中:

    1418MySQL_error_code数值类型错误代码),
    HY000sqlstate_value长度为5的字符串类型错误代码

    DECLARE field_Not_Be_NULL CON
    
    • 1

    (2)处理程序

    即:定义在遇到问题时应当采取的处理方式,保证存储过程或函数在遇到警告或错误时能继续执行。

    • 增强存储程序处理问题的能力,避免程序异常停止运行。
    DECLARE 处理方式 HANDLER FOR 错误类型 处理语句
    
    • 1

    处理方式

    • CONTINUE:遇到错误不处理,继续执行。
    • EXIT:遇到错误马上退出

    错误类型

    • SQLSTATE ‘字符串错误码’:表示长度为5的sqlstate_value类型的错误代码
    • MySQL_error_code:匹配数值类型错误代码
    • 错误名称:表示DECLARE...CONDITION定义的错误条件名称
    • SQLWARNING :匹配所有以01开头的SQLSTATE错误代码;
    • NOT FOUND :匹配所有以02开头的SQLSTATE错误代码;
    • SQLEXCEPTION :匹配所有没有被SQLWARNINGNOT FOUND捕获的SQLSTATE错误代码;

    处理语句
    SET 变量 = 值

    BEGIN...END

    定义处理程序的几种方式,代码如下:

    #方法1:捕获sqlstate_value
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'NO_SUCH_TABLE';
    
    #方法2:捕获mysql_error_value
    DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'NO_SUCH_TABLE';
    
    #方法3:先定义条件,再调用
    DECLARE no_such_table CONDITION FOR 1146;
    DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info = 'NO_SUCH_TABLE';
    
    #方法4:使用SQLWARNING
    DECLARE EXIT HANDLER FOR SQLWARNING SET @info = 'ERROR';
    
    #方法5:使用NOT FOUND
    DECLARE EXIT HANDLER FOR NOT FOUND SET @info = 'NO_SUCH_TABLE';
    
    #方法6:使用SQLEXCEPTION
    DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3. 流程控制

    (1)条件判断语句IF CASE

    ①IF

    用在BEGIN...END

    DELIMITER //
    
    CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
    
    	[标记名:]BEGIN
    	
    		IF ...
    			THEN ...  -- LEAVE 标记名
    		ELSEIF ...
    			THEN ...
    		ELSE
    		END IF;
    	
    	END //
    
    DELIMITER ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ②CASE

    用于BEGIN...END

    • 情况1(类似与switch)

      CASE 表达式
      WHEN1 THEN 结果1或语句1(语句1的结尾要加;)
      WHEN2 THEN 结果2或语句2(语句1的结尾要加;)
      ...
      ELSE 结果n或语句n(语句n的结尾要加;)
      END CASE
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 情况2(类似于多重IF)

      CASE 
      WHEN 条件1 THEN 结果1或语句1(语句1的结尾要加;)
      WHEN 条件2 THEN 结果2或语句2(语句1的结尾要加;)
      ...
      ELSE 结果n或语句n(语句n的结尾要加;)
      END CASE
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    (2)循环语句LOOP WHILE REPEAT

    三种循环都可以省略名称。
    但如果循环中添加了循环控制语句(LEAVE或ITERATE),则必须添加名称

    ①LOOP(一般用于实现简单的"死"循环。(通常要结合LEAVE使用))

    DELIMITER //
    
    CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
    
    BEGIN
    
    	# 定义变量,用于记录循环次数
    	DECLARE loop_count INT DEFAULT 0;
    
    	# ①初始化循环条件
    	SELECT ...
    
    	[标记名:]Loop
    
    		# ②循环条件(何时结束循环)
    		[IF ... THEN LEAVE [标记名];
    		END IF;]
    		[IF ... THEN ITERATE [标记名];
    		END IF;]
    		# ③循环体——循环要完成的任务
    		... -- 根据题目要求写
    		
    		# ④迭代条件
    		...;  -- 重新计算循环条件(与初始化循环条件一致)
    		
    		SET loop_count = loop_count +1;  -- 循环次数+1
    
    	END LOOP loop;
    	
    END //
    
    DELIMITER ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    ②WHILE(先判断后执行)

    DELIMITER // 
    
    CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
    
    BEGIN
    	# ①初始化循环条件
    
    	# ②循环条件
    	[标记名]:WHILE 循环条件 DO
    		# ③循环体
    		# ④迭代条件
    		[IF ...
    			LEAVE 标记名;
    		END IF;]
    		
    	END WHILE;
    	
    END //
    
    DELIMITER ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    ③REPEAT(先执行后判断,无条件至少执行一次)

    DELIMITER //
    
    CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
    
    BEGIN
    
    	REPEAT
    		循环
    	UNTIL  -- 结束循环的条件。注意:这句没有`;`	
    	END REPEAT;
    
    END //
    
    DELIMITER ;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    (3)跳转语句ITERATE LEAVE

    LEAVE类似于break

    LEAVE 标记名
    
    • 1

    ITERATE类似于continue

    只能用在LOOP/REPEAT/WHILE循环语句中

    ITERATE 标记名
    
    • 1

    4. 触发器

    事件:用户的动作或触发某项行为,包括INSERT, UPDATE, DELETE

    当执行INSERT, UPDATE, DELETE事件时,会自动激发触发器执行相应的操作。

    (1)触发器的创建

    DELIMITER //
    
    CREATE TRIGGER 触发器名称
    {BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名  -- `表名`为触发器监控的对象
    FOR EACH ROW
    
    BEGIN
    	触发器执行的语句块;
    	-- VALUE(NEW.字段名)
    	-- VALUE(OLD.字段名)
    END //
    
    DELIMITER ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • BEFORE 表示在事件之前触发
    • AFTER 表示在事件之后触发
    • INSERT 表示插入记录时触发
    • UPDATE 表示更新记录时触发
    • DELETE 表示删除记录时触发
    • NEW关键字用于调用最新插入的数据(用在触发器执行的语句块VALUE语句中,如VALUE(NEW.字段名)可用于查看该字段最新插入的数据值。)
    • OLD关键字用于调用最近删除的数据(用在触发器执行的语句块VALUE语句中,如VALUE(OLD.字段名)可用于查看该字段最近删除的数据值。)

    验证触发器是否起作用
    注:与上方创建触发器的代码中的BEGIN...END中对应

    BEGIN
    触发器执行的语句块

    这个语句块可用于将触发后的操作记录在指定表中。
    .
    这样,当被触发器监控的对象触发操作时,这个指定表就会记录相应的内容。
    .
    通过SELECT * FROM 指定表;,可以查看是否触发了触发器。

    END

    (2)查看触发器

    • 查看当前数据库的所有触发器的定义
      SHOW TRIGGERS
    • 查看当前数据库中某个触发器的定义
      SHOW CREATE TRIGGER 触发器名
    • 从系统库information_schemaTRIGGER表中查询“salary_check_trigger”触发器的信息
      SELECT * FROM information_schema.TRIGGERS;

    (3)删除触发器

    DROP TRIGGER IF EXISTS 触发器名称
    
    • 1

    (4)触发器的优缺点

    优点

    • 确保数据的完整性
    • 帮助我们记录操作日志
    • 在操作数据前,对数据进行合法性检查

    缺点

    • 可读性差(触发器由事件驱动,不受应用层的控制)
    • 相关数据的变更,可能会导致触发器出错
    • 如果在子表中定义了外键约束,并且外键指定了DML操作,此时修改父表也会引起子表的相应操作。但是,基于子表的相应触发器不会被激活
  • 相关阅读:
    CPS攻击案例(一)——基于脉冲宽度调制PWM的无人机攻击
    RK平台ADB不识别问题排查
    使用EasyCV Mask2Former轻松实现图像分割
    leetcode:1157. 子数组中占绝大多数的元素【暴力遍历 + 随机算法相信概率】
    计算机毕业设计Java物联网实验课程考勤网站(源码+系统+mysql数据库+Lw文档)
    C语言 题目 1760: 字符序列模式识别
    HTML - 请你谈一谈img标签图片和background背景图片的区别
    【Linux】多线程互斥与同步
    【FreeRTOS】【STM32】06.1 FreeRTOS的使用1(对06的补充)
    C03-【计算机二级】Excel操作题(2)全国人口普查数据的统计分析
  • 原文地址:https://blog.csdn.net/qq_44250700/article/details/125404766