MySQL进阶教程(一)—— 储存过程与触发器(上)

@
目录

前言

在完成了我们的MySQL的基础教程后,对数据库与表结构的基础操作有了基础概念后,我们继续对MySQL的特性进行学习。本次教程将聚焦与SQL语句来进行介绍,本期要介绍的是储存过程与触发器。

一、准备工作

(一)SQL语句分类型

在正式开始内容前,我们需要回顾一下SQL语句的分类,我们才能具体知道存储过程和触发器到底是一个怎么样的概念。其中SQL语句可分为以下几类。

  • DDL【data definition language】 数据定义语言,用来维护存储数据的结构
    代表指令: create, drop, alter
  • DML【data manipulation language】 数据操纵语言,用来对数据进行操作
    代表指令: insert,delete,update
    DML中又单独分了一个DQL,数据查询语言,代表指令: select
  • DCL【Data Control Language】 数据控制语言,主要负责权限管理和事务
    代表指令: grant,revoke,commit

(二)Navicat工具

本次课程SQL语句的编写将借助Navicat这个工具,有兴趣的读者可以了解一下该工具的使用。

Navicat 是一款专业的图形化数据库管理和开发工具。它的核心价值在于,用一个直观的图形界面替代了复杂的命令行操作,让我们更方便的连接与管理各类数据库。

在这里,我们给出Navicat免费版本的Navicat Premium Lite的官网下载链接,有需要的友友可用。点此处去下载

二、存储过程

(一)定义与特性

存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字和参数来执行,并获取相应的结果。

其具有封装性、可维护性、可重复性的特点 。与用应用程序直接操作数据库的不同点可以用下图进行解释。

可见,其相当与一个经编译后存储在数据库里的媒介,替代应用程序去完成操作数据库的任务。

除了以上特性外,存储过程还有着以下优缺点。

优点:

  • 性能优化:存储过程在创建时编译并存储在数据库中,执行速度比单个SQL语句快。
  • 代码重用:存储过程可以重复调用,减少重复代码,提高代码的可维护性。
  • 安全性:可以限制用户直接访问数据库,通过存储过程间接访问,从而保证系统安全性。
  • 事务管理:可以在存储过程中实现复杂的事务逻辑。
  • 降低耦合:当表结构发⽣变化时,只需要修改相应的存储过程,应用程序的改动较小。

缺点:

  • 可移植性差:存储过程不能跨数据库移植,更换数据库时需要重新编写。
  • 调试困难:只有少数数据库管理系统支持存储过程的调试,开发和维护困难。
  • 不适合高并发场景:在高并发场景下,存储过程可能会增加数据库的压力,难以维护。

(二)相关语法

1、创建

sql 复制代码
-- 修改SQL语句结束标识符为 //
DELIMITER //
-- 创建存储过程
CREATE PROCEDURE 存储过程名 (参数列表)
BEGIN
-- SQL 语句
END //
-- 修改SQL语句结束标识符为 ;
DELIMITER ;'

2、调用

sql 复制代码
-- 调⽤存储过程
CALL 存储过程名 (参数列表);

3、查看

sql 复制代码
-- 查看指定数据库中创建的存储过程
SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = '数据库名';
-- 查看存储过程的定义
SHOW CREATE PROCEDURE 存储过程名;

4、删除

sql 复制代码
DROP PROCEDURE [IF EXISTS] 存储过程名;

下面给出使用的例子

sql 复制代码
-- 计算学生们总分
-- 创建存储过程
DELIMITER //
DROP PROCEDURE IF EXISTS p1;
CREATE PROCEDURE IF NOT EXISTS p1() 
BEGIN
  select name,chinese + math + english as total from exam;
END //

DELIMITER ;
  
-- 调用存储过程
call p1();

其中的 DELIMITER // 是用来告诉客户端,接下来遇到 // 才认为一条完整语句结束。存储过程内部的 ; 不会被客户端当作语句结束符。其只在使用 mysql 命令行或支持该命令的客户端时需要,例如 mysql CLI、Navicat 的查询窗口。

三、变量

在MySQL中变量主要分为:系统变量、用户自定义变量和局部变量。

(一)系统变量

系统变量是MySQL服务器的配置变量,控制着服务器的行为和性能。分为全局变量(GLOBAL)和会话变量(SESSION) 。

1、查看环境变量

sql 复制代码
-- 查看所有系统变量
SHOW [GLOBAL|SESSION] VARIABLES;
-- 查看指定的系统变量
SHOW [GLOBAL|SESSION] VARIABLES LIKE 'xxx';
-- 查看指定的系统变量,可以通过LKIE进⾏模糊查询
SHOW [GLOBAL|SESSION] VARIABLES like '%xxx%';
-- 使⽤SELECT查看指定系统变量
SELECT @@[GLOBAL|SESSION].系统变量名;

2、设置环境变量

sql 复制代码
SET [GLOBAL|SESSION] 系统变量名 = 值;
SET @@SESSION.系统变量名 = 值;

值得注意的是:

如果在设定时没有指定GLOBAL|SESSION ,则默认设置为会话SESSION。

当会话关闭后,所设置的会话变量会失效,新建会话时读取全局系统变量来作为初始值。

当MySQL重启后,设置的全局变量就会失效,想要自己设置的全局变量永久生效,需要去修改对应的配置文件。

(二)用户自定义变量

用户自定义变量是在SQL会话中定义的变量,不用提前声明,其作用域为当前会话。

1、赋值

sql 复制代码
-- ⽅式⼀
SET @var_name = expr [, @var_name]...;
-- ⽅式⼆ 【推荐】
SET @var_name := expr [, @var_name]...;
-- ⽅式三:在SELECT语句中
SELECT @var_name := expr [, @var_name]...;
-- ⽅式四:查询结果赋值给⾃定义变量
SELECT 列名 INTO @var_name FROM 表名 WHERE ...;

因为由于SQL中比较比较相等也是使用等号 (=),所以在为变量赋值的时候推荐使用 ( := ) 。

举一个例子:

sql 复制代码
-- ⽰例:定义⼀个age变量并赋值为18,并查看
SET @age := 18;
SELECT @age;
-- ⽰例:从学⽣表中查询编号为1的学⽣学号并赋值给sno变量
SELECT sno INTO @sno from student where id = 1;
SELECT @sno;
-- ⽰例:查询学⽣表中的总记录数并赋值给conut变量
SELECT count(*) INTO @count from student;
SELECT @count;
-- ⽰例:访问⼀个未赋值的变量,返回NULL
SELECT @var;

(三)局部变量

局部变量只在存储过程、函数或触发器的范围内有效。需要使用 DECLARE 声明,使用的作用域的范围在声明的 BEGIN ... END 块内。

1、声明

DECLARE 变量名 变量类型 DEFAULT 默认值 ...;

2、赋值

sql 复制代码
-- ⽅式⼀
SET var_name = 值;
-- ⽅式⼆ 【推荐】
SET var_name := 值;
-- ⽅式三:查询结果赋值给⾃定义变量
SELECT 列名 INTO var_name FROM 表名 WHERE ...;

具体使用的例子:

sql 复制代码
-- ⽰例:在存储过程中定义局部变量记录学⽣表的总记录数
delimiter //
drop procedure if exists p2;
create procedure if not exists p2()
begin
  declare stu_cnt int default 0;
  select count(*) into stu_cnt from student;
  select stu_cnt;
end //

delimiter ;

call p2();

要注意的是:

  • 变量名不区分大小写
  • 在存储过程和函数中,局部变量必须在使用前声明。
  • 用户自定义变量在会话结束时失效,而局部变量在存储过程或函数结束时失效。
  • 避免使用保留字作为变量名。

结语

以上便是本期关于MySQL储存过程与触发器章节的上部分内容了。如果喜欢我的内容,请点赞、收藏加关注,多多支持我,以及欢迎各位在评论区讨论交流,并指出我的不足,谢谢大家。