1. 程式人生 > >MariaDB/MySQL中的變量

MariaDB/MySQL中的變量

... 還在 sof 通過 動態 系列 但是 版本號 innodb

在MySQL/MariaDB中有好幾種變量類型:用戶自定義變量、系統變量、一般的臨時變量(即本地變量,或稱為局部變量)。

1.用戶變量

用戶變量是基於會話的,也是基於用戶的,所以我覺得稱之為會話變量更合適,但會話變量一般用來表示系統會話變量(後面會說明),所以還是稱之為用戶變量好了。

只有本用戶才能引用自身的用戶變量,其他用戶無法引用,且當用戶退出會話時,用戶變量自動銷毀。

用戶變量使用"@"開頭,用戶變量可以直接賦值,無需事先聲明。在引用未賦值的用戶變量時,該變量值為null

有以下三種方式設置用戶變量:

  1. set語句,此時可以使用"="或者":="操作符;
  2. select語句,此時只能使用":="格式賦值,因為除了set語句中,"="都會被視為比較操作符。;
  3. select ... into var_name from TABLE語句,此時要求select語句只能返回標量值,即單行數據。因此為了保險,select into var_name的時候,應盡量結合limit語句限制輸出。
set @a1=1,@a2=3,@a3:=2;
select @a4:=@a1+@a3;
select 33,‘abc‘ into @a5,@a6 from dual;

查看變量值可以使用select語句。

MariaDB [test]> select @a1,@a2,@a3,@a4,@a5,@a6,@a7;
+------+------+------+------+------+------+------+
| @a1
| @a2 | @a3 | @a4 | @a5 | @a6 | @a7 | +------+------+------+------+------+------+------+ | 1 | 2 | 3 | 4 | 5 | abc | NULL | +------+------+------+------+------+------+------+

在mariadb 10.2.6中,引入了一張系統架構表information_schema.USER_VARIABLES,該表中記錄了當前用戶當前會話定義的用戶變量信息。該信息架構表在mysql中沒有。

MariaDB [test]> SELECT * FROM information_schema.USER_VARIABLES;           
+---------------+----------------+---------------+--------------------+
| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_TYPE | CHARACTER_SET_NAME |
+---------------+----------------+---------------+--------------------+
| a6            | abc            | VARCHAR       | utf8               |
| i             | 2              | INT           | utf8               |
| a5            | 33             | INT           | utf8               |
| a1            | 1              | INT           | utf8               |
| a4            | 3              | INT           | utf8               |
| a2            | 3              | INT           | utf8               |
| a3            | 2              | INT           | utf8               |
+---------------+----------------+---------------+--------------------+

2.系統變量

在MySQL/mariadb中維護兩種系統變量:全局系統變量和會話系統變量。系統變量是用來設置MySQL服務運行屬性和狀態的。

全局系統變量使用global或者"@@global."關鍵字來設置。會話系統變量使用session或者"@@session."關鍵字來設置,其中session可以替換為Local,它們是同義詞。如果省略這些關鍵字,則默認為session系統變量。設置global系統變量要求具有super權限。

-- 設置全局系統變量
set global sort_buffer_size=32M;
set @@global.sort_buffer_size=32M;
-- 設置會話系統變量
set session sort_buffer_size=32M;
set @@session.sort_buffer_size=32M;
set sort_buffer_size=32M;
-- 查看全局系統變量值
select @@global.sort_buffer_size;
show global variables like "sort_buffer%";
-- 查看會話系統變量,不能使用select sort_buffer_size
select @@session.sort_buffer_size;
select @@sort_buffer_size;
show [session] variables like "sort_buffer%";
-- 一次性設置多個變量,包括會話變量、全局變量以及用戶變量
SET @x = 1, SESSION sql_mode = ‘‘;
SET GLOBAL sort_buffer_size = 1000000, SESSION sort_buffer_size = 1000000;
SET @@global.sort_buffer_size = 1000000, @@local.sort_buffer_size = 1000000;
SET GLOBAL max_connections = 1000, sort_buffer_size = 1000000;

全局系統變量對全局有效,當有新的會話打開時,新會話會繼承全局系統變量的值,所以設置全局系統變量之後新打開的會話都會繼承設置後的值。設置全局系統變量對已經打開的連接無效,但是其他已經打開的連接可以查看到設置後的全局系統變量值。

系統變量按照是否允許在運行時修改,還分為動態變量和靜態變量。能在運行過程中修改的變量稱為動態變量,只能在數據庫實例關閉狀態下修改的變量稱為靜態變量或只讀變量。動態變量使用set修改。如果在數據庫實例運行狀態下修改靜態變量,則會給出錯誤。如:

set @@innodb_undo_tablespaces=3;
ERROR 1238 (HY000): Variable ‘innodb_undo_tablespaces‘ is a read only variable

系統變量除了可以在運行中的環境下設置,還可以在配置文件中或者mysqld/mysqld_safe這樣的命令行中設置,甚至mysql客戶端命令行也可以傳遞。在配置文件中設置系統變量時,下劃線或者短橫線都允許,它們表示同一個意思。例如下面的兩行配置是等價的:

innodb_file_per_table=1
innodb-file-per-table=1

3.局部變量

局部變量也稱為本地變量,只能在begin...and語句塊中生效。它不像用戶變量,本地變量必須使用declare事先聲明,所以declare也必須在begin...end中使用

局部變量無論是聲明還是調用的時候都不需要任何多余的符號(即不需要@符號),直接使用其名稱var_name即可。

使用declare聲明變量,可以一次性聲明多個同類型的變量,需要時可有直接為其指定默認值,不指定時默認為null。

decalre var_name,... type [default value];

使用set為變量賦值。MySQL/mariadb中set支持一次性賦值多個變量。

在begin...end中的set是一般set語句的擴展版本,它既可以設置系統變量、用戶變量,也可以設置此處的本地變量。

set var_name=expr,[var_name=expr1,...]

或者使用select...into語句從表中獲取值來賦值給變量,但是這樣的賦值行為要求表的返回結果必須是單列且單行的標量結果。例如下面的語句將col的列值賦值給var_name變量。

select col into var_name from table_name;

因為局部變量只能在begin...end中使用,所以此處使用存儲過程的例子來演示。

DROP PROCEDURE IF EXISTS haha;
DELIMITER $$
CREATE PROCEDURE haha()
BEGIN
    DECLARE a INT;
    SET a=1;
    SET @i:=2;
    SELECT a,@i;
END$$
DELIMITER ;

CALL haha();
     a        @i
------  --------
     1         2

在MySQL中,begin...end只能定義在存儲程序中,所以declare也只能定義在存儲程序內。但在mariadb中,begin...end是允許定義在存儲程序(存儲函數,存儲過程,觸發器,事件)之外的,所以decalre也算是能夠定義在存儲程序之外吧。需要定義在存儲程序之外時,使用 begin not atomic 關鍵字即可。例如:

delimiter $$ 
begin not atomic
    declare a int;
    set a=3;
    select a;
end$$

3.1 declare錨定其他對象的數據類型

在mariadb 10.3中(註意版本號,目前10.3版本還在測試中),declare語句允許在存儲程序中使用TYPE OFROW TYPE OF 關鍵字基於表或遊標來錨定數據類型。在mysql中不支持數據類型的錨定功能。

例如:

DECLARE tmp TYPE OF t1.a; -- 基於表t1中的a列獲取數據類型
DECLARE rec1 ROW TYPE OF t1; -- 錨定表t1中行數據類型
DECLARE rec2 ROW TYPE OF cur1; -- 基於遊標cur1獲取行數據類型

通過其他對象來錨定本地變量的數據類型時,如果對象的數據類型改變,則本地數據類型也隨之改變。這在某些時候非常有利於維護存儲程序。

在定義存儲程序時,不會檢查declare錨定的對象是否存在。但在調用存儲程序時,會先檢查錨定對象是否存在。

當declare語句的錨定是基於表對象(不是遊標)時,在調用存儲程序的瞬間就會檢查錨定的表是否存在,然後立刻聲明該變量。因此:

  • (1).帶有錨定功能的decalre語句可以定義在存儲程序的任意位置;
  • (2).在存儲程序中刪除錨定的表對象,或者修改了錨定的表結構,都不會改變存儲程序調用時聲明的變量類型;
  • (3).所有帶錨定功能的declare都是在存儲程序調用之初被賦值的。

當declare語句的錨定是基於遊標對象時,變量的數據類型是在執行變量聲明語句時才獲取到的。數據類型僅只錨定一次,之後不再改變。如果遊標中的ROW TYPE OF變量是定義在一個循環之中,則數據類型在循環的開頭就已經獲取,且之後的循環不再改變。

示例:

create table t1(a int,b char(20));
drop procedure if exists haha;
delimiter $$
create procedure haha()
begin
    declare x type of t1.a;
    set x=1;
    select x;
end$$
delimiter ;

call haha();

回到Linux系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
回到網站架構系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
回到數據庫系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7586194.html
轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/8695767.html

註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!

MariaDB/MySQL中的變量