MySQL 中的自定義變量用法、場景與最容易踩的坑
在 MySQL 中,**自定義變量(User-Defined Variables)**是一種非常“靈活”的機(jī)制。
它不需要提前聲明,可以在 SQL 中直接賦值、直接使用,因此在寫復(fù)雜 SQL、做臨時(shí)計(jì)算時(shí)經(jīng)常能看到它的身影。
但同時(shí),它也是 MySQL 里最容易被誤用的特性之一。
本文從實(shí)際使用角度,系統(tǒng)講清楚:
它是什么、怎么用、適合干什么、不適合干什么。
一、什么是 MySQL 自定義變量
MySQL 自定義變量是指以 @ 開頭的變量,例如:
@count @total_price @row_num
它的核心特征有三點(diǎn):
- 無需聲明,直接使用
- 作用域是當(dāng)前會(huì)話(session)
- 主要用于 SQL 執(zhí)行過程中的臨時(shí)存儲(chǔ)
只要當(dāng)前連接不斷開,這個(gè)變量就一直存在。
二、自定義變量的基本用法
1. 變量賦值
常見的賦值方式有兩種。
方式一:使用 SET
SET @a = 10; SET @b := 20;
方式二:在 SELECT 中賦值
SELECT @a := 10;
=和:=在賦值場景下都能用,但在復(fù)雜 SQL 中,推薦使用:=,可讀性更好,也更安全。
2. 使用變量
變量賦值后,可以直接使用:
SELECT @a + @b;
也可以在查詢中混合使用:
SELECT
id,
price,
@total := @total + price AS running_total
FROM orders,
(SELECT @total := 0) t;
三、自定義變量的典型使用場景
1. 計(jì)算累計(jì)值(運(yùn)行總和)
這是最經(jīng)典的用法之一:
SELECT
id,
amount,
@sum := @sum + amount AS total_amount
FROM payments,
(SELECT @sum := 0) s;
用于報(bào)表、統(tǒng)計(jì)、導(dǎo)出數(shù)據(jù)時(shí)非常方便。
2. 模擬行號(MySQL 8 之前)
在 MySQL 8.0 之前,沒有 ROW_NUMBER(),很多人用自定義變量模擬:
SELECT
@rownum := @rownum + 1 AS row_num,
name
FROM users,
(SELECT @rownum := 0) r;
3. 復(fù)雜條件的中間狀態(tài)保存
例如在一條 SQL 中保存上一次的值:
SELECT id, score, @prev := score AS prev_score FROM scores ORDER BY id;
四、自定義變量最容易踩的坑
這是重點(diǎn)。
1. 執(zhí)行順序不保證
MySQL 不保證 SELECT 中表達(dá)式的計(jì)算順序。
例如:
SELECT @a := @a + 1, @a FROM table;
你不能假設(shè)左邊一定先執(zhí)行。
官方文檔明確說明:
不要依賴用戶變量在同一 SELECT 中的計(jì)算順序
2. 在 WHERE / ORDER BY 中使用不安全
SELECT * FROM users WHERE score > (@avg := @avg + 1);
這種寫法極不可靠,不同執(zhí)行計(jì)劃可能結(jié)果不同。
3. 并發(fā)場景下容易被誤解
自定義變量是 會(huì)話級別 的,不是全局的。
- 不同連接之間 互不影響
- 但同一個(gè)連接里,多條 SQL 會(huì)共用
很多新手會(huì)誤以為它是“全局變量”,這是錯(cuò)的。
4. 可讀性和可維護(hù)性差
復(fù)雜 SQL 中大量使用 @變量:
- 后期幾乎無法維護(hù)
- 新人很難理解
- 調(diào)試成本極高
五、什么時(shí)候不該用自定義變量
以下場景,強(qiáng)烈不推薦:
- 業(yè)務(wù)核心邏輯
- 更新、刪除等寫操作依賴變量順序
- 高并發(fā)、強(qiáng)一致性要求
- 可以用窗口函數(shù)、子查詢、CTE 解決的場景(MySQL 8+)
六、替代方案建議
如果你使用的是 MySQL 8.0+,優(yōu)先考慮:
ROW_NUMBER()SUM() OVER (...)LAG / LEAD- CTE(WITH 語句)
這些都是語義清晰、結(jié)果可控的正規(guī)方案。
七、總結(jié)一句話
MySQL 自定義變量是“應(yīng)急工具”,不是“長期方案”。
- 寫報(bào)表、一次性 SQL:可以用
- 寫核心業(yè)務(wù)、長期維護(hù)代碼:盡量別用
如果你發(fā)現(xiàn)一條 SQL 里出現(xiàn)了 5 個(gè)以上的 @變量,
那大概率說明:設(shè)計(jì)該重構(gòu)了。
到此這篇關(guān)于MySQL 中的自定義變量詳解(用法、場景與坑)的文章就介紹到這了,更多相關(guān)mysql自定義變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中CONCAT()函數(shù)出現(xiàn)值為空的問題及解決辦法
項(xiàng)目中查詢用到了concat()拼接函數(shù),本文主要介紹了MySQL中CONCAT()函數(shù)出現(xiàn)值為空的問題及解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
MYSQL 創(chuàng)建函數(shù)出錯(cuò)的解決方案
在程序開發(fā)過程中,大家有沒有遇到過mysql函數(shù)不能創(chuàng)建,我是遇到過,是一個(gè)很麻煩的問題,上網(wǎng)搜了些相關(guān)資料,整理在一起了,供大家參考,幫助那些需要幫助的朋友2015-08-08
sql語句escape查詢數(shù)據(jù)中含通配字符[ %用法詳解
這篇文章主要為大家介紹了sql語句escape查詢數(shù)據(jù)中含通配字符[ %用法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
用VirtualBox構(gòu)建MySQL測試環(huán)境的筆記
這篇文章主要介紹了如何用VirtualBox構(gòu)建MySQL測試環(huán)境,特分享下,方便需要的朋友2013-08-08
mysql通過find_in_set()函數(shù)實(shí)現(xiàn)where in()順序排序
這篇文章主要介紹了mysql通過find_in_set()函數(shù)實(shí)現(xiàn)where in()順序排序的相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
Centos7使用yum安裝MySQL及實(shí)現(xiàn)遠(yuǎn)程連接的方法
因?yàn)镸ySQL被Oracle收購,目前推薦使用mariadb數(shù)據(jù)庫。下面通過本文給大家分享Centos7使用yum安裝MySQL及實(shí)現(xiàn)遠(yuǎn)程連接的方法,感興趣的朋友一起看看吧2017-07-07

