MySQL用户变量必须用@前缀,如SET @myvar = 1;系统变量需指定GLOBAL/SESSION作用域;SELECT中赋值必须用:=,且需初始化防NULL;并发不安全,复杂逻辑应优先用临时表或CTE。

SET 语句设置用户变量时必须用 @ 前缀
MySQL 中 SET 赋值分两类:系统变量(如 sql_mode)和用户变量(自定义,以 @ 开头)。不加 @ 直接写变量名,MySQL 会当成系统变量或报错——比如 SET myvar = 1 会提示 Unknown system variable 'myvar'。
- 正确写法是
SET @myvar = 1或SET @myvar := 1 -
=和:=在SET语句中等价,但在SELECT中只有:=是赋值操作符 - 用户变量作用域是当前会话,断开连接后自动销毁
SET 修改全局/会话级系统变量需明确作用域前缀
像 autocommit、max_connections 这类系统变量,直接 SET max_connections = 200 默认修改的是当前会话值;要改全局,必须显式加 GLOBAL 或 SESSION(后者可省略)。
- 仅影响当前连接:
SET SESSION sort_buffer_size = 4*1024*1024 - 影响所有新连接(需 SUPER 权限):
SET GLOBAL max_connections = 500 - 查看当前值:
SELECT @@sort_buffer_size(会话)或SELECT @@GLOBAL.max_connections - 某些变量只读,例如
version,执行SET version = 'x'会报错Variable 'version' is a read only variable
用户变量在 SELECT 中赋值容易混淆 = 和 :=
在 SELECT 里用 = 是比较操作符,不是赋值。如果写成 SELECT @sum = @sum + value FROM t,结果全是 0 或 1(布尔判断),而不是累加。
SELECT @sum := @sum + value FROM t;
- 必须用
:=才能赋值 - 首次使用前建议初始化:
SET @sum := 0,否则@sum为NULL,后续计算结果全为NULL - 这种写法常用于模拟窗口函数(如累计求和),但不可靠:MySQL 不保证
SELECT的行处理顺序,除非配合ORDER BY显式排序
SET 不能跨语句复用表达式结果,临时表或 CTE 更可靠
有人想用 SET @val = (SELECT COUNT(*) FROM users); SELECT @val, @val * 2; 看似可行,但若中间穿插了其他 SELECT ... INTO @var 或触发器,@val 可能被意外覆盖。更麻烦的是,存储过程里多个 SET 之间没有隐式事务保护。
- 复杂逻辑建议改用临时表:
CREATE TEMPORARY TABLE tmp AS SELECT COUNT(*) c FROM users; - MySQL 8.0+ 推荐用 CTE:
WITH t AS (SELECT COUNT(*) c FROM users) SELECT c, c*2 FROM t; - 用户变量不适合并发场景——两个会话同时
SET @id = ...互不影响,但若依赖变量做业务逻辑(如生成单号),极易出错
变量生命周期短、无类型、易被覆盖,这些特性决定了它只适合简单会话内临时传递值。真要持久或结构化,别硬扛。










