### 第9章:語言結構
** 目錄**
[ 9.1. 文字值](#)[ 9.1.1. 字符串](#)[ 9.1.2. 數值](#)[ 9.1.3. 十六進制值](#)[ 9.1.4. 布爾值](#)[ 9.1.5. 位字段值](#)[9.1.6. NULL值](#)[ 9.2. 數據庫、表、索引、列和別名](#)[ 9.2.1. 識別符限制條件](#)[ 9.2.2. 識別符大小寫敏感性](#)[ 9.3. 用戶變量](#)[ 9.4. 系統變量](#)[ 9.4.1. 結構式系統變量](#)[ 9.5. 注釋語法](#)[ 9.6. MySQL中保留字的處理](#)
本章討論了使用MySQL編寫SQL語句的下面元素時所使用的規則:
·???????? 字符串和數字等文字值
·???????? 識別符,例如表和列名
·???????? 用戶和系統變量
·???????? 注釋
·???????? 保留字
### 9.1.?文字值
[ 9.1.1. 字符串](#)[ 9.1.2. 數值](#)[ 9.1.3. 十六進制值](#)[ 9.1.4. 布爾值](#)[ 9.1.5. 位字段值](#)[9.1.6. NULL值](#)
該節描述了如何在MySQL中寫文字值。包括字符串、數值、十六進制值、布爾值和NULL。本節還包括在MySQL中處理這些基本類型時會遇到的各種細微差別和“影印版”。
### 9.1.1.?字符串
字符串指用單引號(‘'’)或雙引號(‘"’)引起來的字符序列。例如:
~~~
'a string'
~~~
~~~
"another string"
~~~
如果SQL服務器模式啟用了NSI_QUOTES,可以只用單引號引用字符串。用雙引號引用的字符串被解釋為一個識別符。
字符串可以有一個可選字符集引介詞和COLLATE子句:
~~~
[_charset_name]'string' [COLLATE collation_name]
~~~
例如:
~~~
SELECT _latin1'string';
~~~
~~~
SELECT _latin1'string' COLLATE latin1_danish_ci;
~~~
關于這些字符串語法形式的詳細信息,參見[10.3.7節,“字符串文字字符集和校對”](# "10.3.7.?Character String Literal Character Set and Collation")。
在字符串中,某些序列具有特殊含義。這些序列均用反斜線(‘\’)開始,即所謂的*轉義字符*。MySQL識別下面的轉義序列:
<table border="1" cellpadding="0" id="table1"><tr><td> <p> <span>\0</span><span> </span></p></td> <td> <p><span>ASCII 0(</span><span>NUL</span><span>)</span>字符。</p></td> </tr><tr><td> <p> <span>\'</span><span> </span></p></td> <td> <p>單引號<span>(</span>‘<span>'</span>’<span>)</span>。</p></td> </tr><tr><td> <p> <span>\"</span><span> </span></p></td> <td> <p>雙引號<span>(</span>‘<span>"</span>’<span>)</span>。</p></td> </tr><tr><td> <p> <span>\b</span><span> </span></p></td> <td> <p>退格符。</p></td> </tr><tr><td> <p> <span>\n</span><span> </span></p></td> <td> <p>換行符。</p></td> </tr><tr><td> <p> <span>\r</span><span> </span></p></td> <td> <p>回車符。</p></td> </tr><tr><td> <p> <span>\t</span><span> </span></p></td> <td> <p><span>tab</span>字符。</p></td> </tr><tr><td> <p> <span>\Z</span><span> </span></p></td> <td> <p><span>ASCII 26(</span>控制(<span>Ctrl</span>)<span>-Z)</span>。該字符可以編碼為‘<span>\Z</span>’,以允許你解決在<span>Windows</span>中<span>ASCII 26</span>代表文件結尾這一問題。<span>(</span>如果你試圖使用<span>mysql <i>db_name</i> < <i>file_name</i></span>,<span>ASCII 26</span>會帶來問題)<span>。</span></p></td> </tr><tr><td> <p> <span>\\</span><span> </span></p></td> <td> <p>反斜線<span>(</span>‘<span>\</span>’<span>)</span>字符。</p></td> </tr><tr><td> <p> <span>\%</span><span> </span></p></td> <td> <p>‘<span>%</span>’字符。參見表后面的注解。</p></td> </tr><tr><td> <p> <span>\_</span><span> </span></p></td> <td> <p>‘<span>_</span>’字符。參見表后面的注解。</p></td> </tr></table>
這些序列對大小寫敏感。例如,‘\b’解釋為退格,但‘\B’解釋為‘B’。
‘\%’和‘\_’序列用于搜索可能會解釋為通配符的模式匹配環境中的‘%’和‘_’文字實例。參見[12.3.1節,“字符串比較函數”](# "12.3.1.?String Comparison Functions")。請注意如果你在其它環境中使用‘\%’或‘\_’,它們返回字符串‘\%’和‘\_’,而不是‘%’和‘_’。
在其它轉義序列中,反斜線被忽略。也就是說,轉義字符解釋為仿佛沒有轉義。
有幾種方式可以在字符串中包括引號:
·???????? 在字符串內用‘'’引用的‘'’可以寫成‘''’。
·???????? 在字符串內用‘"’引用的‘"’可以寫成‘""’。
·???????? 可以在引號前加轉義字符(‘\’)。
·???????? 在字符串內用‘"’引用的‘'’不需要特殊處理,不需要用雙字符或轉義。同樣,在字符串內用‘'’引用的‘"’也不需要特殊處理。
下面的SELECT語句顯示了引用和轉義如何工作:
~~~
mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
~~~
~~~
+-------+---------+-----------+--------+--------+
~~~
~~~
| hello | "hello" | ""hello"" | hel'lo | 'hello |
~~~
~~~
+-------+---------+-----------+--------+--------+
~~~
~~~
?
~~~
~~~
mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
~~~
~~~
+-------+---------+-----------+--------+--------+
~~~
~~~
| hello | 'hello' | ''hello'' | hel"lo | "hello |
~~~
~~~
+-------+---------+-----------+--------+--------+
~~~
~~~
?
~~~
~~~
mysql> SELECT 'This\nIs\nFour\nLines';
~~~
~~~
+--------------------+
~~~
~~~
| This
~~~
~~~
Is
~~~
~~~
Four
~~~
~~~
Lines |
~~~
~~~
+--------------------+
~~~
~~~
?
~~~
~~~
mysql> SELECT 'disappearing\ backslash';
~~~
~~~
+------------------------+
~~~
~~~
| disappearing backslash |
~~~
~~~
+------------------------+
~~~
如果你想要在字符串列內插入二進制數據(例如BLOB),必須通過轉義序列表示下面的字符:
<table border="1" cellpadding="0" id="table2"><tr><td> <p> <span>NUL</span></p></td> <td> <p> <span>NUL</span>字節<span>(ASCII 0)</span>。用‘<span><span>\0</span><span>’</span></span>表示該字符<span>(</span>反斜線后面跟一個<span>ASCII</span>‘<span>0</span>’字符<span>)</span>。</p></td> </tr><tr><td> <p> <span>\</span></p></td> <td> <p>反斜線<span>(ASCII 92)</span>。用‘<span>\\</span>’表示該字符。</p></td> </tr><tr><td> <p> <span>'</span></p></td> <td> <p>單引號<span>(ASCII 39)</span>。用‘<span>\'</span>’表示該字符。</p></td> </tr><tr><td> <p> <span>"</span></p></td> <td> <p>雙引號<span>(ASCII 34)</span>。用‘<span>\"</span>’表示該字符。</p></td> </tr></table>
當編寫應用程序時,在包含這些特殊字符的字符串用于發送到MySQL服務器的SQL語句中的數據值之前,必須對它們正確進行轉義。可以用兩種方法來完成:
·???????? 用轉義特殊字符的函數處理字符串。例如,在C程序中,可以使用mysql_real_escape_string() C API函數來轉義字符。參見[25.2.3.52節,“mysql_real_escape_string()”](# "25.2.3.52.?mysql_real_escape_string()")。Perl DBI接口提供一個quote方法來將特殊字符轉換為正確的轉義序列。參見[25.4節,“MySQL Perl API”](# "25.4.?MySQL Perl API")。
·???????? 顯式轉義特殊字符,許多MySQL API提供了占位符功能,允許你在查詢字符串中插入特殊標記,然后當你發出查詢時將數據值同它們綁定起來。在這種情況下,API關注轉義值中的特殊字符。
### 9.1.2.?數值
整數用一系列阿拉伯數字表示。浮點數使用‘.’作為十進制間隔符。兩種類型的數值均可以在前面加一個‘-’來表示負值。
合法整數的例子:
~~~
1221
~~~
~~~
0
~~~
~~~
-32
~~~
合法浮點數的例子:
~~~
294.42
~~~
~~~
-32032.6809e+10
~~~
~~~
148.00
~~~
整數可以用在浮點環境中;它被解釋為與浮點數等效。
### 9.1.3.?十六進制值
MySQL支持十六進制值。在數字上下文中,十六進制數如同整數(64位精度)。在字符串上下文,如同二進制字符串,每對十六進制數字被轉換為一個字符:
~~~
mysql> SELECT x'4D7953514C';
~~~
~~~
??????? -> 'MySQL'
~~~
~~~
mysql> SELECT 0xa+0;
~~~
~~~
??????? -> 10
~~~
~~~
mysql> SELECT 0x5061756c;
~~~
~~~
??????? -> 'Paul'
~~~
十六進制值的默認類型是字符串。如果想要確保該值作為數字處理,可以使用CAST(...AS UNSIGNED):
~~~
mysql> SELECT 0x41,CAST(0x41 AS UNSIGNED);
~~~
~~~
??????? -> 'A',65
~~~
0x語法基于ODBC。十六進制字符串通常用于ODBC以便為BLOB列提供值。x’hexstring’語法基于標準SQL。
可以用HEX()函數將一個字符串或數字轉換為十六進制格式的字符串:
~~~
mysql> SELECT HEX('cat');
~~~
~~~
??????? -> '636174'
~~~
~~~
mysql> SELECT 0x636174;
~~~
~~~
??????? -> 'cat'
~~~
### 9.1.4.?布爾值
常量TRUE等于1,常量FALSE等于0。常量名可以寫成大寫或小寫。
~~~
mysql> SELECT TRUE,true,FALSE,false;
~~~
~~~
??????? -> 1,1,0,0
~~~
### 9.1.5.?位字段值
可以使用b'*value*'符號寫位字段值。*value*是一個用0和1寫成的二進制值。
位字段符號可以方便指定分配給BIT列的值:
~~~
mysql> CREATE TABLE t (b BIT(8));
~~~
~~~
mysql> INSERT INTO t SET b = b'11111111';
~~~
~~~
mysql> INSERT INTO t SET b = b'1010';
~~~
~~~
+------+----------+----------+----------+
~~~
~~~
| b+0? | BIN(b+0) | OCT(b+0) | HEX(b+0) |
~~~
~~~
+------+----------+----------+----------+
~~~
~~~
|? 255 | 11111111 | 377????? | FF?????? |
~~~
~~~
|?? 10 | 1010???? | 12?????? | A??????? |
~~~
~~~
+------+----------+----------+----------+
~~~
### 9.1.6.?NULL值
NULL值表示“沒有數據”。NULL可以寫成大寫或小寫。
請注意NULL值不同于數字類型的0或字符串類型的空字符串。參見[A.5.3節,“與NULL值有關的問題``”](# "A.5.3.?Problems with NULL Values")。
對于用LOAD DATA INFILE或SELECT ...INTO OUTFILE執行的文本文件導入或導出操作,NULL用序列\N表示。參見[13.2.5節,“LOAD DATA INFILE語法”](# "13.2.5.?LOAD DATA INFILE Syntax")。
### 9.2.?數據庫、表、索引、列和別名
[ 9.2.1. 識別符限制條件](#)[ 9.2.2. 識別符大小寫敏感性](#)
數據庫、表、索引、列和別名是識別符。該節描述了在MySQL中識別符的允許的語法。
下面的表描述了每類識別符的最大長度和允許的字符。
<table border="1" cellpadding="0" id="table3"><tr><td> <p><strong><span>識別符</span></strong></p></td> <td> <p><strong><span>最大長度<span>(</span>字節<span>)</span></span></strong></p></td> <td> <p><strong><span>允許的字符</span></strong></p></td> </tr><tr><td> <p>數據庫</p></td> <td> <p><span>64</span></p></td> <td> <p>目錄名允許的任何字符,不包括‘<span style="font-size: 10.0pt; ">/</span>’、‘<span>\</span>’或者‘<span>。</span>’</p></td> </tr><tr><td> <p>表</p></td> <td> <p><span>64</span></p></td> <td> <p>文件名允許的任何字符,不包括‘<span style="font-size: 10.0pt; ">/</span>’、‘<span>\</span>’或者‘<span>。</span>’</p></td> </tr><tr><td> <p>列</p></td> <td> <p><span>64</span></p></td> <td> <p>所有字符</p></td> </tr><tr><td> <p>索引</p></td> <td> <p><span>64</span></p></td> <td> <p>所有字符</p></td> </tr><tr><td> <p>別名</p></td> <td> <p><span>255</span></p></td> <td> <p>所有字符</p></td> </tr></table>
除了表內注明的限制,識別符不可以包含ASCII 0或值為255的字節。數據庫、表和列名不應以空格結尾。在識別符中可以使用引號識別符,盡管應盡可能避免這樣使用。
識別符用Unicode(UTF8)保存。在.frm文件中保存的表定義的識別符和在mysql數據庫中的授權表保存的識別符也用Unicode(UTF8)保存。在MySQL 5.1中授權表(和其它表)的字符串列的大小等于字符個數;這說明(不象以前版本的MySQL)你可以在這些列保存的值中使用多字節字符而不需要降低字符個數。
識別符可以引起來也可以不引起來。如果識別符是一個保留字或包含特殊字符,無論何時使用,*必須*將它引起來。關于保留字的列表參見[9.6節,“MySQL中保留字的處理”](# "9.6.?Treatment of Reserved Words in MySQL")。特殊字符指那些當前字符集、‘_’和‘$’之外的文字數字字符集。
識別符的引用符是反勾號(‘`’):
~~~
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
~~~
如果SQL服務器模式包括ANSI_QUOTES模式選項,還可以用雙引號將識別符引起來:
~~~
mysql> CREATE TABLE "test" (col INT);
~~~
~~~
ERROR 1064: You have an error in your SQL syntax. (...)
~~~
~~~
mysql> SET sql_mode='ANSI_QUOTES';
~~~
~~~
mysql> CREATE TABLE "test" (col INT);
~~~
~~~
Query OK, 0 rows affected (0.00 sec)
~~~
參見[5.3.2節,“SQL服務器模式”](# "5.3.2.?The Server SQL Mode")。
*如果*你引用識別符**,可以在識別符內包括識別符引用符。如果識別符內包括的字符與引用識別符的字符相同,則需要用雙字符。下面的語句創建一個名為a`b包含列c"d的表:
~~~
mysql> CREATE TABLE `a``b` (`c"d` INT);
~~~
建議不要使用*X*e*X*模式的名,例如1e或2e2,因為類似1e+1的表達式比較模糊。根據上下文,它可以解釋為表達式1e + 1或數字1e+1。
使用MD5產生表名時應仔細,因為它可能產生不合法的表名,如上所述。
### 9.2.1.?識別符限制條件
MySQL允許使用由單個識別符或多個識別符組成的名字。多部分名各組件之間應以句點(‘.’)間隔開。多部分名的開頭部分作為限定詞,后面的識別符被解釋。
在MySQL中可以引用下面形式的列:
<table border="1" cellpadding="0" id="table4"><tr><td> <p><strong><span> 列參考</span></strong></p></td> <td> <p><strong><span>含義</span></strong></p></td> </tr><tr><td> <p><span><i> <span>col_name</span></i></span></p></td> <td> <p>列<span><i><span>col_name</span></i></span>,查詢中使用的表包含有此名字的列。</p></td> </tr><tr><td> <p><span><i> <span> tbl_name.col_name</span></i></span></p></td> <td> <p>默認數據庫中的表<span><i><span>tbl_name</span></i></span>的列<span><i><span>col_name</span></i></span>。</p></td> </tr><tr><td> <p><span><i> <span> db_name.tbl_name.col_name</span></i></span></p></td> <td> <p>數據庫<span><i><span>db_name</span></i></span>中的表<span><i><span>tbl_name</span></i></span>的列<span><i><span>col_name</span></i></span>。</p></td> </tr></table>
?
如果多部分名的組件需要引用,應分別將它們引起來而不要將整個名引起來。例如,`my-tables`.`my-column`有效,而`my-tables.my-column`無效。
不需要在語句中為列指定*tbl_name*或*db_name.tbl_name*前綴,除非列會很模糊。假定表t1和t2各包含一個列c,你使用SELECT語句在t1和t2中搜索c。在這種情況下,c很模糊,因為它在語句中使用的表內不唯一。你必須用表名t1.c或t2.c限定它,表示指哪個表。同樣,要想用同一語句搜索數據庫db1中的表t和數據庫db2中的表t,你必須將那些表中的列指為db1.t.col_name和db2.t.col_name。
限定名中句點后面的字必須為一個識別符,因此不需要將它引起來,即使是一個保留字。
語法*.tbl_name*表示當前數據庫中的*tbl_name*。該語法與ODBC兼容,因為某些ODBC程序在表名前面加前綴‘.’字符。
### 9.2.2.?識別符大小寫敏感性
在MySQL中,數據庫對應數據目錄中的目錄。數據庫中的每個表至少對應數據庫目錄中的一個文件(也可能是多個,取決于存儲引擎)。因此,所使用操作系統的大小寫敏感性決定了數據庫名和表名的大小寫敏感性。這說明在大多數Unix中數據庫名和表名對大小寫敏感,而在Windows中對大小寫不敏感。一個顯著的例外情況是Mac OS X,它基于Unix但使用默認文件系統類型(HFS+),對大小寫不敏感。然而,Mac OS X也支持UFS卷,該卷對大小寫敏感,就像Unix一樣。參見[1.8.4節,“MySQL對標準SQL的擴展”](# "1.8.4.?MySQL Extensions to Standard SQL")。
**注釋:**盡管在某些平臺中數據庫名和表名對大小寫不敏感,不應在同一查詢中使用不同的大小寫來引用給定的數據庫或表。下面的查詢不會工作,因為它同時引用了表my_tables和as MY_tables:
~~~
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
~~~
列、索引、存儲子程序和觸發器名在任何平臺上對大小寫不敏感,列的別名也不敏感。
默認情況,表別名在Unix中對大小寫敏感,但在Windows或Mac OS X中對大小寫不敏感。下面的查詢在Unix中不會工作,因為它同時引用了別名a和A:
~~~
mysql> SELECT col_name FROM tbl_name AS a
~~~
~~~
??? -> WHERE a.col_name = 1 OR A.col_name = 2;
~~~
然而,該查詢在Windows中是可以的。要想避免出現差別,最好采用一致的轉換,例如總是用小寫創建并引用數據庫名和表名。在大多數移植和使用中建議使用該轉換。
在MySQL中如何在硬盤上保存和使用表名和數據庫名由lower_case_tables_name系統變量確定,可以在啟動**mysqld**時設置。lower_case_tables_name可以采用下面的任一值:
<table border="1" cellpadding="0" id="table5"><tr><td> <p><strong><span>值</span></strong></p></td> <td> <p><strong><span>含義</span></strong></p></td> </tr><tr><td> <p> <span>0</span></p></td> <td> <p>使用<span>CREATE TABLE</span>或<span>CREATE DATABASE</span>語句指定的大寫和小寫在硬盤上保存表名和數據庫名。名稱比較對大小寫敏感。在<span>Unix</span>系統中的默認設置即如此。請注意如果在大小寫不敏感的文件系統上用<span>--lower-case-table-names=0</span>強制設為<span>0</span>,并且使用不同的大小寫訪問<span>MyISAM</span>表名,會導致索引破壞。</p></td> </tr><tr><td> <p> <span>1</span></p></td> <td> <p>表名在硬盤上以小寫保存,名稱比較對大小寫敏感。<span>MySQL</span>將所有表名轉換為小寫以便存儲和查找。該行為也適合數據庫名和表的別名。該值為<span>Windows</span>和<span>Mac OS X</span>系統中的默認值。</p></td> </tr><tr><td> <p> <span>2</span></p></td> <td> <p>表名和數據庫名在硬盤上使用<span>CREATE TABLE</span>或<span>CREATE DATABASE</span>語句指定的大小寫進行保存,但<span>MySQL</span>將它們轉換為小寫以便查找。名稱比較對大小寫敏感。<strong><span>注</span><span>釋:</span></strong><em><span>只</span></em>在對大小寫不敏感的文件系統上適用<span>! </span> <span>InnoDB</span>表名以小寫保存,例如<span>lower_case_tables_name=1</span>。</p></td> </tr></table>
在Windows和Mac OS X中,lower_case_tables_name的 默認值是1。
如果只在一個平臺上使用MySQL,通常不需要更改lower_case_tables_name變量。然而,如果你想要在對大小寫敏感不同的文件系統的平臺之間轉移表,會遇到困難。例如,在Unix中,my_tables和MY_tables是兩個不同的表,但在Windows中,這兩個表名相同。要想避免由于數據庫或表名的大小寫造成的數據轉移問題,可使用兩個選項:
·???????? 在任何系統中可以使用lower_case_tables_name=1。使用該選項的不利之處是當使用SHOW TABLES或SHOW DATABASES時,看不出名字原來是用大寫還是小寫。
·???????? 在Unix中使用lower_case_tables_name=0,在Windows中使用lower_case_tables_name=2。這樣了可以保留數據庫名和表名的大小寫。不利之處是必須確保在Windows中查詢總是用正確大小寫引用數據庫名和表名。如果將查詢轉移到Unix中,由于在Unix中大小寫很重要,如果大小寫不正確,它們不工作。
**例外**:如果你正使用InnoDB表,在任何平臺上均應將lower_case_tables_name設置為1,以強制將名轉換為小寫。
請注意在Unix中將lower_case_tables_name設置為1之前,重啟**mysqld**之前,必須先將舊的數據庫名和表名轉換為小寫。
### 9.3.?用戶變量
可以先在用戶變量中保存值然后在以后引用它;這樣可以將值從一個語句傳遞到另一個語句。*用戶變量與連接有關*。也就是說,一個客戶端定義的變量不能被其它客戶端看到或使用。當客戶端退出時,該客戶端連接的所有變量將自動釋放。
用戶變量的形式為@*var_name*,其中變量名*var_name*可以由當前字符集的文字數字字符、‘.’、‘_’和‘$’組成。 默認字符集是cp1252 (Latin1)。可以用**mysqld**的--default-character-set選項更改字符集。參見[5.10.1節,“數據和排序用字符集”](# "5.10.1.?The Character Set Used for Data and Sorting")。用戶變量名對大小寫不敏感。
設置用戶變量的一個途徑是執行SET語句:
~~~
SET @var_name = expr [, @var_name = expr] ...
~~~
對于SET,可以使用=或:=作為分配符。分配給每個變量的*expr*可以為整數、實數、字符串或者NULL值。
也可以用語句代替SET來為用戶變量分配一個值。在這種情況下,分配符必須為:=而不能用=,因為在非SET語句中=被視為一個比較 操作符:
~~~
mysql> SET @t1=0, @t2=0, @t3=0;
~~~
~~~
mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
~~~
~~~
+----------------------+------+------+------+
~~~
~~~
| @t1:=(@t2:=1)+@t3:=4 | @t1? | @t2? | @t3? |
~~~
~~~
+----------------------+------+------+------+
~~~
~~~
|????????????????? ??5 |??? 5 |??? 1 |??? 4 |
~~~
~~~
+----------------------+------+------+------+
~~~
用戶變量可以用于表達式中。目前不包括明顯需要文字值的上下文中,例如SELECT語句的LIMIT子句,或者LOAD DATA語句的IGNORE number LINES子句。
如果使用沒有初始化的變量,其值是NULL。
如果用戶變量分配了一個字符串值,其字符集和校對規則與該字符串的相同。用戶變量的可壓縮性(coercibility)是隱含的。(即為表列值的相同的可壓縮性(coercibility)。
**注釋:**在SELECT語句中,表達式發送到客戶端后才進行計算。這說明在HAVING、GROUP BY或者ORDER BY子句中,不能使用包含SELECT列表中所設的變量的表達式。例如,下面的語句不能按期望工作:
~~~
mysql> SELECT (@aa:=id) AS a,(@aa+3) AS b 從tbl_name HAVING b=5;
~~~
HAVING子句中引用了SELECT列表中的表達式的別名,使用@aa。不能按期望工作:@aa不包含當前行的值,而是前面所選的行的id值。
一般原則是不要在語句的一個部分為用戶變量分配一個值而在同一語句的其它部分使用該變量。可能會得到期望的結果,但不能保證。
設置變量并在同一語句中使用它的另一個問題是變量的默認結果的類型取決于語句前面的變量類型。下面的例子說明了該點:
~~~
mysql> SET @a='test';
~~~
~~~
mysql> SELECT @a,(@a:=20) FROM tbl_name;
~~~
對于該 SELECT語句,MySQL向客戶端報告第1列是一個字符串,并且將@a的所有訪問轉換為字符串,即使@a在第2行中設置為一個數字。執行完SELECT語句后,@a被視為下一語句的一個數字。
要想避免這種問題,要么不在同一個語句中設置并使用相同的變量,要么在使用前將變量設置為0、0.0或者''以定義其類型。
未分配的變量有一個值NULL,類型為字符串。
### 9.4.?系統變量
[ 9.4.1. 結構式系統變量](#)
MySQL可以訪問許多系統和連接變量。當服務器運行時許多變量可以動態更改。這樣通常允許你修改服務器操作而不需要停止并重啟服務器。
**mysqld**服務器維護兩種變量。全局變量影響服務器整體操作。會話變量影響具體客戶端連接的操作。
當服務器啟動時,它將所有全局變量初始化為默認值。這些默認值可以在選項文件中或在命令行中指定的選項進行更改。服務器啟動后,通過連接服務器并執行SET GLOBAL *var_name*語句,可以動態更改這些全局變量。要想更改全局變量,必須具有SUPER權限。
服務器還為每個連接的客戶端維護一系列會話變量。在連接時使用相應全局變量的當前值對客戶端的會話變量進行初始化。對于動態會話變量,客戶端可以通過SET SESSION *var_name*語句更改它們。設置會話變量不需要特殊權限,但客戶端只能更改自己的會話變量,而不能更改其它客戶端的會話變量。
對于全局變量的更改可以被訪問該全局變量的任何客戶端看見。然而,它只影響更改后連接的客戶的從該全局變量初始化的相應會話變量。不影響目前已經連接的客戶端的會話變量(即使客戶端執行SET GLOBAL語句也不影響)。
可以使用幾種語法形式來設置或檢索全局或會話變量。下面的例子使用了sort_buffer_sizeas作為示例變量名。
要想設置一個GLOBAL變量的值,使用下面的語法:
~~~
mysql> SET GLOBAL sort_buffer_size=value;
~~~
~~~
mysql> SET @@global.sort_buffer_size=value;
~~~
要想設置一個SESSION變量的值,使用下面的語法:
~~~
mysql> SET SESSION sort_buffer_size=value;
~~~
~~~
mysql> SET @@session.sort_buffer_size=value;
~~~
~~~
mysql> SET sort_buffer_size=value;
~~~
LOCAL是SESSION的同義詞。
如果設置變量時不指定GLOBAL、SESSION或者LOCAL,默認使用SESSION。參見[13.5.3節,“SET語法”](# "13.5.3.?SET Syntax")。
要想檢索一個GLOBAL變量的值,使用下面的語法:
~~~
mysql> SELECT @@global.sort_buffer_size;
~~~
~~~
mysql> SHOW GLOBAL VARIABLES like 'sort_buffer_size';
~~~
要想檢索一個SESSION變量的值,使用下面的語法:
~~~
mysql> SELECT @@sort_buffer_size;
~~~
~~~
mysql> SELECT @@session.sort_buffer_size;
~~~
~~~
mysql> SHOW SESSION VARIABLES like 'sort_buffer_size';
~~~
這里,LOCAL也是SESSION的同義詞。
當你用SELECT @@*var_name*搜索一個變量時(也就是說,不指定global.、session.或者local.),MySQL返回SESSION值(如果存在),否則返回GLOBAL值。
對于SHOW VARIABLES,如果不指定GLOBAL、SESSION或者LOCAL,MySQL返回SESSION值。
當設置GLOBAL變量需要GLOBAL關鍵字但檢索時不需要它們的原因是防止將來出現問題。如果我們移除一個與某個GLOBAL變量具有相同名字的SESSION變量,具有SUPER權限的客戶可能會意外地更改GLOBAL變量而不是它自己的連接的SESSION變量。如果我們添加一個與某個GLOBAL變量具有相同名字的SESSION變量,想更改GLOBAL變量的客戶可能會發現只有自己的SESSION變量被更改了。
關于系統啟動選項和系統變量的詳細信息參見[5.3.1節,“**mysqld**命令行選項”](# "5.3.1.?mysqld Command-Line Options")和[5.3.3節,“服務器系統變量”](# "5.3.3.?Server System Variables")。在[5.3.3.1節,“動態系統變量”](# "5.3.3.1.?Dynamic System Variables")中列出了可以在運行時設置的變量。
### 9.4.1.?結構式系統變量
結構式變量在兩個方面不同于常規系統變量:
·???????? 其值是一個含組件的結構,可以指定服務器參數,一般緊密相關。
·???????? 可能是給定類型的結構式變量的幾個實例。每個實例有一個不同的名,指向服務器維護的不同的資源。
MySQL 5.1支持結構式變量類型,可以指定監控鍵值緩存操作的參數。鍵值緩存結構式變量有以下組件:
·???????? key_buffer_size
·???????? key_cache_block_size
·???????? key_cache_division_limit
·???????? key_cache_age_threshold
該節描述了引用結構式變量的語法。在語法的例子中使用了鍵值緩存變量,但關于鍵值緩存如何操作的具體詳情在其它章節中,如 [ 7.4.6節,“MyISAM鍵高速緩沖”](# "7.4.6.?The MyISAM Key Cache")。
要引用結構式變量實例的組件,可以使用instance_name.component_name格式的復合名。例如:
~~~
hot_cache.key_buffer_size
~~~
~~~
hot_cache.key_cache_block_size
~~~
~~~
cold_cache.key_cache_block_size
~~~
對于每個結構式系統變量,總是預定義名為default的一個實例。如果不使用任何實例名引用結構式變量的一個組件,default實例被使用。這樣,default.key_buffer_size和key_buffer_sizeboth均指向同一系統變量。
結構式變量實例和組件的命名規則為:
·???????? 對于給定類型的結構式變量,每個實例必須有一個在該類變量中唯一的一個名。但是,在不同類型的結構式變量中實例名不需要唯一。例如,每個結構式變量有一個實例default,因此在不同的變量類型中default不是唯一的。
·???????? 每個結構式變量類型的組件名在所有系統變量名中必須是唯一的。如果不是這樣(也就是說,如果兩個不同類型的結構式變量能夠共享組件成員名),將不清楚使用哪個默認結構式變量來用作沒有使用實例名限定的成員名。
·???????? 如果結構式變量實例名作為未引起來的識別符不合法,將它用反勾號引起來作為識別符。例如,hot-cache不合法,但`hot-cache`合法。
·???????? global、session和local不是合法實例名。這樣可以避免與引用非結構式系統變量的符號的沖突,例如@@global.*var_name*。
目前,這前兩個規則不可能違背,因為唯一的結構式變量類型是鍵值緩存。在將來創建其它類型的結構式變量,這些規則將有重要的意義。
一個例外是,可以在可能出現簡單變量名的上下文中使用復合名引用結構式變量組件。例如,可以使用一個命令行選項未某個結構式變量分配一個值:
~~~
shell> mysqld --hot_cache.key_buffer_size=64K
~~~
在選項文件中,使用:
~~~
[mysqld]
~~~
~~~
hot_cache.key_buffer_size=64K
~~~
如果用該選項啟動服務器,除了默認大小為8MB的默認鍵值緩存,還創建一個名為hot_cache的鍵值緩存,大小為64KB。
假定你這樣啟動服務器:
~~~
shell> mysqld --key_buffer_size=256K \
~~~
~~~
???????? --extra_cache.key_buffer_size=128K \
~~~
~~~
???????? --extra_cache.key_cache_block_size=2048
~~~
在這種情況下,服務器將默認鍵值緩存的大小設定為256KB。(也可以寫成--default.key_buffer_size=256K)。 并且,服務器創建一個名為extra_cache的第2個鍵值緩存,大小為128KB,緩存表索引塊的塊緩存區的大小設置為2048字節。
在下面的例子中,用3個不同的鍵值緩存(大小比例為3:1:1)啟動服務器:
~~~
shell> mysqld --key_buffer_size=6M \
~~~
~~~
??????? ?--hot_cache.key_buffer_size=2M \
~~~
~~~
???????? --cold_cache.key_buffer_size=2M
~~~
也可以在運行時設置和檢索結構式變量值。例如,要想將名為hot_cache的一個鍵值緩存的大小設置為10MB,使用下面任何一個語句:
~~~
mysql> SET GLOBAL hot_cache.key_buffer_size = 10*1024*1024;
~~~
~~~
mysql> SET @@global.hot_cache.key_buffer_size = 10*1024*1024;
~~~
要想檢索緩存大小,執行:
~~~
mysql> SELECT @@global.hot_cache.key_buffer_size;
~~~
但是,下面的語句不工作。變量不解釋為一個復合名,而是解釋為LIKE模式匹配操作的簡單字符串:
~~~
mysql> SHOW GLOBAL VARIABLES LIKE 'hot_cache.key_buffer_size';
~~~
這是一個在可能出現簡單的變量名時使用結構式變量名的例子。
### 9.5.?注釋語法
MySQL服務器支持3種注釋風格:
·???????? 從‘#’字符從行尾。
·???????? 從‘-- ’序列到行尾。請注意‘-- ’(雙破折號)注釋風格要求第2個破折號后面至少跟一個空格符(例如空格、tab、換行符等等)。該語法與標準SQL注釋語法稍有不同,后者將在[1.8.5.7, “‘--’作為注釋起始標記”](# "1.8.5.7.?'--' as the Start of a Comment")中討論。
·???????? 從/*序列到后面的*/序列。結束序列不一定在同一行中,因此該語法允許注釋跨越多行。
下面的例子顯示了3種風格的注釋:
~~~
mysql> SELECT 1+1;???? # This comment continues to the end of line
~~~
~~~
mysql> SELECT 1+1;???? -- This comment continues to the end of line
~~~
~~~
mysql> SELECT 1 /* this is an in-line comment */ + 1;
~~~
~~~
mysql> SELECT 1+
~~~
~~~
/*
~~~
~~~
this is a
~~~
~~~
multiple-line comment
~~~
~~~
*/
~~~
~~~
1;
~~~
上述的注釋語法適用于**mysqld**服務器如何分析SQL語句。發送到服務器之前,**mysql客戶**程序也執行部分語句解析。(例如,它通過解析來確定在多語句行中的語句邊界)。
在MySQL 5.1中,**mysql**解析/* ...*/注釋的唯一局限性是結合該風格的注釋定界符使用的嘆號標記了有條件執行的SQL語句部分。適用于交互式運行**mysql**和將命令放入一個文件中,并以批處理模式使用**mysql**來處理**mysql < *****file_name***的文件。詳細信息和例子參見[1.8.4節,“MySQL對標準SQL的擴展”](# "1.8.4.?MySQL Extensions to Standard SQL")。
### 9.6.?MySQL中保留字的處理
嘗試使用一個識別符,例如使用嵌入式MySQL數據類型或函數名作為表名或列名,例如TIMESTAMP或GROUP,會造成一個常見問題。允許你這樣操作(例如,ABS可以作為一個列名)。但是,默認情況下,在數調用中在函數名和后面的‘(’字符之間不允許有空格。該要求使函數調用與列名引用不同。
該行為的不利結果是在某些上下文中省略一個空格會使識別符解釋為函數名。例如,該語句合法:
~~~
mysql> CREATE TABLE abs (val INT);
~~~
但省略abs后面的空格會造成語法錯誤,因為省略后該語句好像要調用ABS()函數:
~~~
mysql> CREATE TABLE abs(val INT);
~~~
如果SQL服務器模式包括IGNORE_SPACE模式值,服務器允許函數調用時在函數名和后面的‘(’字符之間有空格。這樣使函數名被視為保留字。結果是,與函數名相同的識別符必須按照[9.2節,“數據庫、表、索引、列和別名”](# "9.2.?Database, Table, Index, Column, and Alias Names")中所描述的引起來。SQL服務器模式按照[5.3.2節,“SQL服務器模式”](# "5.3.2.?The Server SQL Mode")中所描述的進行控制。
限定名中句點后面的字必須為一個識別符,因此不需要將它引起來,即使它是一個保留字。
在MySQL中,下表中的字顯式被保留。其中大多數字進制被標準SQL用作列名和/或表名(例如,GROUP)。少數被保留了,因為MySQL需要它們,(目前)使用**yacc**解析程序。保留字被引起來后可以用作識別符。
| ADD | ALL | ALTER |
|-----|-----|-----|
| ANALYZE | AND | AS |
| ASC | ASENSITIVE | BEFORE |
| BETWEEN | BIGINT | BINARY |
| BLOB | BOTH | BY |
| CALL | CASCADE | CASE |
| CHANGE | CHAR | CHARACTER |
| CHECK | COLLATE | COLUMN |
| CONDITION | CONNECTION | CONSTRAINT |
| CONTINUE | CONVERT | CREATE |
| CROSS | CURRENT_DATE | CURRENT_TIME |
| CURRENT_TIMESTAMP | CURRENT_USER | CURSOR |
| DATABASE | DATABASES | DAY_HOUR |
| DAY_MICROSECOND | DAY_MINUTE | DAY_SECOND |
| DEC | DECIMAL | DECLARE |
| DEFAULT | DELAYED | DELETE |
| DESC | DESCRIBE | DETERMINISTIC |
| DISTINCT | DISTINCTROW | DIV |
| DOUBLE | DROP | DUAL |
| EACH | ELSE | ELSEIF |
| ENCLOSED | ESCAPED | EXISTS |
| EXIT | EXPLAIN | FALSE |
| FETCH | FLOAT | FLOAT4 |
| FLOAT8 | FOR | FORCE |
| FOREIGN | FROM | FULLTEXT |
| GOTO | GRANT | GROUP |
| HAVING | HIGH_PRIORITY | HOUR_MICROSECOND |
| HOUR_MINUTE | HOUR_SECOND | IF |
| IGNORE | IN | INDEX |
| INFILE | INNER | INOUT |
| INSENSITIVE | INSERT | INT |
| INT1 | INT2 | INT3 |
| INT4 | INT8 | INTEGER |
| INTERVAL | INTO | IS |
| ITERATE | JOIN | KEY |
| KEYS | KILL | LABEL |
| LEADING | LEAVE | LEFT |
| LIKE | LIMIT | LINEAR |
| LINES | LOAD | LOCALTIME |
| LOCALTIMESTAMP | LOCK | LONG |
| LONGBLOB | LONGTEXT | LOOP |
| LOW_PRIORITY | MATCH | MEDIUMBLOB |
| MEDIUMINT | MEDIUMTEXT | MIDDLEINT |
| MINUTE_MICROSECOND | MINUTE_SECOND | MOD |
| MODIFIES | NATURAL | NOT |
| NO_WRITE_TO_BINLOG | NULL | NUMERIC |
| ON | OPTIMIZE | OPTION |
| OPTIONALLY | OR | ORDER |
| OUT | OUTER | OUTFILE |
| PRECISION | PRIMARY | PROCEDURE |
| PURGE | RAID0 | RANGE |
| READ | READS | REAL |
| REFERENCES | REGEXP | RELEASE |
| RENAME | REPEAT | REPLACE |
| REQUIRE | RESTRICT | RETURN |
| REVOKE | RIGHT | RLIKE |
| SCHEMA | SCHEMAS | SECOND_MICROSECOND |
| SELECT | SENSITIVE | SEPARATOR |
| SET | SHOW | SMALLINT |
| SPATIAL | SPECIFIC | SQL |
| SQLEXCEPTION | SQLSTATE | SQLWARNING |
| SQL_BIG_RESULT | SQL_CALC_FOUND_ROWS | SQL_SMALL_RESULT |
| SSL | STARTING | STRAIGHT_JOIN |
| TABLE | TERMINATED | THEN |
| TINYBLOB | TINYINT | TINYTEXT |
| TO | TRAILING | TRIGGER |
| TRUE | UNDO | UNION |
| UNIQUE | UNLOCK | UNSIGNED |
| UPDATE | USAGE | USE |
| USING | UTC_DATE | UTC_TIME |
| UTC_TIMESTAMP | VALUES | VARBINARY |
| VARCHAR | VARCHARACTER | VARYING |
| WHEN | WHERE | WHILE |
| WITH | WRITE | X509 |
| XOR | YEAR_MONTH | ZEROFILL |
MySQL允許部分關鍵字用做未引起來的識別符,因為許多人以前曾使用過它們。下面列出了一些例子:
-
ACTION
-
BIT
-
DATE
-
ENUM
-
NO
-
TEXT
-
TIME
-
TIMESTAMP
這是MySQL參考手冊的翻譯版本,關于MySQL參考手冊,請訪問[dev.mysql.com.](http://dev.mysql.com/doc/mysql/en)。原始參考手冊為英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。
- 目錄
- 前言
- 1. 一般信息
- 2. 安裝MySQL
- 3. 教程
- NoName
- 4. MySQL程序概述
- 5. 數據庫管理
- 6. MySQL中的復制
- 7. 優化
- 8. 客戶端和實用工具程序
- 9. 語言結構
- 10. 字符集支持
- 11. 列類型
- 12. 函數和操作符
- 13. SQL語句語法
- 14. 插件式存儲引擎體系結構
- 15. 存儲引擎和表類型
- 16. 編寫自定義存儲引擎
- 17. MySQL簇
- 18. 分區
- 19. MySQL中的空間擴展
- 20. 存儲程序和函數
- 21. 觸發程序
- 22. 視圖
- 23. INFORMATION_SCHEMA信息數據庫
- 24. 精度數學
- 25. API和庫
- 26. 連接器
- 27. 擴展MySQL
- A. 問題和常見錯誤
- B. 錯誤代碼和消息
- C. 感謝
- D. MySQL變更史
- E. 移植到其他系統
- F. 環境變量
- G. MySQL正則表達式
- H. MySQL中的限制
- I. 特性限制
- J. GNU通用公共許可
- K. MySQL FLOSS許可例外
- 索引