Mysql之存储过程

1. 视图

视图是一个虚拟表,其内容由查询定义。与实际的物理表类似,视图也包含一系列具有名称的列和行数据。视图的数据变化会影响基表,反之,基表的数据变化也会影响视图。

1.1 基本使用

创建视图

创建视图的基本语法如下:

sql 复制代码
CREATE VIEW 视图名 AS SELECT 查询语句;

示例:查看学生的学号、姓名、成绩和课程号:

ini 复制代码
SELECT s1.sno, snme, sdept, grade, cno 
FROM student s1 
JOIN score s2 ON s1.sno = s2.sno;

创建视图 v_s_s,该视图包含学生学号、姓名、成绩和课程号:

sql 复制代码
CREATE VIEW v_s_s AS 
SELECT s1.sno, snme, sdept, grade, cno 
FROM student s1 
JOIN score s2 ON s1.sno = s2.sno;

修改视图中的数据:假设我们希望修改马小燕课程号 001 的成绩为 100,若视图支持更新操作,可以修改原表数据:

ini 复制代码
UPDATE v_s_s 
SET grade = 100 
WHERE sno = '马小燕' AND cno = '001';

删除视图

删除视图的语法如下:

sql 复制代码
DROP VIEW 视图名;
1.2 视图的规则与限制

视图与基表之间存在紧密的关系,视图数据的修改会影响基表的数据,反之亦然。为了确保系统的稳定性,使用视图时需要特别注意以下限制:

  • 数据更新限制:并非所有视图都支持数据更新操作。特别是当视图涉及多个表的连接、聚合函数、分组(GROUP BY)等操作时,修改视图中的数据可能会受到限制。例如,包含聚合函数或联合查询的视图通常不支持更新。
  • 性能考虑:虽然视图可以简化查询,但如果查询的视图非常复杂且涉及大量数据,可能会导致性能问题。因此,在设计视图时应避免过于复杂的查询,特别是涉及大量数据的视图。
  • 不支持索引:视图本身不支持索引,因此在使用视图时,查询性能可能不如直接查询基表。如果视图查询包含复杂的计算或连接操作,可能会对查询性能产生影响。
  • 只读视图:一些视图被设计为只读的,无法修改其中的数据。这通常发生在视图涉及多表连接、聚合操作或复杂计算时。对于这种只读视图,修改视图中的数据将会失败。
1.3 视图与查找数据创建表的比较

视图和基于查询结果创建的表在以下方面有所不同:

  • 视图

    视图是动态的,它始终基于最新的查询结果。当视图中的数据发生变化时,实际的数据表也会发生变化。视图不存储数据本身,而是存储查询逻辑。当查询视图时,实际上是执行视图定义中的查询语句。

    语法示例:

    sql 复制代码
    CREATE VIEW t_name AS SELECT 查询数据;
  • 创建表

使用 CREATE TABLE 可以将查询结果保存为一个物理表。与视图不同,创建的表会将数据永久存储在数据库中,数据修改不会影响原始数据表。创建的表可以具有索引等性能优化。

语法示例:

sql 复制代码
CREATE TABLE t_name AS SELECT 查询数据;
1.4 视图添加限制

在 MySQL 中,视图虽然提供了极大的便利,但在某些情况下需要对其进行适当的限制,以确保数据的一致性和完整性。以下是常见的视图限制及其应用:

视图的修改限制

  • 当视图涉及多个表、聚合函数、分组等操作时,视图通常为只读,无法直接修改。只有在视图基于单一表且没有涉及复杂计算时,视图才通常支持数据更新操作。

  • 若需要限制视图中数据的修改,可以使用 WITH CHECK OPTION,该选项确保通过视图进行的更新操作符合视图中的条件,否则修改会被拒绝。

    例如,创建一个只允许修改 grade >= 60 的视图:

    sql 复制代码
    CREATE VIEW v_students AS 
    SELECT sno, snme, grade 
    FROM student 
    WHERE grade >= 60
    WITH CHECK OPTION;

视图查询限制

视图能够简化复杂的查询,但也需要根据实际需求进行适当限制。为了确保不暴露敏感数据,可以设计只包含非敏感字段或经过加密/脱敏处理的视图。

权限控制与安全性

权限设置示例:

vbnet 复制代码
GRANT SELECT ON v_employee_view TO 'user1';

使用视图时,应当考虑权限控制,通过为不同用户分配不同的视图访问权限,可以确保数据安全。视图可以提供一个中介层,使得用户仅能访问特定数据,而不暴露整个表的数据。

对于敏感数据,视图的设计应遵循最小权限原则,避免直接暴露敏感信息。


2. 存储过程的基本语法

存储过程是一组 SQL 语句的集合,它被存储在数据库中,并可根据需要执行,可以接收输入参数并返回结果。

2.1 创建存储过程

存储过程的创建需要修改语句分隔符,以避免与 SQL 语句的结束符(;)发生冲突:

sql 复制代码
DELIMITER $$  -- 修改分隔符以避免与语句结束符冲突
CREATE PROCEDURE procedure_name (parameters)
BEGIN
   -- SQL 语句
END$$
DELIMITER ;  -- 恢复分隔符

存储过程的参数包括:

  • IN:输入参数,用于向存储过程传递值。
  • OUT:输出参数,用于存储过程返回数据。
  • INOUT:输入输出参数,既可以接收输入数据,又可以返回结果。

不改变分隔符会出现报错:

2.2 调用存储过程

调用存储过程的语法如下:

scss 复制代码
CALL procedure_name(parameters);
2.3 查看存储过程信息
  1. 查看所有数据库的存储过程:

    sql 复制代码
    SHOW PROCEDURE STATUS;
  2. 查看当前数据库的存储过程:

    ini 复制代码
    SHOW PROCEDURE STATUS WHERE db = 'db_name';
  • Db:存储过程所在的数据库
  • Name:存储过程的名称
  • Type:存储过程类型(例如 PROCEDURE
  • Definer:存储过程的定义者
  • Modified:最后修改时间
  • Created:创建时间
  • Security_type:安全类型
  • Comment:存储过程的注释
2.4 查看存储过程定义

查看存储过程定义的语法:

sql 复制代码
SHOW CREATE PROCEDURE procedure_name;
2.5 删除存储过程

删除存储过程的语法如下:

sql 复制代码
DROP PROCEDURE procedure_name;

3. 变量

3.1 查看系统变量​​​​​​​
3.1.1查看所有系统变量

查看当前会话的系统变量:

ini 复制代码
SHOW SESSION VARIABLES;

查看全局系统变量:

sql 复制代码
SHOW GLOBAL VARIABLES;
3.1.2系统变量的模糊匹配
sql 复制代码
show session variables like '...';
​show global variables like '...';
3.1.3查看指定变量
sql 复制代码
select @@global.tname;----查看指定全局环境变量
select @@session.tname;----查看当前会话环境变量
3.2 设置全局变量与会话变量
Aspect 全局隔离权限 会话隔离权限
作用范围 系统范围,决定了系统的默认行为和限制 仅对当前会话有效,独立于全局权限
初始化与导入 在系统初始化时从全局设置导入 在新会话启动时从全局导入配置
修改的时效性 修改后不会立即影响现有会话,需重新启动会话才会生效 当前会话的隔离级别修改不会影响其他会话
对系统设计的影响 确保系统权限的统一性,易于集中管理 确保每个会话可以根据需要调整权限,而不影响其他会话
3.2.1全局变量设置
ini 复制代码
SET GLOBAL transaction_isolation_level = 'READ COMMITTED';

重新启动一个新的会话:

3.2.2当前会话变量设置
arduino 复制代码
set session transaction isolation level read committed;

重新启动一个会话:

3.3 用户定义变量

用户定义变量是会话级别的临时变量,用户可以在 SQL 语句中使用它们来存储数据或进行计算。变量名以 @ 开头。例如:

  • 使用 SET 语句定义变量:

    sql 复制代码
    SET @variable_name = value;-----方法一
    SET @variable_name := value;----方法二

    例如 ,定义一个名为 @age 的变量并赋值为 25:

    ini 复制代码
    SET @age = 25;
  • 也可以直接在查询语句中进行赋值:

    scss 复制代码
    SELECT @variable_name := expression;

    例如,将查询结果赋值给变量:

    sql 复制代码
    SELECT @age := age FROM users WHERE name = 'John';-----方法一
     
    SELECT age into @age FROM users WHERE name = 'John';---方法二
3.4 局部变量

局部变量是在存储过程、函数或触发器内部定义的变量,作用范围仅限于该存储过程、函数或触发器的执行期间。它们通常用于临时存储数据、进行计算或传递信息。

3.4.1 局部变量的声明

在 MySQL 中,局部变量通过 DECLARE 语句在存储过程、函数或触发器中声明。局部变量的作用范围仅限于声明它们的存储过程、函数或触发器内部,并且不能在 SQL 查询的其他地方使用。

局部变量的特点:

  • 局部性:局部变量仅在存储过程、函数或触发器的执行期间有效。当存储过程或函数执行完毕后,局部变量会被自动销毁。
  • 无法在查询外部使用:局部变量只能在其所在的存储过程、函数或触发器内使用,不能在 SQL 查询的其他部分引用。
  • 生命周期:当存储过程或函数执行结束时,局部变量的值会丢失。每次执行存储过程或函数时,局部变量会重新创建,并可以为其赋予初始值(如果指定了初始值)。

3.4.2 局部变量的使用

局部变量常用于存储中间计算结果、执行逻辑运算或在存储过程/函数中临时存储查询结果。它们的使用受到以下限制:

  • 声明位置DECLARE 语句必须在存储过程、函数或触发器的开头部分,也就是在 BEGIN 语句之前声明。
  • 命名规则 :局部变量不能使用以 @ 开头的命名方式。@ 是用于用户定义会话变量的前缀,局部变量不允许使用此命名规则。
  • 初始值 :如果没有为局部变量指定初始值,则其默认值为 NULL。因此,在使用局部变量时,开发者需要考虑 NULL 的处理,确保程序的逻辑正确。

语法:

ini 复制代码
DECLARE variable_name data_type [DEFAULT value];
  • variable_name:变量的名称。
  • data_type:变量的数据类型(如 INT, VARCHAR, DATE 等)。
  • [DEFAULT value]:可选,设置默认值。如果不指定,则默认值为 NULL

例子:

sql 复制代码
DECLARE @user_id INT DEFAULT 100;
DECLARE @user_name VARCHAR(255) DEFAULT 'John';

[](

相关推荐
程序员不想YY啊3 分钟前
MySQL元数据库完全指南:探秘数据背后的数据
数据库·mysql·oracle
iuyou️9 分钟前
Spring Boot知识点详解
java·spring boot·后端
一弓虽21 分钟前
SpringBoot 学习
java·spring boot·后端·学习
姑苏洛言30 分钟前
扫码小程序实现仓库进销存管理中遇到的问题 setStorageSync 存储大小限制错误解决方案
前端·后端
光而不耀@lgy1 小时前
C++初登门槛
linux·开发语言·网络·c++·后端
方圆想当图灵1 小时前
由 Mybatis 源码畅谈软件设计(七):SQL “染色” 拦截器实战
后端·mybatis·代码规范
毅航1 小时前
MyBatis 事务管理:一文掌握Mybatis事务管理核心逻辑
java·后端·mybatis
我的golang之路果然有问题2 小时前
速成GO访问sql,个人笔记
经验分享·笔记·后端·sql·golang·go·database
柏油2 小时前
MySql InnoDB 事务实现之 undo log 日志
数据库·后端·mysql
jack xu13 小时前
高频面试题:如何保证数据库和es数据一致性
java·大数据·数据库·mysql·elasticsearch