一、MySQL的變量分類
MySQL變量一共分為兩大類:用戶自定義變量和系統變量。如下:
- 用戶自定義變量
- 局部變量
- 會話變量
- 系統變量
- 會話變量
- 全局變量
局部變量
局部變量一般用於SQL的語句塊中,比如存儲過程中的begin和end語句塊。其作用域僅限於該語句塊內。生命周期也僅限於該存儲過程的調用期間。
DROP PROCEDURE IF EXISTS add; CREATE PROCEDURE add ( IN a int, IN b int ) BEGIN DECLARE c int DEFAULT 0; SET c = a + b; SELECT c AS c; END;
備注:
declare 定義的變量相當於局部變量,只在存儲過程中的begin和end之間生效。
set 定義的變量可以是全局變量或者會話變量,在整個會話或者全局都起作用(比如某個應用的一個連接過程中),即這個變量可以在被調用的存儲過程或者代碼之間共享數據。
會話變量
會話變量即為服務器為每個客戶端連接維護的變量。在客戶端連接時,使用相應全局變量的當前值對客戶端的回話變量進行初始化。
設置會話變量不需要特殊權限,但客戶端只能更改自己的會話變量。其作用域與生命周期均限於當前客戶端連接。
根據手冊,set命令設置變量時若不指定GLOBAL、SESSION或者LOCAL,默認使用SESSION
會話變量的賦值
set session var_name = value; set @@session.var_name = value; set var_name = value;
-- 其實我們都是@XXX作為變量名 set @var_name = value;
會話變量的查詢
select @@var_name; select @@session.var_name; show session variables like "%var%";
全局變量
全局變量影響服務器整體操作。當服務器啟動時,它將所有全局變量初始化為默認值。這些默認值可以在選項文件中或在命令行中指定的選項進行更改。要想更改全局變量,必須具有SUPER權限。
全局變量作用於server的整個生命周期,但是不能跨重啟。即重啟后所有設置的全局變量均失效。要想讓全局變量重啟后繼續生效,需要更改相應的配置文件。
全局變量的賦值
set global var_name = value; //注意:此處的global不能省略。根據手冊,set命令設置變量時若不指定GLOBAL、SESSION或者LOCAL,默認使用SESSION set @@global.var_name = value; //同上
全局變量的賦值
select @@global.var_name; show global variables like "%var%";
二、MySQL用戶自定義變量詳解
你可以利用SQL語句將值存儲在用戶自定義變量中,然后再利用另一條SQL語句來查詢用戶自定義變量。這樣以來,可以再不同的SQL間傳遞值。
用戶自定義變量的聲明方法形如:@var_name,其中變量名稱由字母、數字、“.”、“_”和“$”組成。當然,在以字符串或者標識符引用時也可以包含其他字符(例如:@’my-var’,@”my-var”,或者@`my-var`)。
用戶自定義變量是會話級別的變量。其變量的作用域僅限於聲明其的客戶端鏈接。當這個客戶端斷開時,其所有的會話變量將會被釋放。
用戶自定義變量是不區分大小寫的。
使用SET語句來聲明用戶自定義變量:
SET @var_name = expr[, @var_name = expr] … SET @var_name := expr[, @var_name = expr] …
在使用SET設置變量時,可以使用“=”或者“:=”操作符進行賦值。
當然,除了SET語句還有其他賦值的方式。比如下面這個例子,但是賦值操作符只能使用“:=”。因為“=”操作符將會被認為是比較操作符。
mysql> SET @t1=1, @t2=2, @t3:=4; mysql> SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3; +------+------+------+--------------------+ | @t1 | @t2 | @t3 | @t4 := @t1+@t2+@t3 | +------+------+------+--------------------+ | 1 | 2 | 4 | 7 | +------+------+------+--------------------+
用戶變量的類型僅限於:整形、浮點型、二進制與非二進制串和NULL。在賦值浮點數時,系統不會保留精度。其他類型的值將會被轉成相應的上述類型。比如:一個包含時間或者空間數據類型(temporal or spatial data type)的值將會轉換成一個二進制串。
如果用戶自定義變量的值以結果集形式返回,系統會將其轉換成字符串形式。
如果查詢一個沒有初始化的變量,將會以字符串類型返回NULL。
不要在同一個非SET語句中同時賦值並使用同一個用戶自定義變量
用戶自定義變量可以用於很多上下文中。但是目前並不包括那些顯式使用常量的表達式中,比如SELECT中的LIMIT子句,或者LOAD DATA中的IGNORE N LINES的字句中。
通常來說,除了在SET語句中,不要再同一個SQL語句中同時賦值並使用同一個用戶自定義變量。舉個變量自增的例子,下面的是沒問題的:
SET @a = @a + 1;
對於其他語句,比如SELECT,也許會得到期望的效果,但這真心不靠譜。比如下面的語句,也許你自然地會認為MySQL會先執行@a的值,然后再進行賦值操作:
SELECT @a, @a:=@a+1, …;
然而,用戶自定義變量表達式的計算順序還沒有定義呢。
除此之外,還有另一個問題。變量的默認返回類型由語句開始時的類型決定的,正如下面的例子:
mysql> SET @a=’test’; mysql> SELECT @a,(@a:=20) FROM tbl_name;
上述的SELECT語句中,MySQL會報告給客戶端第一列的字段類型為字符串,同時將所有對@a變量的使用均轉換為字符串處理,盡管在SELECT語句中將@a變量設置為數字類型。在SELECT語句執行后,@a變量才會在下一個語句中識別為數字類型。
為了避免上述問題的發生,要么不在同一個語句中同時賦值並使用變量,要么在使用之前,將變量設置為0,0.0,或者”,以確定它的數據類型。