Skip to content

MySQL - 变量

变量是存储数据值的命名容器。在编程和脚本中,它们允许您存储结果、操作结果并在以后引用它。MySQL 支持多种类型的变量,每种变量都有不同的作用域和用例,使您的 SQL 脚本更具动态性和强大功能。

理解不同类型的变量是编写高级查询、存储过程和管理脚本的关键。MySQL 主要有三类变量:

  • 用户定义变量:会话特定的变量,您可以在多个语句中设置和使用它们。
  • 局部变量:在存储程序、函数和触发器内部使用的变量,其作用域仅限于声明它们的 BEGIN...END 块。
  • 系统变量:预定义的服务器配置变量,用于控制 MySQL 服务器的行为。

用户定义变量特定于您当前的会话。它们以单个 @ 符号为前缀(例如,@my_variable)。一旦设置了用户定义变量,它会一直存在,直到您的会话结束(您断开连接)。它们是松散类型的,这意味着您不需要声明数据类型;数据类型会从您分配的值中推断出来。

您可以使用带有 = 的 SET 语句或带有 := 赋值运算符的 SELECT 语句来赋值。

-- 使用 SET(简单赋值的首选)
SET @my_name = 'Alice';
-- 使用 SELECT(从查询结果赋值时很有用)
SELECT @max_salary := MAX(salary) FROM employees;

让我们使用前面示例中的 employees 表。我们想找出哪些员工的薪水最高。我们可以使用变量分两步完成:

首先,找到最高薪水并将其存储在一个变量中。

SELECT @max_salary := MAX(salary) FROM employees;

其次,使用该变量查找所有获得该薪水的员工。

SELECT NAME, SALARY FROM employees WHERE SALARY = @max_salary;

这将显示薪水最高的员工,而无需使用子查询。

NAMESALARY
Charlie81000.00

局部变量用于存储程序中,如过程、函数、事件和触发器。它们使用 DECLARE 关键字声明,是强类型的,并且没有前缀。它们的作用域仅限于声明它们的 BEGIN...END 块。

DECLARE variable_name DATATYPE [DEFAULT default_value];

让我们创建一个存储过程,计算给定部门的总薪水。我们将使用一个局部变量 total_salary 来存储总和。

-- 更改分隔符以允许在存储过程内部使用分号
DELIMITER $$
CREATE PROCEDURE GetDepartmentSalary(IN dept_name VARCHAR(50))
BEGIN
-- 声明一个 DECIMAL 类型的局部变量
DECLARE total_salary DECIMAL(15, 2) DEFAULT 0.00;
-- 计算总和并将其存储在局部变量中
SELECT SUM(SALARY) INTO total_salary
FROM employees
WHERE DEPARTMENT = dept_name;
-- 返回结果
SELECT total_salary AS total_for_department;
END$$
-- 将分隔符重置回默认值
DELIMITER ;

现在,您可以调用该过程以获取“Engineering”部门的总薪水:

CALL GetDepartmentSalary('Engineering');
total_for_department
156000.00

系统变量控制 MySQL 服务器的配置和操作。它们可以在运行时查看,并且在许多情况下可以修改。它们有两个作用域:GLOBAL(全局)和 SESSION(会话)。

  • GLOBAL:全局设置影响服务器的整体行为。更改 GLOBAL 变量需要 SUPER 权限,并应用于更改后所有建立到服务器的新连接。
  • SESSION:会话设置仅影响当前的客户端连接。任何用户都可以更改会话变量,并且更改会在会话结束时被丢弃。
-- 显示所有系统变量
SHOW VARIABLES;
-- 显示匹配模式的变量
SHOW GLOBAL VARIABLES LIKE '%time_zone%';
-- 查看特定系统变量的值(注意 @@ 前缀)
SELECT @@sql_mode;
SELECT @@GLOBAL.max_connections;
-- 为当前会话设置系统变量
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE';
-- 全局设置系统变量(需要 SUPER 权限)
SET GLOBAL max_connections = 200;

让我们检查会话的当前时区,然后更改它。

-- 检查当前时区
SELECT @@session.time_zone; -- 可能会显示 'SYSTEM'
-- 将当前会话的时区设置为 UTC
SET SESSION time_zone = '+00:00';
-- 验证更改
SELECT @@session.time_zone; -- 现在显示 '+00:00'
特性用户定义变量局部变量
语法@variable_namevariable_name (无前缀)
声明不声明,直接通过 SET 或 SELECT 赋值在 BEGIN...END 块的开头用 DECLARE 声明
作用域整个连接会话声明它的 BEGIN...END 块
类型松散类型强类型(需要数据类型)
用例在单个会话中在语句之间传递值存储过程、函数和触发器中的逻辑