發新話題

MySQL語言,程式設計,語法大全

MySQL語言,程式設計,語法大全

7 MySQL語言參考
7.1 文字:怎麼寫字符串和數字
7.1.1 字符串:
一個字符串是一個字符序列,由單引號(“'”)或雙引號(“"”)字符(後者只有你不在ANSI模式運行)包圍。例如:
'a string'
"another string"

在字符串內,某個順序有特殊的意義。這些順序的每一個以一條反斜線(“\”)開始,稱為轉義字符。MySQL識別下列轉義字符:
\0
    一個ASCII 0 (NUL)字符。
\n
    一個新行符。
\t
    一個定位符。
\r
    一個回車符。
\b
    一個退格符。
\'
    一個單引號(“'”)符。
\"
    一個雙引號(“"”)符。
\\
    一個反斜線(“\”)符。
\%
    一個“%”符。它用于在正文中搜索“%”的文字實例,否則這里“%”將解釋為一個通配符。
\_
    一個“_”符。它用于在正文中搜索“_”的文字實例,否則這里“_”將解釋為一個通配符。

注意,如果你在某些正文環境中使用“\%”或“\%_”,這些將返回字符串“\%”和“\_”而不是“%”和“_”。

有幾種方法在一個字符串內包括引號:

    * 一個字符串內用“'”加引號的“'”可以被寫作為“''”。
    * 一個字符串內用“"”加引號的“"”可以被寫作為“""”。
    * 你可以把一個轉義字符(“\”)放在引號前面。
    * 一個字符串內用“"”加引號的“'”不需要特殊對待而且不必被重複或轉義。同理,一個字符串內用“'”加引號的與“"”也不需要特殊對待。

下面顯示的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 |
+--------------------+


如果你想要把二進制數據插入到一個BLOB列,下列字符必須由轉義序列表示:

NUL
    ASCII 0。你應該用'\0'(一個反斜線和一個ASCII '0')表示它。
\
    ASCII 92,反斜線。用'\\'表示。
'
    ASCII 39,單引號。用“\'”表示。
"
    ASCII 34,雙引號。用“\"”表示。

如果你寫C代碼,你可以使用C API函數mysql_escape_string()來為INSERT語句轉義字符。見20.3 C API 函數概述。在 Perl中,你可以使用DBI包中的quote方法變換特殊的字符到正確的轉義序列。見20.5.2 DBI接口。

你應該在任何可能包含上述任何特殊字符的字符串上使用轉義函數!
7.1.2 數字

整數表示為一個數字順序。浮點數使用“.”作為一個十進制分隔符。這兩種類型的數字可以前置“-”表明一個負值。

有效整數的例子:

1221
0
-32

有效浮點數的例子:

294.42
-32032.6809e+10
148.00

一個整數可以在浮點上下文使用;它解釋為等值的浮點數。
7.1.3 十六進制值

MySQL支持十六進制值。在數字上下文,它們表現類似于一個整數(64位精度)。在字符串上下文,它們表現類似于一個二進制字符串,這里每一對十六進制數字被變換為一個字符。

mysql> SELECT 0xa+0
       -> 10
mysql> select 0x5061756c;
       -> Paul

十六進制字符串經常被ODBC使用,給出BLOB列的值。
7.1.4 NULL值

NULL值意味著“無數據”並且不同于例如數字類型的0為或字符串類型的空字符串。見18.15 NULL值問題。

當使用文本文件導入或導出格式(LOAD DATA INFILE, SELECT ... INTO OUTFILE)時,NULL可以用\N表示。見7.16 LOAD DATA INFILE句法。
7.1.5 數據庫、表、索引、列和別名的命名

數據庫、表、索引、列和別名的名字都遵守MySQL同樣的規則:

注意,從MySQL3.23.6開始規則改變了,此時我們引入了用'引用的標識符(數據庫、表和列命名)(如果你以ANSI模式運行,"也將用于引用標識符)。
標識符         最大長度         允許的字符
數據庫         64         在一個目錄名允許的任何字符,除了/.
表         64         在文件名中允許的任何字符,除了/或.
列         64         所有字符
別名         255         所有字符

注意,除了以上,你在一個標識符中不能有ASCII(0)或ASCII(255)。

注意,如果標識符是一個限制詞或包含特殊字符,當你使用它時,你必須總是用`引用它:

SELECT * from `select` where `select`.id > 100;

在 MySQL的先前版本,命名規則如下:

    * 一個名字可以包含來自當前字符集的數字字母的字符和“_”和“$”。缺省字符集是ISO-8859-1 Latin1;這可以通過重新編譯MySQL來改變。見9.1.1 用于數據和排序的字符集。
    * 一個名字可以以在一個名字中合法的任何字符開始。特別地,一個名字可以以一個數字開始(這不同于許多其他的數據庫系統!)。然而,一個名字不能僅僅由數字組成。
    * 你不能在名字中使用“.”,因為它被用來擴充格式,你能用它引用列(見下面)。

建議你不使用象1e這樣的名字,因為一個表達式如1e+1是二義性的。它可以解釋為表達式1e + 1或數字1e+1。

在MySQL中,你能使用下列表格的任何一種引用列:
列引用         含義
col_name         來自于任意表的列col_name,用于包含該表的一個列的查詢中
tbl_name.col_name         來自當前的數據庫的表tbl_name的列col_name
db_name.tbl_name.col_name         行列col_name從表格tbl_name數據庫db_name。這個形式在MySQL3.22或以後版本可用。
`column_name`         是一個關鍵詞或包含特殊字符的列。

在一條語句的列引用中,你不必指定一個tbl_name或db_name.tbl_name前綴,除非引用會有二義性。例如,假定表t1和t2,每個均包含列c,並且你用一個使用t1和t2的SELECT語句檢索c。在這種情況下,c有二義性,因為它在使用表的語句中不是唯一的,因此你必須通過寫出t1.c或t2.c來指明你想要哪個表。同樣,如果你從數據庫db1中一個表t和在數據庫db2的一個表t檢索,你必須用db1.t.col_name和db2.t.col_name引用這些數據表的列。

句法.tbl_name意味著在當前的數據庫中的表tbl_name,該句法為了ODBC的兼容性被接受,因為一些ODBC程序用一個“.”字符作為數據庫表名的前綴。
7.1.5.1 名字的大小寫敏感性

在MySQL中,數據庫和表對應于在那些目錄下的目錄和文件,因而,內在的操作系統的敏感性決定數據庫和表命名的大小寫敏感性。這意味著數據庫和表名在Unix上是區分大小寫的,而在Win32上忽略大小寫。

注意:在Win32上,盡管數據庫和表名是忽略大小寫的,你不應該在同一個查詢中使用不同的大小寫來引用一個給定的數據庫和表。下列查詢將不工作,因為它作為my_table和作為MY_TABLE引用一個表:

mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;

列名在所有情況下都是忽略大小寫的。

表的別名是區分大小寫的。下列查詢將不工作,: 因為它用a和A引用別名:

mysql> SELECT col_name FROM tbl_name AS a
           WHERE a.col_name = 1 OR A.col_name = 2;

列的別名是忽略大小寫的。
7.2 用戶變量

MySQL支持線程特定的變量,用@variablename句法。一個變量名可以由當前字符集的數字字母字符和“_”、“$”和“.”組成。缺省字符集是ISO-8859-1 Latin1;這可以通過重新編譯MySQL改變。見9.1.1 用于數據和排序的字符集。

變量不必被初始化。缺省地,他們包含NULL並能存儲整數、實數或一個字符串值。當線程退出時,對于一個線程的所有變量自動地被釋放。

你可以用SET句法設置一個變量:

SET @variable= { integer expression | real expression | string expression }
[,@variable= ...].

你也可以用@variable:=expr句法在一個表達式中設置一個變量:

select @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
+----------------------+------+------+------+
|                    5 |    5 |    1 |    4 |
+----------------------+------+------+------+

(這里,我們不得不使用:=句法,因為=是為比較保留的)
7.3 列類型

MySQL支持大量的列類型,它可以被分為3類:數字類型、日期和時間類型以及字符串(字符)類型。本節首先給出可用類型的一個概述,並且總結每個列類型的存儲需求,然後提供每個類中的類型性質的更詳細的描述。概述有意簡化,更詳細的說明應該考慮到有關特定列類型的附加信息,例如你能為其指定值的允許格式。

由MySQL支持的列類型列在下面。下列代碼字母用于描述中:

M
    指出最大的顯示尺寸。最大的合法的顯示尺寸是 255 。
D
    適用于浮點類型並且指出跟隨在十進制小數點後的數碼的數量。最大可能的值是30,但是應該不大于M-2。

方括號(“[”和“]”)指出可選的類型修飾符的部分。

注意,如果你指定一個了為ZEROFILL,MySQL將為該列自動地增加UNSIGNED屬性。

TINYINT[(M)] [UNSIGNED] [ZEROFILL]
    一個很小的整數。有符號的範圍是-128到127,無符號的範圍是0到255。
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
    一個小整數。有符號的範圍是-32768到32767,無符號的範圍是0到65535。
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
    一個中等大小整數。有符號的範圍是-8388608到8388607,無符號的範圍是0到16777215。
INT[(M)] [UNSIGNED] [ZEROFILL]
    一個正常大小整數。有符號的範圍是-2147483648到2147483647,無符號的範圍是0到4294967295。
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
    這是INT的一個同義詞。
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
    一個大整數。有符號的範圍是-9223372036854775808到9223372036854775807,無符號的範圍是0到18446744073709551615。注意,所有算術運算用有符號的BIGINT或DOUBLE值完成,因此你不應該使用大于9223372036854775807(63位)的有符號大整數,除了位函數!注意,當兩個參數是INTEGER值時,-、+和*將使用BIGINT運算!這意味著如果你乘2個大整數(或來自于返回整數的函數),如果結果大于9223372036854775807,你可以得到意外的結果。一個浮點數字,不能是無符號的,對一個單精度浮點數,其精度可以是<=24,對一個雙精度浮點數,是在25 和53之間,這些類型如FLOAT和DOUBLE類型馬上在下面描述。FLOAT(X)有對應的FLOAT和DOUBLE相同的範圍,但是顯示尺寸和小數位數是未定義的。在MySQL3.23中,這是一個真正的浮點值。在更早的MySQL版本中,FLOAT(precision)總是有2位小數。該句法為了ODBC兼容性而提供。
FLOAT[(M,D)] [ZEROFILL]
    一個小(單精密)浮點數字。不能無符號。允許的值是-3.402823466E+38到-1.175494351E-38,0 和1.175494351E-38到3.402823466E+38。M是顯示寬度而D是小數的位數。沒有參數的FLOAT或有<24 的一個參數表示一個單精密浮點數字。
DOUBLE[(M,D)] [ZEROFILL]
    一個正常大小(雙精密)浮點數字。不能無符號。允許的值是-1.7976931348623157E+308到-2.2250738585072014E-308、 0和2.2250738585072014E-308到1.7976931348623157E+308。M是顯示寬度而D是小數位數。沒有一個參數的DOUBLE或FLOAT(X)(25 < = X < = 53)代表一個雙精密浮點數字。
DOUBLE PRECISION[(M,D)] [ZEROFILL]
     
REAL[(M,D)] [ZEROFILL]
    這些是DOUBLE同義詞。
DECIMAL[(M[,D])] [ZEROFILL]
    一個未壓縮(unpack)的浮點數字。不能無符號。行為如同一個CHAR列:“未壓縮”意味著數字作為一個字符串被存儲,值的每一位使用一個字符。小數點,並且對于負數,“-”符號不在M中計算。如果D是0,值將沒有小數點或小數部分。DECIMAL值的最大範圍與DOUBLE相同,但是對一個給定的DECIMAL列,實際的範圍可以通過M和D的選擇被限制。如果D被省略,它被設置為0。如果M被省掉,它被設置為10。注意,在MySQL3.22里,M參數包括符號和小數點。
NUMERIC(M,D) [ZEROFILL]
    這是DECIMAL的一個同義詞。
DATE
    一個日期。支持的範圍是'1000-01-01'到'9999-12-31'。MySQL以'YYYY-MM-DD'格式來顯示DATE值,但是允許你使用字符串或數字把值賦給DATE列。
DATETIME
    一個日期和時間組合。支持的範圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。MySQL以'YYYY-MM-DD HH:MM:SS'格式來顯示DATETIME值,但是允許你使用字符串或數字把值賦給DATETIME的列。
TIMESTAMP[(M)]
    一個時間戳記。範圍是'1970-01-01 00:00:00'到2037年的某時。MySQL以YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD或YYMMDD格式來顯示TIMESTAMP值,取決于是否M是14(或省略)、12、8或6,但是允許你使用字符串或數字把值賦給TIMESTAMP列。一個TIMESTAMP列對于記錄一個INSERT或UPDATE操作的日期和時間是有用的,因為如果你不自己給它賦值,它自動地被設置為最近操作的日期和時間。你以可以通過賦給它一個NULL值設置它為當前的日期和時間。見7.3.6 日期和時間類型。
TIME
    一個時間。範圍是'-838:59:59'到'838:59:59'。MySQL以'HH:MM:SS'格式來顯示TIME值,但是允許你使用字符串或數字把值賦給TIME列。
YEAR[(2|4)]
    一個2或4位數字格式的年(缺省是4位)。允許的值是1901到2155,和0000(4位年格式),如果你使用2位,1970-2069( 70-69)。MySQL以YYYY格式來顯示YEAR值,但是允許你把使用字符串或數字值賦給YEAR列。(YEAR類型在MySQL3.22中是新類型。)
CHAR(M) [BINARY]
    一個定長字符串,當存儲時,總是是用空格填滿右邊到指定的長度。M的範圍是1 ~ 255個字符。當值被檢索時,空格尾部被刪除。CHAR值根據缺省字符集以大小寫不區分的方式排序和比較,除非給出BINARY關鍵詞。NATIONAL CHAR(短形式NCHAR)是ANSI SQL的方式來定義CHAR列應該使用缺省字符集。這是MySQL的缺省。CHAR是CHARACTER的一個縮寫。
[NATIONAL] VARCHAR(M) [BINARY]
    一個變長字符串。注意:當值被存儲時,尾部的空格被刪除(這不同于ANSI SQL規範)。M的範圍是1 ~ 255個字符。 VARCHAR值根據缺省字符集以大小寫不區分的方式排序和比較,除非給出BINARY關鍵詞值。見7.7.1 隱式列指定變化。 VARCHAR是CHARACTER VARYING一個縮寫。
TINYBLOB
     
TINYTEXT
    一個BLOB或TEXT列,最大長度為255(2^8-1)個字符。見7.7.1 隱式列指定變化。
BLOB
     
TEXT
    一個BLOB或TEXT列,最大長度為65535(2^16-1)個字符。見7.7.1 隱式列指定變化。
MEDIUMBLOB
     
MEDIUMTEXT
    一個BLOB或TEXT列,最大長度為16777215(2^24-1)個字符。見7.7.1 隱式列指定變化。
LONGBLOB
     
LONGTEXT
    一個BLOB或TEXT列,最大長度為4294967295(2^32-1)個字符。見7.7.1 隱式列指定變化
ENUM('value1','value2',...)
    枚舉。一個僅有一個值的字符串對象,這個值式選自與值列表'value1'、'value2', ...,或NULL。一個ENUM最多能有65535不同的值。
SET('value1','value2',...)
    一個集合。能有零個或多個值的一個字符串對象,其中每一個必須從值列表'value1', 'value2', ...選出。一個SET最多能有64個成員。

7.3.1 列類型存儲需求

對于每個由MySQL支持的列類型的存儲需求在下面按類列出。
7.3.2 數字類型
列類型         需要的存儲量
TINYINT         1 字節
SMALLINT         2 個字節
MEDIUMINT         3 個字節
INT         4 個字節
INTEGER         4 個字節
BIGINT         8 個字節
FLOAT(X)         4 如果 X < = 24 或 8 如果 25 < = X < = 53
FLOAT         4 個字節
DOUBLE         8 個字節
DOUBLE PRECISION         8 個字節
REAL         8 個字節
DECIMAL(M,D)         M字節(D+2 , 如果M < D)
NUMERIC(M,D)         M字節(D+2 , 如果M < D)
7.3.3 日期和時間類型
列類型         需要的存儲量
DATE         3 個字節
DATETIME         8 個字節
TIMESTAMP         4 個字節
TIME         3 個字節
YEAR         1 字節
7.3.4 串類型
列類型         需要的存儲量
CHAR(M)         M字節,1 <= M <= 255
VARCHAR(M)         L+1 字節, 在此L <= M和1 <= M <= 255
TINYBLOB, TINYTEXT         L+1 字節, 在此L< 2 ^ 8
BLOB, TEXT         L+2 字節, 在此L< 2 ^ 16
MEDIUMBLOB, MEDIUMTEXT         L+3 字節, 在此L< 2 ^ 24
LONGBLOB, LONGTEXT         L+4 字節, 在此L< 2 ^ 32
ENUM('value1','value2',...)         1 或 2 個字節, 取決于枚舉值的數目(最大值65535)
SET('value1','value2',...)         1,2,3,4或8個字節, 取決于集合成員的數量(最多64個成員)

VARCHAR和BLOB和TEXT類型是變長類型,對于其存儲需求取決于列值的實際長度(在前面的表格中用L表示),而不是取決于類型的最大可能尺寸。例如,一個VARCHAR(10)列能保存最大長度為10個字符的一個字符串,實際的存儲需要是字符串的長度(L),加上1個字節以記錄字符串的長度。對于字符串'abcd',L是4而存儲要求是5個字節。

BLOB和TEXT類型需要1,2,3或4個字節來記錄列值的長度,這取決于類型的最大可能長度。

如果一個表包括任何變長的列類型,記錄格式將也是變長的。注意,當一個表被創建時,MySQL可能在某些條件下將一個列從一個變長類型改變為一個定長類型或相反。見7.7.1 隱式列指定變化。

一個ENUM對象的大小由不同枚舉值的數量決定。1字節被用于枚舉,最大到255個可能的值;2個字節用于枚舉,最大到65535 值。

一個SET對象的大小由不同的集合成員的數量決定。如果集合大小是N,對象占據(N+7)/8個字節,四舍五入為1,2,3,4或8 個字節。一個SET最多能有64個成員。
7.3.5 數字類型

MySQL支持所有的ANSI/ISO SQL92的數字類型。這些類型包括准確數字的數據類型(NUMERIC, DECIMAL, INTEGER,和SMALLINT),也包括近似數字的數據類型(FLOAT, REAL,和DOUBLE PRECISION)。關鍵詞INT是INTEGER的一個同義詞,而關鍵詞DEC是DECIMAL一個同義詞。

NUMERIC和DECIMAL類型被MySQL實現為同樣的類型,這在SQL92標准允許。他們被用于保存值,該值的准確精度是極其重要的值,例如與金錢有關的數據。當聲明一個類是這些類型之一時,精度和規模的能被(並且通常是)指定;例如:

salary DECIMAL(9,2)

在這個例子中,9(precision)代表將被用于存儲值的總的小數位數,而2(scale)代表將被用于存儲小數點後的位數。因此,在這種情況下,能被存儲在salary列中的值的範圍是從-9999999.99到9999999.99。在ANSI/ISO SQL92中,句法DECIMAL(p)等價于DECIMAL(p,0)。同樣,句法DECIMAL等價于DECIMAL(p,0),這里實現被允許決定值p。MySQL當前不支持DECIMAL/NUMERIC數據類型的這些變種形式的任一種。這一般說來不是一個嚴重的問題,因為這些類型的主要益處得自于明顯地控制精度和規模的能力。

DECIMAL和NUMERIC值作為字符串存儲,而不是作為二進制浮點數,以便保存那些值的小數精度。一個字符用于值的每一位、小數點(如果scale>0)和“-”符號(對于負值)。如果scale是0,DECIMAL和NUMERIC值不包含小數點或小數部分。

DECIMAL和NUMERIC值得最大的範圍與DOUBLE一樣,但是對于一個給定的DECIMAL或NUMERIC列,實際的範圍可由制由給定列的precision或scale限制。當這樣的列賦給了小數點後面的位超過指定scale所允許的位的值,該值根據scale四舍五入。當一個DECIMAL或NUMERIC列被賦給了其大小超過指定(或缺省的)precision和scale隱含的範圍的值,MySQL存儲表示那個範圍的相應的端點值。

作為對ANSI/ISO SQL92標准的擴展,MySQL也支持上表所列的整型類型TINYINT、MEDIUMINT和BIGINT。另一個擴展是MySQL支持可選地指定一個整型值顯示的寬度,用括號跟在基本關鍵詞之後(例如,INT(4))。這個可選的寬度指定被用于其寬度小于列指定寬度的值得左填補顯示,但是不限制能在列中被存儲的值的範圍,也不限制值將被顯示的位數,其寬度超過列指定的寬度。當與可選的擴展屬性ZEROFILL一起使用時,缺省的空格填補用零代替。例如,對于聲明為INT(5) ZEROFILL的列,一個為4的值作為00004被檢索。注意,如果你在一個整型列存儲超過顯示寬度的更大值,當MySQL對于某些複雜的聯結(join)生成臨時表時,你可能會遇到問題,因為在這些情況下,MySQL相信數據確實適合原來的列寬度。

所有的整型類型可以有一個可選(非標准的)屬性UNSIGNED。當你想要在列中僅允許正數並且你需要一個稍大一點的列範圍,可以使用無符號值。

FLOAT類型被用來標示近似數字的數據類型。ANSI/ISO SQL92標准允許一個可選的精度說明(但不是指數的範圍),跟在關鍵詞FLOAT後面的括號內位數。MySQL實現也支持這個可選的精度說明。當關鍵詞FLOAT被用于一個列類型而沒有精度說明時,MySQL使用4個字節存儲值。一個變種的句法也被支持,在FLOAT關鍵詞後面的括號給出2個數字。用這個選項,第一個數字繼續表示在字節計算的值存儲需求,而第二個數字指定要被存儲的和顯示跟隨小數點後的位數(就象DECIMAL和NUMERIC)。當MySQL要求為這樣一個列,一個小數點後的小數位超過列指定的值,存儲值時,該值被四舍五入,去掉額外的位。

REAL和DOUBLE PRECISION類型不接受精度說明。作為對 ANSI/ISO SQL92 標准的擴展,MySQL識別出DOUBLE作為DOUBLE PRECISION類型的一個同義詞。與REAL精度比用于DOUBLE PRECISION的更小的標准要求相反,MySQL實現了兩種,作為8字節雙精度浮點值(當運行不是“Ansi模式”時)。為了最大的移植性,近似數字的數據值的存儲所需代碼應該使用沒有精度或小數位數說明的FLOAT或DOUBLE PRECISION。

當要求在數字的列存儲超出該列類型允許的範圍的值時,MySQL剪切該值到範圍內的正確端點值並且存儲剪切後的結果值。

例如,一個INT列的範圍是-2147483648到2147483647。如果你試圖插入-9999999999到一個INT列中,值被剪切到範圍的低部端點,並存儲-2147483648。同樣,如果你試圖插入9999999999,2147483647被存儲。

如果INT列是UNSIGNED,列的範圍的大小是相同的,但是它的端點移到了0和4294967295。如果你試圖存儲-9999999999和9999999999,在列被存儲的值變為0和4294967296。

對于ALTER TABLE、LOAD DATA INFILE、UPDATE和多行INSERT語句,由于剪切所發生的變換作為“警告”被報告。
7.3.6 日期和時間類型

日期和時間類型是DATETIME、DATE、TIMESTAMP、TIME和YEAR。這些的每一個都有合法值的一個範圍,而“零”當你指定確實不合法的值時被使用。注意,MySQL允許你存儲某個“不嚴格地”合法的日期值,例如1999-11-31,原因我們認為它是應用程序的責任來處理日期檢查,而不是SQL服務器。為了使日期檢查更“快”,MySQL僅檢查月份在0-12的範圍,天在0-31的範圍。上述範圍這樣被定義是因為MySQL允許你在一個DATE或DATETIME列中存儲日期,這里的天或月是零。這對存儲你不知道准確的日期的一個生日的應用程序來說是極其有用的,在這種情況下,你簡單地存儲日期象1999-00-00或1999-01-00。(當然你不能期望從函數如DATE_SUB()或DATE_ADD()得到類似以這些日期的正確值)。

當用日期和時間工作時,這里是的一些要記住的一般考慮:

    * MySQL對一個給定的日期或時間類型以標准的格式檢索,但是它試圖為你提供的值解釋成許多格式(例如,當你指定一個值被賦給或與比較一個日期或時間類型時),但是只支持有在下列小節描述的格式。期望你提供合法的值,並且如果你以其他格式使用這些值,可能造成無法預料的結果。
    * 盡管MySQL試圖以多種格式解釋值,但它總是期望日期值的年份部分在最左面,日期必須以年-月-日的順序給出(例如,'98-09-04'),而不是以其他地方常用的月-日-年或日-月-年的次序(例如,'09-04-98'、'04-09-98')。
    * 如果一個值在數字的上下文環境中被使用,MySQL自動變換一個日期或時間類型值到一個數字,反過來也如此。
    * 當MySQL遇到一個日期或時間類型的值超出範圍或對給類型不合法(見本節的開始)時,它將該類型的值變換到“零”值。(例外的是超出範圍的TIME值被剪切為適當的TIME範圍端點值。)下表顯示對每種類型的“零”值的格式:
      列類型         “零”值
      DATETIME         '0000-00-00 00:00:00'
      DATE         '0000-00-00'
      TIMESTAMP         00000000000000(長度取決于顯示尺寸)
      TIME         '00:00:00'
      YEAR         0000
    * “零”值是特殊的,但是你能使用在表中顯示的值來明顯地存儲或引用他們。你也可以使用值'0'或0做到, 這更容易寫。
    * 在MyODBC 2.50.12和以上版本中,由MyODBC使用的“零”日期或時間值被自動變換到NULL,因為ODBC不能處理這樣的值。

7.3.6.1 Y2K問題和日期類型

MySQL本身Y2K安全的(見1.6 2000年一致性),但是呈交給MySQL的輸入值可能不是。一個包含2位年份值的任何輸入是由二義性的,因為世紀是未知的。這樣的值必須被解釋成4位形式,因為MySQL內部使用4位存儲年份。

對于DATETIME, DATE, TIMESTAMP和YEAR類型,MySQL使用下列規則的解釋二義性的年份值:

    * 在範圍00-69的年值被變換到2000-2069。
    * 在範圍70-99的年值被變換到1970-1999。

記得這些規則僅僅提供對于你數據的含義的合理猜測。如果MySQL使用的啟發規則不產生正確的值,你應該提供無二義的包含4位年值的輸入。
7.3.6.2 DATETIME, DATE和TIMESTAMP類型

DATETIME, DATE和TIMESTAMP類型是相關的。本節描述他們的特征,他們是如何類似的而又不同的。

DATETIME類型用在你需要同時包含日期和時間信息的值時。MySQL檢索並且以'YYYY-MM-DD HH:MM:SS'格式顯示DATETIME值,支持的範圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。(“支持”意味著盡管更早的值可能工作,但不能保証他們可以。)

DATE類型用在你僅需要日期值時,沒有時間部分。MySQL檢索並且以'YYYY-MM-DD'格式顯示DATE值,支持的範圍是'1000-01-01'到'9999-12-31'。

TIMESTAMP列類型提供一種類型,你可以使用它自動地用當前的日期和時間標記INSERT或UPDATE的操作。如果你有多個TIMESTAMP列,只有第一個自動更新。

自動更新第一個TIMESTAMP列在下列任何條件下發生:

    * 列沒有明確地在一個INSERT或LOAD DATA INFILE語句中指定。
    * 列沒有明確地在一個UPDATE語句中指定且一些另外的列改變值。(注意一個UPDATE設置一個列為它已經有的值,這將不引起TIMESTAMP列被更新,因為如果你設置一個列為它當前的值,MySQL為了效率而忽略更改。)
    * 你明確地設定TIMESTAMP列為NULL.

除第一個以外的TIMESTAMP列也可以設置到當前的日期和時間,只要將列設為NULL,或NOW()。

通過明確地設置希望的值,你可以設置任何TIMESTAMP列為不同于當前日期和時間的值,即使對第一個TIMESTAMP列也是這樣。例如,如果,當你創建一個行時,你想要一個TIMESTAMP被設置到當前的日期和時間,但在以後無論何時行被更新時都不改變,你可以使用這個屬性:

    * 讓MySQL在行被創建時設置列,這將初始化它為當前的日期和時間。
    * 當你執行隨後的對該行中其他列的更改時,明確設定TIMESTAMP列為它的當前值。

另一方面,你可能發現,當行被創建並且遠離隨後的更改時,很容易用一個你用NOW()初始化的DATETIME列。

TIMESTAMP值可以從1970的某時的開始一直到2037年,精度為一秒,其值作為數字顯示。

在MySQL檢索並且顯示TIMESTAMP值取決于顯示尺寸的格式如下表。“完整”TIMESTAMP格式是14位,但是TIMESTAMP列可以用更短的顯示尺寸創造:
列類型         顯示格式
TIMESTAMP(14)         YYYYMMDDHHMMSS
TIMESTAMP(12)         YYMMDDHHMMSS
TIMESTAMP(10)         YYMMDDHHMM
TIMESTAMP(8)         YYYYMMDD
TIMESTAMP(6)         YYMMDD
TIMESTAMP(4)         YYMM
TIMESTAMP(2)         YY

所有的TIMESTAMP列都有同樣的存儲大小,不考慮顯示尺寸。最常見的顯示尺寸是6、8、12、和14。你可以在表創建時間指定一個任意的顯示尺寸,但是值0或比14大被強制到14。在從1~13範圍的奇數值尺寸被強制為下一個更大的偶數。

使用一個常用的格式集的任何一個,你可以指定DATETIME、DATE和TIMESTAMP值:

    * 'YYYY-MM-DD HH:MM:SS'或'YY-MM-DD HH:MM:SS'格式的一個字符串。允許一種“寬松”的語法--任何標點可用作在日期部分和時間部分之間的分隔符。例如,'98-12-31 11:30:45'、'98.12.31 11+30+45'、'98/12/31 11*30*45'和'98@12@31 11^30^45'是等價的。
    * 'YYYY-MM-DD'或'YY-MM-DD'格式的一個字符串。允許一種“寬松”的語法。例如,'98-12-31', '98.12.31', '98/12/31'和'98@12@31'是等價的。
    * 'YYYYMMDDHHMMSS'或'YYMMDDHHMMSS'格式的沒有任何分隔符的一個字符串,例如,'19970523091528'和'970523091528'被解釋為'1997-05-23 09:15:28',但是'971122459015'是不合法的(它有毫無意義的分鐘部分)且變成'0000-00-00 00:00:00'。
    * 'YYYYMMDD'或'YYMMDD'格式的沒有任何分隔符的一個字符串,如果字符串認為是一個日期。例如,'19970523'和'970523'被解釋作為'1997-05-23',但是'971332'是不合法的( 它有無意義的月和天部分)且變成'0000-00-00'。
    * YYYYMMDDHHMMSS或YYMMDDHHMMSS格式的一個數字,如果數字認為是一個日期。例如,19830905132800和830905132800被解釋作為'1983-09-05 13:28:00'。
    * YYYYMMDD或YYMMDD格式的一個數字,如果數字認為是一個日期。例如,19830905和830905被解釋作為'1983-09-05'。
    * 一個返回值可以在一個DATETIME, DATE或TIMESTAMP上下文環境中接受的函數,例如NOW()或CURRENT_DATE。

不合法DATETIME, DATE或TIMESTAMP值被變換到適當類型的“零”值('0000-00-00 00:00:00', '0000-00-00'或00000000000000)。

對于包括的日期部分分隔符的指定為字符串的值,不必要為小于10的月或天的值指定2位數字,'1979-6-9'與'1979-06-09'是一樣的。同樣, 對于包括的時間部分分隔符的指定為字符串的值,不必為小于10的小時、月或秒指定2位數字,'1979-10-30 1:2:3'與'1979-10-30 01:02:03'是一樣的。

指定為數字應該是6、8、12或14位長。如果數字是8或14位長,它被假定以YYYYMMDD或YYYYMMDDHHMMSS格式並且年份由頭4位數字給出。如果數字是6或12位長,它被假定是以YYMMDD或YYMMDDHHMMSS格式且年份由頭2位數字給出。不是這些長度之一的數字通過填補前頭的零到最接近的長度來解釋。

指定為無分隔符的字符串用它們給定的長度來解釋。如果字符串長度是8或14個字符,年份被假定頭4個字符給出,否則年份被假定由頭2個字符給出。對于字符串中呈現的多個部分,字符串從左到右邊被解釋,以找出年、月、日、小時、分鐘和秒值,這意味著,你不應該使用少于 6 個字符的字符串。例如,如果你指定'9903',認為將代表1999年3月,你會發現MySQL把一個“零”日期插入到你的表中,這是因為年份和月份值99和03,但是日期部分丟失(零),因此該值不是一個合法的日期。

TIMESTAMP列使用被指定的值的完整精度的存儲合法的值,不考慮顯示大小。這有幾個含意:

    * 總是指定年,月,和日,即使你的列類型是TIMESTAMP(4)或TIMESTAMP(2)。否則,值將不是一個合法的日期並且0將被存儲。
    * 如果你使用ALTER TABLE拓寬一個狹窄的TIMESTAMP列,以前被“隱蔽”的信息將被顯示。
    * 同樣,縮小一個TIMESTAMP列不會導致信息失去,除了感覺上值在顯示時,較少的信息被顯示出。
    * 盡管TIMESTAMP值被存儲為完整精度,直接操作存儲值的唯一函數是UNIX_TIMESTAMP(),其他函數操作在格式化了的檢索的值上,這意味著你不能使用函數例如HOUR()或SECOND(),除非TIMESTAMP值的相關部分被包含在格式化的值中。例如,一個TIMESTAMP列的HH部分部被顯示,除非顯示大小至少是10,因此在更短的TIMESTAMP值上試試使用HOUR()產生一個無意義的結果。

在某種程度上,你可以把一種日期類型的值賦給一個不同的日期類型的對象。然而,這可能值有一些改變或信息的損失:

    * 如果你將一個DATE值賦給一個DATETIME或TIMESTAMP對象,結果值的時間部分被設置為'00:00:00',因為DATE值不包含時間信息。
    * 如果你將一個DATETIME或TIMESTAMP值賦給一個DATE對象,結果值的時間部分被刪除,因為DATE類型不存儲時間信息。
    * 記住,盡管DATETIME, DATE和TIMESTAMP值全都可以用同樣的格式集來指定,但所有類型不都有同樣的值範圍。例如,TIMESTAMP值不能比1970早或比2037網晚,這意味著,一個日期例如'1968-01-01',當作為一個DATETIME或DATE值合法時,它不是一個正確TIMESTAMP值,並且如果賦值給這樣一個對象,它將被變換到0。

當指定日期值時,當心某些缺陷:

    * 允許作為字符串指定值的寬松格式能被欺騙。例如,值例如'10:11:12'可能看起來像時間值,因為“:”分隔符,但是如果在一個日期中使用,上下文將作為年份被解釋成'2010-11-12'。值'10:45:15'將被變換到'0000-00-00',因為'45'不是一個合法的月份。
    * 以2位數字指定的年值是模糊的,因為世紀是未知的。MySQL使用下列規則解釋2位年值:
          o 在00-69範圍的年值被變換到2000-2069。
          o 在範70-99圍的年值被變換到1970-1999。

7.3.6.3 TIME類型

MySQL檢索並以'HH:MM:SS'格式顯示TIME值(或對大小時值,'HHH:MM:SS'格式)。TIME值的範圍可以從'-838:59:59'到'838:59:59'。小時部分可能很大的的原因是TIME類型不僅可以被使用在表示一天的時間(它必須是不到24個小時),而且用在表示在2個事件之間經過的時間或時間間隔(它可以是比24個小時大些,或甚至是負值)。

你能用多中格式指定TIME值:

    * 作為'HH:MM:SS'格式的一個字符串。“寬松”的語法被允許--任何標點符號可用作時間部分的分隔符,例如,'10:11:12'和'10.11.12'是等價的。
    * 作為沒有分隔符的'HHMMSS'格式的一個字符串,如果它作為一個時間解釋。例如,'101112'被理解為'10:11:12',但是'109712'是不合法的(它有無意義的分鐘部分)並變成'00:00:00'。
    * 作為HHMMSS格式的一個數字,如果它能解釋為一個時間。例如,101112被理解為'10:11:12'。
    * 返回值可在一個TIME上下文接受的函數,例如CURRENT_TIME。

對于作為包括一個時間分隔符的字符串被指定的TIME值,不必為小于10的小時、分鐘或秒值指定2位數字,'8:3:2'與'08:03:02'是一樣的。

將“短的”TIME值賦值給一個TIME行列是要格外小心。MySQL使用最右位代表秒的假設來解釋值。(MySQL將TIME值解釋為經過的時間,而非作為一天的時間 )例如,你可能想到'11:12'、'1112'和1112意味著'11:12:00'(11點12分),但是MySQL解釋他們為'00:11:12'(11分12秒)。同樣,'12'和12被解釋為'00:00:12'。

但是超出TIME範圍之外的值是樣合法的,它被剪切到範圍適當的端點值。例如,'-850:00:00'和'850:00:00'被變換到'-838:59:59'和'838:59:59'。

不合法的TIME值被變換到'00:00:00'。注意,既然'00:00:00'本身是一個合法的TIME值,沒有其他方法區分表中存儲的一個'00:00:00'值,原來的值是否被指定為'00:00:00'或它是否是不合法的。
7.3.6.4 YEAR類型

YEAR類型是一個 1 字節類型用于表示年份。

MySQL檢索並且以YYYY格式顯示YEAR值,其範圍是1901到2155。

你能用多種格式指定YEAR值:

    * 作為在'1901'到'2155'範圍的一個4位字符串。
    * 作為在1901到2155範圍的一個4位數字。
    * 作為在'00'到'99'範圍的一個2位字符串.在'00'到'69'和'70'到'99'範圍的值被變換到在2000到2069範圍和1970到1999的YEAR值。
    * 作為在1到99範圍的一個2位數字。在範圍1到69和70到99的值被變換到在範圍2001到2069和1970到1999的YEAR的值。注意對于2位數字的範圍略微不同于2位數字字符串的範圍,因為你不能直接指定零作為一個數字並且把它解釋為2000。你必須作為一個字符串'0'或'00'指定它,它將被解釋為0000。
    * 其返回值可在一個YEAR上下文環境中接受的函數,例如NOW()。

不合法YEAR值被變換到0000。
7.3.7 字符串類型

字符串類型是CHAR、VARCHAR、BLOB、TEXT、ENUM和SET。
7.3.7.1 CHAR和VARCHAR類型

CHAR和VARCHAR類型是類似的,但是在他們被存儲和檢索的方式不同。

一個CHAR列的長度被修正為在你創造表時你所聲明的長度。長度可以是1和255之間的任何值。(在MySQL 3.23中,CHAR長度可以是0~255。) 當CHAR值被存儲時,他們被用空格在右邊填補到指定的長度。當CHAR值被檢索時,拖後的空格被刪去。

在VARCHAR列中的值是變長字符串。你可以聲明一個VARCHAR列是在1和255之間的任何長度,就像對CHAR列。然而,與CHAR相反,VARCHAR值只存儲所需的字符,外加一個字節記錄長度,值不被填補;相反,當值被存儲時,拖後的空格被刪去。(這個空格刪除不同于ANSI SQL規範。)

如果你把一個超過列最大長度的值賦給一個CHAR或VARCHAR列,值被截斷以適合它。

下表顯示了兩種類型的列的不同,通過演示存儲變長字符串值到CHAR(4)和VARCHAR(4)列:
值         CHAR(4)         存儲需求         VARCHAR(4)         存儲需求
''         ' '         4 個字節         ''         1 字節
'ab'         'ab '         4 個字節         'ab'         3 個字節
'abcd'         'abcd'         4 個字節         'abcd'         5 個字節
'abcdefgh'         'abcd'         4 個字節         'abcd'         5 個字節

從CHAR(4)和VARCHAR(4)列檢索的值在每種情況下都是一樣的,因為拖後的空格從檢索的CHAR列上被刪除。

在CHAR和VARCHAR列中存儲和比較值是以大小寫不區分的方式進行的,除非當桌子被創建時,BINARY屬性被指定。BINARY屬性意味著該列的值根據MySQL服務器正在運行的機器的ASCII順序以大小寫區分的方式存儲和比較。

BINARY屬性是“粘性”的。這意味著,如果標記了BINARY的列用于一個表達式中,整個的表達式作為一個BINARY值被比較。

MySQL在表創建時可以隱含地改變一個CHAR或VARCHAR列的類型。見7.7.1 隱含的的列說明改變。
7.3.7.2 BLOB和TEXT類型

一個BLOB是一個能保存可變數量的數據的二進制的大對象。4個BLOB類型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB僅僅在他們能保存值的最大長度方面有所不同。見7.3.1 列類型存儲需求。

4個TEXT類型TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT對應于4個BLOB類型,並且有同樣的最大長度和存儲需求。在BLOB和TEXT類型之間的唯一差別是對BLOB值的排序和比較以大小寫敏感方式執行,而對TEXT值是大小寫不敏感的。換句話說,一個TEXT是一個大小寫不敏感的BLOB。

如果你把一個超過列類型最大長度的值賦給一個BLOB或TEXT列,值被截斷以適合它。

在大多數方面,你可以認為一個TEXT行列是你所希望大的一個VARCHAR列。同樣,你可以認為一個BLOB列是一個VARCHAR BINARY列。差別是:

    * 用MySQL版本3.23.2和更新,你能在BLOB和TEXT列上索引。更舊的MySQL版本不支持這個。
    * 當值被存儲時,對BLOB和TEXT列沒有拖後空格的刪除,因為對VARCHAR列有刪除。
    * BLOB和TEXT列不能有DEFAULT值。

MyODBC定義BLOB為LONGVARBINARY,TEXT值為LONGVARCHAR。

因為BLOB和TEXT值可以是非常長的,當使用他們時,你可能遇到一些限制:

    * 如果你想要在一個BLOB或TEXT列上使用GROUP BY或ORDER BY,你必須將列值變換成一個定長對象。這樣做的標准方法是用SUBSTRING函數。例如:

      mysql> select comment from tbl_name,substring(comment,20) as substr ORDER BY substr;

      如果你不這樣做,在排序時,只有列的首max_sort_length個字節被使用,缺省的max_sort_length是1024;這個值能在啟動mysqld服務器時使用-O選擇改變。你可以在包含BLOB或TEXT值得一個表達式上分組(group),通過指定列的位置或使用一個別名:

      mysql> select id,substring(blob_col,1,100) from tbl_name
                 GROUP BY 2;
      mysql> select id,substring(blob_col,1,100) as b from tbl_name
                 GROUP BY b;

    * 一個BLOB或TEXT對象的最大尺寸由其類型決定,但是你能在客戶與服務器之間是實際傳輸的最大值由可用的內存數量和通訊緩衝區的大小來決定。你能改變消息緩衝區大小,但是你必須在服務器和客戶兩端做。見10.2.3 調節服務器參數。

注意,每個BLOB或TEXT值內部由一個獨立分配的對象表示。這與所有的其他列類型相反,它們是在打開表時,按列被分配一次存儲。
7.3.7.3 ENUM類型

一個ENUM是一個字符對象,其值通常從一個在表創建時明確被列舉的允許值的一張表中選擇。

在下列的某個情形下,值也可以空字符串("")或NULL:

    * 如果你把一個無效值插入到一個ENUM(即,一個不在允許的值列表中的字符串),空字符串作為一個特殊錯誤的值被插入。
    * 如果一個ENUM被聲明為NULL,NULL也是列的合法值,並且缺省值是NULL。如果一個ENUM被聲明為NOT NULL,缺省值是允許值的列表的第一成員。

每枚舉值有一個編號:

    * 在列說明中來自允許成員值列表值用從1開始編號。
    * 空字符串錯誤值的編號值是0。這意味著,你能使用下列SELECT語句找出被賦給無效ENUM值的行:

      mysql> SELECT * FROM tbl_name WHERE enum_col=0;

    * NULL值的編號是NULL。

例如,指定為ENUM("one", "two", "three")的列可以有顯示在下面的值的任何一個。每個值的編號也被顯示:
值         編號
NULL         NULL
""         0
"one"         1
"two"         2
"three"         3

枚舉可以有最大65535個成員。

當你把值賦給一個ENUM列時,字母的大小寫是無關緊要的。然而,以後從列中檢索的值大小寫匹配在表創建時用來指定允許值的值的大小寫。

如果你在一個數字的上下文環境中檢索一個ENUM,列值的編號被返回。如果你存儲一個數字到一個ENUM中,數字被當作一個標號,並且存儲的值是該編號的枚舉成員。

ENUM值根據列說明列舉的枚舉成員的次序被排序。(換句話說,ENUM值根據他們的編號數字被排序) 例如,對ENUM("a", "b"),"a"排在"b"前面,但是對ENUM("b", "a"),"b"排在"a"前面。空字符串排序非空字符串之前,並且NULL排在所有其他枚舉值之前。

如果你想要得到一個ENUM列的所有可能的值,你應該使用:SHOW COLUMNS FROM table_name LIKE enum_column_name並且分析在第二列的ENUM定義。
7.3.7.4 SET類型

一個SET是可以有零或多個值的一個字符串對象,其每一個必須從表創建造被指定了的允許值的一張列表中被選擇。由多個集合成員組成的SET列通過由由逗號分隔(“,”)的成員被指定,其推論是該SET成員值不能包含逗號本身。

例如, 一個指定為SET("one", "two") NOT NULL的列可以有這些值的任何一個:

""
"one"
"two"
"one,two"

一個SET能有最多64個不同的成員。

MySQL用數字值存儲SET值,存儲值的低階位對應于第一個集合成員。如果你在數字上下文中檢索一個SET值,檢索的值把位設置位對應組成列值的集合成員。如果一個數字被存儲進一個SET列,在數字的二進制表示中設置的位決定了在列中的集合成員。假定一個列被指定為SET("a","b","c","d"),那麼成員有下列位值:
SET 成員         十進制的值         二進制的值
a         1         0001
b         2         0010
c         4         0100
d         8         1000

如果你給該列賦值9,即二進制的1001,這樣第一個和第四個SET值成員"a"和"d"被選擇並且結果值是"a,d"。

對于包含超過一個SET成員的值,當你插入值時,無所謂以什麼順序列舉值,也無所謂給定的值列舉了多少次。當以後檢索值時,在值中的每個成員將出現一次,根據他們在表創建時被指定的順序列出成員。例如,如果列指定為SET("a","b","c","d"),那麼"a,d"、"d,a"和"d,a,a,d,d"在檢索時將均作為"a,d"出現。

SET值以數字次序被排序。NULL指排在非NULL SET值之前。

通常,你使用LIKE操作符或FIND_IN_SET()函數執行在一個SET上的一個SELECT:

mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;

但是下列也會工作:

mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
mysql> SELECT * FROM tbl_name WHERE set_col & 1;

這些語句的第一個語句尋找一個精確的匹配。第二個尋找包含第一個集合成員的值。

如果你想要得到一個SET列的所有可能的值,你應該使用:SHOW COLUMNS FROM table_name LIKE set_column_name並且分析在第二列的SET定義。
7.3.8 為列選擇正確的類型

為了最有效地使用存儲空間,試著在所有的情況下使用最精確的類型。例如,如果一個整數列被用于在之間1和99999的值, MEDIUMINT UNSIGNED是最好的類型。

貨幣值的精確表示是一個常見的問題。在MySQL,你應該使用DECIMAL類型,它作為一個字符串被存儲,不會發生精確性的損失。如果精確性不是太重要,DOUBLE類型也是足夠好的。

對高精度,你總是能變換到以一個BIGINT存儲的定點類型。這允許你用整數做所有的計算,並且僅在必要時將結果轉換回浮點值。見10.6 選擇一個表類型。
7.3.9 列索引

所有的MySQL列類型能被索引。在相關的列上的使用索引是改進SELECT操作性能的最好方法。

一個表最多可有16個索引。最大索引長度是256個字節,盡管這可以在編譯MySQL時被改變。

對于CHAR和VARCHAR列,你可以索引列的前綴。這更快並且比索引整個列需要較少的磁盤空間。在CREATE TABLE語句中索引列前綴的語法看起來像這樣:

KEY index_name (col_name(length))

下面的例子為name列的頭10個字符創建一個索引:

mysql> CREATE TABLE test (
           name CHAR(200) NOT NULL,
           KEY index_name (name(10)));

對于BLOB和TEXT列,你必須索引列的前綴,你不能索引列的全部。
7.3.10 多列索引

MySQL能在多個列上創建索引。一個索引可以由最多15個列組成。(在CHAR和VARCHAR列上,你也可以使用列的前綴作為一個索引的部分)。

一個多重列索引可以認為是包含通過合並(concatenate)索引列值創建的值的一個排序數組。

當你為在一個WHERE子句索引的第一列指定已知的數量時,MySQL以這種方式使用多重列索引使得查詢非常快速,即使你不為其他列指定值。

假定一張表使用下列說明創建:

mysql> CREATE TABLE test (
           id INT NOT NULL,
           last_name CHAR(30) NOT NULL,
           first_name CHAR(30) NOT NULL,
           PRIMARY KEY (id),
           INDEX name (last_name,first_name));

那麼索引name是一個在last_name和first_name上的索引,這個索引將被用于在last_name或last_name和first_name的一個已知範圍內指定值的查詢,因此,name索引將使用在下列查詢中:

mysql> SELECT * FROM test WHERE last_name="Widenius";

mysql> SELECT * FROM test WHERE last_name="Widenius"
                          AND first_name="Michael";

mysql> SELECT * FROM test WHERE last_name="Widenius"
                          AND (first_name="Michael" OR first_name="Monty");

mysql> SELECT * FROM test WHERE last_name="Widenius"
                          AND first_name >="M" AND first_name < "N";

然而,name索引將不用在下列詢問中:

mysql> SELECT * FROM test WHERE first_name="Michael";

mysql> SELECT * FROM test WHERE last_name="Widenius"
                          OR first_name="Michael";

關于MySQL使用索引改進性能的方式的更多的信息,見10.4 使用MySQL索引。
7.3.11 使用來自其他數據庫引擎的列類型

為了跟容易地使用為其他供應商的SQL實現編寫的代碼,下表顯示了MySQL映射的列類型。這些映射使得從其他數據庫引擎移動表定義到MySQL更容易:
其他供應商類型         MySQL類型
BINARY(NUM)         CHAR(NUM) BINARY
CHAR VARYING(NUM)         VARCHAR(NUM)
FLOAT4         FLOAT
FLOAT8         DOUBLE
INT1         TINYINT
INT2         SMALLINT
INT3         MEDIUMINT
INT4         INT
INT8         BIGINT
LONG VARBINARY         MEDIUMBLOB
LONG VARCHAR         MEDIUMTEXT
MIDDLEINT         MEDIUMINT
VARBINARY(NUM)         VARCHAR(NUM) BINARY

列類型映射發生在表創建時。如果你用其他供應商使用的類型創建表,那麼發出一個DESCRIBE tbl_name語句,MySQL使用等價的MySQL類型報告表結構。
7.4 用在SELECT和WHERE子句中的函數

在一個SQL語句中的select_expression或where_definition可由使用下面描述的函數的任何表達式組成。

包含NULL的一個表達式總是產生一個NULL值,否則除非表達式所包含的操作符和函數在文檔中說明。

注意:在一個函數名和跟隨它的括號之間不許沒有空格。這幫助MySQL分析器區分函數調用和具有相同名字的對表或列的引用,盡管允許在參數周圍有空格。

為了簡潔,例子以縮寫形式顯示從mysql程序輸出。因此:

mysql> select MOD(29,9);
1 rows in set (0.00 sec)

+-----------+
| mod(29,9) |
+-----------+
|         2 |
+-----------+

被顯示為這樣:

mysql> select MOD(29,9);
        -> 2

7.4.1 分組函數

( ... )
    括號。使用它們來強制在一個表達式的計算順序。

    mysql> select 1+2*3;
            -> 7
    mysql> select (1+2)*3;
            -> 9

7.4.2 常用的算術操作

一般的算術操作符是可用的。注意在-、+和*情況下,如果兩個參數是整數,結果用BIGINT(64位)精度計算!  

+
    加法

    mysql> select 3+5;
            -> 8

-
    減法

    mysql> select 3-5;
            -> -2  

*
    乘法

    mysql> select 3*5;
            -> 15
    mysql> select 18014398509481984*18014398509481984.0;
            -> 324518553658426726783156020576256.0
    mysql> select 18014398509481984*18014398509481984;
            -> 0


    最後一個表達式的結果是不正確的,因為整數乘積的結果超過用BIGINT計算的64位範圍。
/
    除法

    mysql> select 3/5;
            -> 0.60

    被零除產生一個NULL結果:

    mysql> select 102/(1-1);
            -> NULL

    一個除法用BIGINT算術計算,只要在它的結果被轉換到一個整數的上下文中執行!

7.4.3 位函數

MySQL為位操作使用BIGINT(64位)算法,因此這些操作符有最大64位的一個範圍。

|
    位或

    mysql> select 29 | 15;
            -> 31

&
    位與

    mysql> select 29 & 15;
            -> 13
     

<<
    左移位一個長(BIGINT)數字。

    mysql> select 1 << 2
            -> 4
     

>>
    右移位一個長(BIGINT)數字。

    mysql> select 4 >> 2
            -> 1

~
    顛倒所有的位。

    mysql> select 5 & ~1
            -> 4
     

BIT_COUNT(N)
    返回在參數N設定的位的數量。

    mysql> select BIT_COUNT(29);
            -> 4
      

7.4.4 邏輯運算

所有的邏輯函數返回1(TRUE)或0(FALSE)。

NOT
!
    邏輯非。如果參數是0,返回1,否則返回0。例外: NOT NULL返回NULL。

    mysql> select NOT 1;
            -> 0
    mysql> select NOT NULL;
            -> NULL
    mysql> select ! (1+1);
            -> 0
    mysql> select ! 1+1;
            -> 1

    最後的例子返回1,因為表達式作為(!1)+1計算。   

OR
     
||
    邏輯或。如果任何一個參數不是0並且不NULL,返回1。

    mysql> select 1 || 0;
            -> 1
    mysql> select 0 || 0;
            -> 0
    mysql> select 1 || NULL;
            -> 1
     

AND
     
&&
    邏輯與。如果任何一個參數是0或NULL,返回0,否則返回1。

    mysql> select 1 && NULL;
            -> 0
    mysql> select 1 && 0;
            -> 0
      

7.4.5 比較運算符

比較操作得出值1(TRUE)、0(FALSE)或NULL等結果。這些函數工作運用在數字和字符串上。當需要時,字符串自動地被變換到數字且數字到字符串(如在Perl)。

MySQL使用下列規則執行比較:

    * 如果一個或兩個參數是NULL,比較的結果是NULL,除了<=>操作符。
    * 如果在比較中操作的兩個參數是字符串,他們作為字符串被比較。
    * 如果兩個參數是整數,他們作為整數被比較。
    * 十六進制的值如果不與一個數字比較,則被當作二進制字符串。
    * 如果參數之一是一個TIMESTAMP或DATETIME列而其他參數是一個常數,在比較執行前,常數被轉換為一個時間標記。這樣做是為了對ODBC更友好。
    * 在所有其他的情況下,參數作為浮點(實數)數字被比較。

缺省地,字符串使用當前的字符集以大小寫敏感的方式進行(缺省為ISO-8859-1 Latin1,它對英語運用得很出色)。

下面的例子演示了對于比較操作字符串到數字的轉換:

mysql> SELECT 1 > '6x';
         -> 0
mysql> SELECT 7 > '6x';
         -> 1
mysql> SELECT 0 > 'x6';
         -> 0
mysql> SELECT 0 = 'x6';
         -> 1

=
    等于

    mysql> select 1 = 0;
            -> 0
    mysql> select '0' = 0;
            -> 1
    mysql> select '0.0' = 0;
            -> 1
    mysql> select '0.01' = 0;
            -> 0
    mysql> select '.01' = 0.01;
            -> 1
        

<>
     
!=
    不等于

    mysql> select '.01' <> '0.01';
            -> 1
    mysql> select .01 <> '0.01';
            -> 0
    mysql> select 'zapp' <> 'zappp';
            -> 1

<=
    小于或等于

    mysql> select 0.1 <= 2;
            -> 1
     

<
    小于

    mysql> select 2 <= 2;
            -> 1
      

>=
    大于或等于

    mysql> select 2 >= 2;
            -> 1

>
    大于

    mysql> select 2 > 2;
            -> 0

<=>
    安全等于Null

    mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
            -> 1 1 0
      

IS NULL
     
IS NOT NULL
    測試值是否是或不是NULL

    mysql> select 1 IS NULL, 0 IS NULL, NULL IS NULL:
            -> 0 0 1
    mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
     

expr BETWEEN min AND max
    如果expr對大于或等于min且expr是小于或等于max,BETWEEN返回1,否則它返回0。如果所有的參數類型是一樣得,這等價于表達式(min <= expr AND expr <= max)。第一個參數(expr)決定比較如何被執行。如果expr是一個大小寫不敏感的字符串表達式,進行一個大小寫不敏感的字符串比較。如果expr是一個大小寫敏感的字符串表達式,進行一個大小寫敏感的字符串比較。如果expr是一個整數表達式,進行整數比較。否則,進行一個浮點(實數)比較。

    mysql> select 1 BETWEEN 2 AND 3;
            -> 0
    mysql> select 'b' BETWEEN 'a' AND 'c';
            -> 1
    mysql> select 2 BETWEEN 2 AND '3';
            -> 1
    mysql> select 2 BETWEEN 2 AND 'x-3';
            -> 0

expr IN (value,...)
    如果expr是在IN表中的任何值,返回1,否則返回0。如果所有的值是常數,那麼所有的值根據expr類型被計算和排序,然後項目的搜索是用二進制的搜索完成。這意味著如果IN值表全部由常數組成,IN是很快的。如果expr是一個大小寫敏感的字符串表達式,字符串比較以大小寫敏感方式執行。

    mysql> select 2 IN (0,3,5,'wefwf');
            -> 0
    mysql> select 'wefwf' IN (0,3,5,'wefwf');
            -> 1

expr NOT IN (value,...)
    與NOT (expr IN (value,...))相同。
ISNULL(expr)
    如果expr是NULL,ISNULL()返回1,否則它返回0。

    mysql> select ISNULL(1+1);
            -> 0
    mysql> select ISNULL(1/0);
            -> 1

    注意,使用=的NULL的值比較總為假!
COALESCE(list)
    回來list中第一個非NULL的單元。

    mysql> select COALESCE(NULL,1);
            -> 1
    mysql> select COALESCE(NULL,NULL,NULL);
            -> NULL

INTERVAL(N,N1,N2,N3,...)
    如果N< N1,返回0,如果N< N2,返回1等等。所有的參數被當作整數。為了函數能正確地工作,它要求N1<N2<N3< ...<Nn。這是因為使用二進制搜索(很快)。

    mysql> select INTERVAL(23, 1, 15, 17, 30, 44, 200);
            -> 3
    mysql> select INTERVAL(10, 1, 10, 100, 1000);
            -> 2
    mysql> select INTERVAL(22, 23, 30, 44, 200);
            -> 0  

7.4.6 字符串比較函數

通常,如果在字符串比較中的任何表達式是區分大小寫的,比較以大小寫敏感的方式執行。

expr LIKE pat [ESCAPE 'escape-char']
    使用SQL的簡單的正規表達式比較的模式匹配。返回1(TRUE)或0(FALSE)。用LIKE,你可以在模式中使用下列2個通配符字符:
    %         匹配任何數目的字符,甚至零個字符
    _         精確匹配一個字符

    mysql> select 'David!' LIKE 'David_';
            -> 1
    mysql> select 'David!' LIKE '%D%v%';
            -> 1

    為了測試一個通配符的文字實例,用轉義字符的加在字符前面。如果你不指定ESCAPE字符,假定為“\”:
    \%         匹配一%字符
    \_         匹配一_字符

    mysql> select 'David!' LIKE 'David\_';
            -> 0
    mysql> select 'David_' LIKE 'David\_';
            -> 1

    為了指定一個不同的轉義字符,使用ESCAPE子句:

    mysql> select 'David_' LIKE 'David|_' ESCAPE '|';
            -> 1

    LIKE允許用在數字的表達式上!(這是MySQL對ANSI SQL LIKE的一個擴充。)

    mysql> select 10 LIKE '1%';
            -> 1

    注意:因為MySQL在字符串中使用C轉義語法(例如,“\n”),你必須在你的LIKE字符串中重複任何“\”。例如,為了查找“\n”,指定它為“ \\n”,為了查找“\”,指定它為“\\\\”(反斜線被分析器剝去一次,另一次是在模式匹配完成時,留下一條單獨的反斜線被匹配)。
expr NOT LIKE pat [ESCAPE 'escape-char']
    與NOT (expr LIKE pat [ESCAPE 'escape-char'])相同。
expr REGEXP pat
     
expr RLIKE pat
    執行一個字符串表達式expr對一個模式pat的模式匹配。模式可以是一個擴充的正則表達式。見MySQL 正則表達式句法的 H 描述.如果expr匹配pat,返回1,否則返回0。RLIKE是REGEXP的一個同義詞,提供了與mSQL的兼容性。注意:因為MySQL在字符串中使用C轉義語法(例如,“\n”), 你必須在你的REGEXP字符串重複任何“\”。在MySQL3.23.4中,REGEXP對于正常的(不是二進制)字符串是忽略大小寫。

    mysql> select 'Monty!' REGEXP 'm%y%%';
            -> 0
    mysql> select 'Monty!' REGEXP '.*';
            -> 1
    mysql> select 'new*\n*line' REGEXP 'new\\*.\\*line';
            -> 1
    mysql> select "a" REGEXP "A", "a" REGEXP BINARY "A";
            -> 1  0

    當決定一個字符的類型時,REGEXP和RLIKE使用當前的字符集(缺省為ISO-8859-1 Latin1)。
expr NOT REGEXP pat
     
expr NOT RLIKE pat
    與NOT (expr REGEXP pat)相同。
STRCMP(expr1,expr2)
    如果字符串相同,STRCMP()回來0,如果第一參數根據當前的排序次序小于第二個,返回-1,否則返回1。

    mysql> select STRCMP('text', 'text2');
            -> -1
    mysql> select STRCMP('text2', 'text');
            -> 1
    mysql> select STRCMP('text', 'text');
            -> 0
     

7.4.7 類型轉換運算符

BINARY
    BINARY操作符強制跟隨它後面的字符串為一個二進制字符串。即使列沒被定義為BINARY或BLOB,這是一個強制列比較區分大小寫的簡易方法。

    mysql> select "a" = "A";
            -> 1
    mysql> select BINARY "a" = "A";
            -> 0

    BINARY在MySQL 3.23.0中被引入。

7.4.8 控制流函數

IFNULL(expr1,expr2)
    如果expr1不是NULL,IFNULL()返回expr1,否則它返回expr2。IFNULL()返回一個數字或字符串值,取決于它被使用的上下文環境。

        mysql> select IFNULL(1,0);
                -> 1
        mysql> select IFNULL(0,10);
                -> 0
        mysql> select IFNULL(1/0,10);
                -> 10
        mysql> select IFNULL(1/0,'yes');
                -> 'yes'
         

IF(expr1,expr2,expr3)
    如果expr1是TRUE(expr1<>0且expr1<>NULL),那麼IF()返回expr2,否則它返回expr3。IF()返回一個數字或字符串值,取決于它被使用的上下文。

    mysql> select IF(1>2,2,3);
            -> 3
    mysql> select IF(1<2,'yes','no');
            -> 'yes'
    mysql> select IF(strcmp('test','test1'),'yes','no');
            -> 'no'

    expr1作為整數值被計算,它意味著如果你正在測試浮點或字符串值,你應該使用一個比較操作來做。

    mysql> select IF(0.1,1,0);
            -> 0
    mysql> select IF(0.1<>0,1,0);
            -> 1

    在上面的第一種情況中,IF(0.1)返回0,因為0.1被變換到整數值, 導致測試IF(0)。這可能不是你期望的。在第二種情況中,比較測試原來的浮點值看它是否是非零,比較的結果被用作一個整數。
CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
     
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
    第一個版本返回result,其中value=compare-value。第二個版本中如果第一個條件為真,返回result。如果沒有匹配的result值,那麼結果在ELSE後的result被返回。如果沒有ELSE部分,那麼NULL被返回。

    mysql> SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END;
           -> "one"
    mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
           -> "true"
    mysql> SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END;
           -> NULL

7.4.9 數學函數

所有的數學函數在一個出錯的情況下返回NULL。

-
    單目減。改變參數的符號。

    mysql> select - 2;

    注意,如果這個操作符與一個BIGINT使用,返回值是一個BIGINT!這意味著你應該避免在整數上使用-,那可能有值-2^63!

ABS(X)
    返回X的絕對值。

    mysql> select ABS(2);
            -> 2
    mysql> select ABS(-32);
            -> 32

    該功能可安全用于BIGINT值。
SIGN(X)
    返回參數的符號,為-1、0或1,取決于X是否是負數、零或正數。

    mysql> select SIGN(-32);
            -> -1
    mysql> select SIGN(0);
            -> 0
    mysql> select SIGN(234);
            -> 1
      

MOD(N,M)
     
%
    模 (類似C中的%操作符)。返回N被M除的余數。

    mysql> select MOD(234, 10);
            -> 4
    mysql> select 253 % 7;
            -> 1
    mysql> select MOD(29,9);
            -> 2

    這個函數可安全用于BIGINT值。  

FLOOR(X)
    返回不大于X的最大整數值。

    mysql> select FLOOR(1.23);
            -> 1
    mysql> select FLOOR(-1.23);
            -> -2

    注意返回值被變換為一個BIGINT!  

CEILING(X)
    返回不小于X的最小整數值。

    mysql> select CEILING(1.23);
            -> 2
    mysql> select CEILING(-1.23);
            -> -1

    注意返回值被變換為一個BIGINT!
ROUND(X)
    返回參數X的四舍五入的一個整數。

    mysql> select ROUND(-1.23);
            -> -1
    mysql> select ROUND(-1.58);
            -> -2
    mysql> select ROUND(1.58);
            -> 2
     

    注意返回值被變換為一個BIGINT!
ROUND(X,D)
    返回參數X的四舍五入的有D為小數的一個數字。如果D為0,結果將沒有小數點或小數部分。

    mysql> select ROUND(1.298, 1);
            -> 1.3
    mysql> select ROUND(1.298, 0);
            -> 1

    注意返回值被變換為一個BIGINT!
EXP(X)
    返回值e(自然對數的底)的X次方。

    mysql> select EXP(2);
            -> 7.389056
    mysql> select EXP(-2);
            -> 0.135335
     

LOG(X)
    返回X的自然對數。

    mysql> select LOG(2);
            -> 0.693147
    mysql> select LOG(-2);
            -> NULL

    如果你想要一個數字X的任意底B的對數,使用公式LOG(X)/LOG(B)。
LOG10(X)
    返回X的以10為底的對數。

    mysql> select LOG10(2);
            -> 0.301030
    mysql> select LOG10(100);
            -> 2.000000
    mysql> select LOG10(-100);
            -> NULL

POW(X,Y)
     
POWER(X,Y)
    返回值X的Y次冪。

    mysql> select POW(2,2);
            -> 4.000000
    mysql> select POW(2,-2);
            -> 0.250000

SQRT(X)
    返回非負數X的平方根。

    mysql> select SQRT(4);
            -> 2.000000
    mysql> select SQRT(20);
            -> 4.472136
     

PI()
    返回PI的值(圓周率)。

    mysql> select PI();
            -> 3.141593

COS(X)
    返回X的余弦, 在這里X以弧度給出。

    mysql> select COS(PI());
            -> -1.000000
     

SIN(X)
    返回X的正弦值,在此X以弧度給出。

    mysql> select SIN(PI());
            -> 0.000000
     

TAN(X)
    返回X的正切值,在此X以弧度給出。

    mysql> select TAN(PI()+1);
            -> 1.557408
     

ACOS(X)
    返回X反余弦,即其余弦值是X。如果X不在-1到1的範圍,返回NULL。

    mysql> select ACOS(1);
            -> 0.000000
    mysql> select ACOS(1.0001);
            -> NULL
    mysql> select ACOS(0);
            -> 1.570796
     

ASIN(X)
    返回X反正弦值,即其正弦值是X。L如果X不在-1到1的範圍,返回NULL。

    mysql> select ASIN(0.2);
            -> 0.201358
    mysql> select ASIN('foo');
            -> 0.000000
     

ATAN(X)
    返回X的反正切值,即其正切值是X。

    mysql> select ATAN(2);
            -> 1.107149
    mysql> select ATAN(-2);
            -> -1.107149

ATAN2(X,Y)
    返回2個變量X和Y的反正切。它類似于計算Y/X的反正切,除了兩個參數的符號被用來決定結果的象限。

    mysql> select ATAN(-2,2);
            -> -0.785398
    mysql> select ATAN(PI(),0);
            -> 1.570796

COT(X)
    返回X的余切。

    mysql> select COT(12);
            -> -1.57267341
    mysql> select COT(0);
            -> NULL

RAND()
     
RAND(N)
    返回在範圍0到1.0內的隨機浮點值。如果一個整數參數N被指定,它被用作種子值。

    mysql> select RAND();
            -> 0.5925
    mysql> select RAND(20);
            -> 0.1811
    mysql> select RAND(20);
            -> 0.1811
    mysql> select RAND();
            -> 0.2079
    mysql> select RAND();
            -> 0.7888

    你不能在一個ORDER BY子句用RAND()值使用列,因為ORDER BY將重複計算列多次。然而在MySQL3.23中,你可以做: SELECT * FROM table_name ORDER BY RAND(),這是有利于得到一個來自SELECT * FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000的集合的隨機樣本。注意在一個WHERE子句里的一個RAND()將在每次WHERE被執行時重新評估。
LEAST(X,Y,...)
    有2和2個以上的參數,返回最小(最小值)的參數。參數使用下列規則進行比較:

        * 如果返回值被使用在一個INTEGER上下文,或所有的參數都是整數值,他們作為整數比較。
        * 如果返回值被使用在一個REAL上下文,或所有的參數是實數值,他們作為實數比較。
        * 如果任何參數是一個大小敏感的字符串,參數作為大小寫敏感的字符串被比較。
        * 在其他的情況下,參數作為大小寫無關的字符串被比較。

    mysql> select LEAST(2,0);
            -> 0
    mysql> select LEAST(34.0,3.0,5.0,767.0);
            -> 3.0
    mysql> select LEAST("B","A","C");
            -> "A"

    在MySQL 3.22.5以前的版本,你可以使用MIN()而不是LEAST。
GREATEST(X,Y,...)
    返回最大(最大值)的參數。參數使用與LEAST一樣的規則進行比較。

    mysql> select GREATEST(2,0);
            -> 2
    mysql> select GREATEST(34.0,3.0,5.0,767.0);
            -> 767.0
    mysql> select GREATEST("B","A","C");
            -> "C"

    在MySQL在 3.22.5 以前的版本, 你能使用MAX()而不是GREATEST.  

DEGREES(X)
    返回參數X,從弧度變換為角度。

    mysql> select DEGREES(PI());
            -> 180.000000

RADIANS(X)
    返回參數X,從角度變換為弧度。

    mysql> select RADIANS(90);
            -> 1.570796

TRUNCATE(X,D)
    返回數字X,截斷為D位小數。如果D為0,結果將沒有小數點或小數部分。

    mysql> select TRUNCATE(1.223,1);
            -> 1.2
    mysql> select TRUNCATE(1.999,1);
            -> 1.9
    mysql> select TRUNCATE(1.999,0);
            -> 1
     

7.4.10 字符串函數

如果結果的長度大于服務器參數max_allowed_packet,字符串值函數返回NULL。見10.2.3 調節服務器參數。

對于針對字符串位置的操作,第一個位置被標記為1。

ASCII(str)
    返回字符串str的最左面字符的ASCII代碼值。如果str是空字符串,返回0。如果str是NULL,返回NULL。

    mysql> select ASCII('2');
            -> 50
    mysql> select ASCII(2);
            -> 50
    mysql> select ASCII('dx');
            -> 100

    也可參見ORD()函數。
ORD(str)
    如果字符串str最左面字符是一個多字節字符,通過以格式((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code...]返回字符的ASCII代碼值來返回多字節字符代碼。如果最左面的字符不是一個多字節字符。返回與ASCII()函數返回的相同值。

    mysql> select ORD('2');
            -> 50
     

CONV(N,from_base,to_base)
    在不同的數字基之間變換數字。返回數字N的字符串數字,從from_base基變換為to_base基,如果任何參數是NULL,返回NULL。參數N解釋為一個整數,但是可以指定為一個整數或一個字符串。最小基是2且最大的基是36。如果to_base是一個負數,N被認為是一個有符號數,否則,N被當作無符號數。 CONV以64位點精度工作。

    mysql> select CONV("a",16,2);
            -> '1010'
    mysql> select CONV("6E",18,8);
            -> '172'
    mysql> select CONV(-17,10,-18);
            -> '-H'
    mysql> select CONV(10+"10"+'10'+0xa,10,10);
            -> '40'
     

BIN(N)
    返回二進制值N的一個字符串表示,在此N是一個長整數(BIGINT)數字,這等價于CONV(N,10,2)。如果N是NULL,返回NULL。

    mysql> select BIN(12);
            -> '1100'

OCT(N)
    返回八進制值N的一個字符串的表示,在此N是一個長整型數字,這等價于CONV(N,10,8)。如果N是NULL,返回NULL。

    mysql> select OCT(12);
            -> '14'
     

HEX(N)
    返回十六進制值N一個字符串的表示,在此N是一個長整型(BIGINT)數字,這等價于CONV(N,10,16)。如果N是NULL,返回NULL。

    mysql> select HEX(255);
            -> 'FF'
     

CHAR(N,...)
    CHAR()將參數解釋為整數並且返回由這些整數的ASCII代碼字符組成的一個字符串。NULL值被跳過。

    mysql> select CHAR(77,121,83,81,'76');
            -> 'MySQL'
    mysql> select CHAR(77,77.3,'77.3');
            -> 'MMM'
     

CONCAT(str1,str2,...)
    返回來自于參數連結的字符串。如果任何參數是NULL,返回NULL。可以有超過2個的參數。一個數字參數被變換為等價的字符串形式。

    mysql> select CONCAT('My', 'S', 'QL');
            -> 'MySQL'
    mysql> select CONCAT('My', NULL, 'QL');
            -> NULL
    mysql> select CONCAT(14.3);
            -> '14.3'

LENGTH(str)
     
OCTET_LENGTH(str)
     
CHAR_LENGTH(str)
     
CHARACTER_LENGTH(str)
    返回字符串str的長度。

    mysql> select LENGTH('text');
            -> 4
    mysql> select OCTET_LENGTH('text');
            -> 4

    注意,對于多字節字符,其CHAR_LENGTH()僅計算一次。
LOCATE(substr,str)
     
POSITION(substr IN str)
    返回子串substr在字符串str第一個出現的位置,如果substr不是在str里面,返回0.

    mysql> select LOCATE('bar', 'foobarbar');
            -> 4
    mysql> select LOCATE('xbar', 'foobar');
            -> 0

    該函數是多字節可靠的。  

LOCATE(substr,str,pos)
    返回子串substr在字符串str第一個出現的位置,從位置pos開始。如果substr不是在str里面,返回0。

    mysql> select LOCATE('bar', 'foobarbar',5);
            -> 7

    這函數是多字節可靠的。
INSTR(str,substr)
    返回子串substr在字符串str中的第一個出現的位置。這與有2個參數形式的LOCATE()相同,除了參數被顛倒。

    mysql> select INSTR('foobarbar', 'bar');
            -> 4
    mysql> select INSTR('xbar', 'foobar');
            -> 0

    這函數是多字節可靠的。
LPAD(str,len,padstr)
    返回字符串str,左面用字符串padstr填補直到str是len個字符長。

    mysql> select LPAD('hi',4,'??');
            -> '??hi'
     

RPAD(str,len,padstr)
    返回字符串str,右面用字符串padstr填補直到str是len個字符長。  

    mysql> select RPAD('hi',5,'?');
            -> 'hi???'

LEFT(str,len)
    返回字符串str的最左面len個字符。

    mysql> select LEFT('foobarbar', 5);
            -> 'fooba'

    該函數是多字節可靠的。
RIGHT(str,len)
    返回字符串str的最右面len個字符。

    mysql> select RIGHT('foobarbar', 4);
            -> 'rbar'

    該函數是多字節可靠的。
SUBSTRING(str,pos,len)
     
SUBSTRING(str FROM pos FOR len)
     
MID(str,pos,len)
    從字符串str返回一個len個字符的子串,從位置pos開始。使用FROM的變種形式是ANSI SQL92語法。

    mysql> select SUBSTRING('Quadratically',5,6);
            -> 'ratica'

    該函數是多字節可靠的。
SUBSTRING(str,pos)
     
SUBSTRING(str FROM pos)
    從字符串str的起始位置pos返回一個子串。

    mysql> select SUBSTRING('Quadratically',5);
            -> 'ratically'
    mysql> select SUBSTRING('foobarbar' FROM 4);
            -> 'barbar'

    該函數是多字節可靠的。
SUBSTRING_INDEX(str,delim,count)
    返回從字符串str的第count個出現的分隔符delim之後的子串。如果count是正數,返回最後的分隔符到左邊(從左邊數) 的所有字符。如果count是負數,返回最後的分隔符到右邊的所有字符(從右邊數)。

    mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2);
            -> 'www.mysql'
    mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2);
            -> 'mysql.com'

    該函數對多字節是可靠的。
LTRIM(str)
    返回刪除了其前置空格字符的字符串str。

    mysql> select LTRIM('  barbar');
            -> 'barbar'

RTRIM(str)
    返回刪除了其拖後空格字符的字符串str。

    mysql> select RTRIM('barbar   ');
            -> 'barbar'

    該函數對多字節是可靠的。  

TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
    返回字符串str,其所有remstr前綴或後綴被刪除了。如果沒有修飾符BOTH、LEADING或TRAILING給出,BOTH被假定。如果remstr沒被指定,空格被刪除。

    mysql> select TRIM('  bar   ');
            -> 'bar'
    mysql> select TRIM(LEADING 'x' FROM 'xxxbarxxx');
            -> 'barxxx'
    mysql> select TRIM(BOTH 'x' FROM 'xxxbarxxx');
            -> 'bar'
    mysql> select TRIM(TRAILING 'xyz' FROM 'barxxyz');
            -> 'barx'

    該函數對多字節是可靠的。
SOUNDEX(str)
    返回str的一個同音字符串。聽起來“大致相同”的2個字符串應該有相同的同音字符串。一個“標准”的同音字符串長是4個字符,但是SOUNDEX()函數返回一個任意長的字符串。你可以在結果上使用SUBSTRING()得到一個“標准”的 同音串。所有非數字字母字符在給定的字符串中被忽略。所有在A-Z之外的字符國際字母被當作元音。

    mysql> select SOUNDEX('Hello');
            -> 'H400'
    mysql> select SOUNDEX('Quadratically');
            -> 'Q36324'
     

SPACE(N)
    返回由N個空格字符組成的一個字符串。

    mysql> select SPACE(6);
            -> '      '
     

REPLACE(str,from_str,to_str)
    返回字符串str,其字符串from_str的所有出現由字符串to_str代替。

    mysql> select REPLACE('www.mysql.com', 'w', 'Ww');
            -> 'WwWwWw.mysql.com'

    該函數對多字節是可靠的。
REPEAT(str,count)
    返回由重複countTimes次的字符串str組成的一個字符串。如果count <= 0,返回一個空字符串。如果str或count是NULL,返回NULL。

    mysql> select REPEAT('MySQL', 3);
            -> 'MySQLMySQLMySQL'
     

REVERSE(str)
    返回顛倒字符順序的字符串str。

    mysql> select REVERSE('abc');
            -> 'cba'

    該函數對多字節可靠的。
INSERT(str,pos,len,newstr)
    返回字符串str,在位置pos起始的子串且len個字符長得子串由字符串newstr代替。

    mysql> select INSERT('Quadratic', 3, 4, 'What');
            -> 'QuWhattic'

    該函數對多字節是可靠的。
ELT(N,str1,str2,str3,...)
    如果N= 1,返回str1,如果N= 2,返回str2,等等。如果N小于1或大于參數個數,返回NULL。ELT()是FIELD()反運算。

    mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo');
            -> 'ej'
    mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo');
            -> 'foo'

FIELD(str,str1,str2,str3,...)
    返回str在str1, str2, str3, ...清單的索引。如果str沒找到,返回0。FIELD()是ELT()反運算。

    mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
            -> 2
    mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
            -> 0

FIND_IN_SET(str,strlist)
    如果字符串str在由N子串組成的表strlist之中,返回一個1到N的值。一個字符串表是被“,”分隔的子串組成的一個字符串。如果第一個參數是一個常數字符串並且第二個參數是一種類型為SET的列,FIND_IN_SET()函數被優化而使用位運算!如果str不是在strlist里面或如果strlist是空字符串,返回0。如果任何一個參數是NULL,返回NULL。如果第一個參數包含一個“,”,該函數將工作不正常。

    mysql> SELECT FIND_IN_SET('b','a,b,c,d');
            -> 2
     

MAKE_SET(bits,str1,str2,...)
    返回一個集合 (包含由“,”字符分隔的子串組成的一個字符串),由相應的位在bits集合中的的字符串組成。str1對應于位0,str2對應位1,等等。在str1, str2, ...中的NULL串不添加到結果中。

    mysql> SELECT MAKE_SET(1,'a','b','c');
            -> 'a'
    mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
            -> 'hello,world'
    mysql> SELECT MAKE_SET(0,'a','b','c');
            -> ''

EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
    返回一個字符串,在這里對于在“bits”中設定每一位,你得到一個“on”字符串,並且對于每個複位(reset)的位,你得到一個“off”字符串。每個字符串用“separator”分隔(缺省“,”),並且只有“bits”的“number_of_bits” (缺省64)位被使用。

    mysql> select EXPORT_SET(5,'Y','N',',',4)
            -> Y,N,Y,N

LCASE(str)
     
LOWER(str)
    返回字符串str,根據當前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改變成小寫。該函數對多字節是可靠的。

    mysql> select LCASE('QUADRATICALLY');
            -> 'quadratically'
     

UCASE(str)
     
UPPER(str)
    返回字符串str,根據當前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改變成大寫。該函數對多字節是可靠的。

    mysql> select UCASE('Hej');
            -> 'HEJ'

    該函數對多字節是可靠的。
LOAD_FILE(file_name)
    讀入文件並且作為一個字符串返回文件內容。文件必須在服務器上,你必須指定到文件的完整路徑名,而且你必須有file權限。文件必須所有內容都是可讀的並且小于max_allowed_packet。如果文件不存在或由于上面原因之一不能被讀出,函數返回NULL。

    mysql> UPDATE table_name
               SET blob_column=LOAD_FILE("/tmp/picture")
               WHERE id=1;


MySQL必要時自動變換數字為字符串,並且反過來也如此:

mysql> SELECT 1+"1";
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

如果你想要明確地變換一個數字到一個字符串,把它作為參數傳遞到CONCAT()。

如果字符串函數提供一個二進制字符串作為參數,結果字符串也是一個二進制字符串。被變換到一個字符串的數字被當作是一個二進制字符串。這僅影響比較。

TOP

7.4.11 日期和時間函數
對于每個類型擁有的值範圍以及並且指定日期何時間值的有效格式的描述見7.3.6 日期和時間類型。

這里是一個使用日期函數的例子。下面的查詢選擇了所有記錄,其date_col的值是在最後30天以內:

mysql> SELECT something FROM table
           WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;

DAYOFWEEK(date)
    返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。這些索引值對應于ODBC標准。

    mysql> select DAYOFWEEK('1998-02-03');
            -> 3
     

WEEKDAY(date)
    返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。

    mysql> select WEEKDAY('1997-10-04 22:23:00');
            -> 5
    mysql> select WEEKDAY('1997-11-05');
            -> 2
     

DAYOFMONTH(date)
    返回date的月份中日期,在1到31範圍內。

    mysql> select DAYOFMONTH('1998-02-03');
            -> 3

DAYOFYEAR(date)
    返回date在一年中的日數, 在1到366範圍內。

    mysql> select DAYOFYEAR('1998-02-03');
            -> 34

MONTH(date)
    返回date的月份,範圍1到12。

    mysql> select MONTH('1998-02-03');
            -> 2
     

DAYNAME(date)
    返回date的星期名字。

    mysql> select DAYNAME("1998-02-05");
            -> 'Thursday'

MONTHNAME(date)
    返回date的月份名字。

    mysql> select MONTHNAME("1998-02-05");
            -> 'February'
     

QUARTER(date)
    返回date一年中的季度,範圍1到4。

    mysql> select QUARTER('98-04-01');
            -> 2
     

WEEK(date)
     
WEEK(date,first)
    對于星期天是一周的第一天的地方,有一個單個參數,返回date的周數,範圍在0到52。2個參數形式WEEK()允許你指定星期是否開始于星期天或星期一。如果第二個參數是0,星期從星期天開始,如果第二個參數是1,從星期一開始。

    mysql> select WEEK('1998-02-20');
            -> 7
    mysql> select WEEK('1998-02-20',0);
            -> 7
    mysql> select WEEK('1998-02-20',1);
            -> 8

YEAR(date)
    返回date的年份,範圍在1000到9999。

    mysql> select YEAR('98-02-03');
            -> 1998

HOUR(time)
    返回time的小時,範圍是0到23。

    mysql> select HOUR('10:05:03');
            -> 10

MINUTE(time)
    返回time的分鐘,範圍是0到59。

    mysql> select MINUTE('98-02-03 10:05:03');
            -> 5

SECOND(time)
    回來time的秒數,範圍是0到59。

    mysql> select SECOND('10:05:03');
            -> 3

PERIOD_ADD(P,N)
    增加N個月到階段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意階段參數P不是日期值。

    mysql> select PERIOD_ADD(9801,2);
            -> 199803

PERIOD_DIFF(P1,P2)
    返回在時期P1和P2之間月數,P1和P2應該以格式YYMM或YYYYMM。注意,時期參數P1和P2不是日期值。

    mysql> select PERIOD_DIFF(9802,199703);
            -> 11
        

DATE_ADD(date,INTERVAL expr type)
     
DATE_SUB(date,INTERVAL expr type)
     
ADDDATE(date,INTERVAL expr type)
     
SUBDATE(date,INTERVAL expr type)
    這些功能執行日期運算。對于MySQL 3.22,他們是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同義詞。在MySQL 3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(見例子)date是一個指定開始日期的DATETIME或DATE值,expr是指定加到開始日期或從開始日期減去的間隔值一個表達式,expr是一個字符串;它可以以一個“-”開始表示負間隔。type是一個關鍵詞,指明表達式應該如何被解釋。EXTRACT(type FROM date)函數從日期中返回“type”間隔。下表顯示了type和expr參數怎樣被關聯:
    type值         含義         期望的expr格式
    SECOND         秒         SECONDS
    MINUTE         分鐘         MINUTES
    HOUR         時間         HOURS
    DAY         天         DAYS
    MONTH         月         MONTHS
    YEAR         年         YEARS
    MINUTE_SECOND         分鐘和秒         "MINUTES:SECONDS"
    HOUR_MINUTE         小時和分鐘         "HOURS:MINUTES"
    DAY_HOUR         天和小時         "DAYS HOURS"
    YEAR_MONTH         年和月         "YEARS-MONTHS"
    HOUR_SECOND         小時, 分鐘,         "HOURS:MINUTES:SECONDS"
    DAY_MINUTE         天, 小時, 分鐘         "DAYS HOURS:MINUTES"
    DAY_SECOND         天, 小時, 分鐘, 秒         "DAYS HOURS:MINUTES:SECONDS"

    MySQL在expr格式中允許任何標點分隔符。表示顯示的是建議的分隔符。如果date參數是一個DATE值並且你的計算僅僅包含YEAR、MONTH和DAY部分(即,沒有時間部分),結果是一個DATE值。否則結果是一個DATETIME值。

    mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
            -> 1998-01-01 00:00:00
    mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
            -> 1998-01-01
    mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
           -> 1997-12-31 23:59:59
    mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
                           INTERVAL 1 SECOND);
            -> 1998-01-01 00:00:00
    mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
                           INTERVAL 1 DAY);
            -> 1998-01-01 23:59:59
    mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
                           INTERVAL "1:1" MINUTE_SECOND);
            -> 1998-01-01 00:01:00
    mysql> SELECT DATE_SUB("1998-01-01 00:00:00",
                           INTERVAL "1 1:1:1" DAY_SECOND);
            -> 1997-12-30 22:58:59
    mysql> SELECT DATE_ADD("1998-01-01 00:00:00",
                           INTERVAL "-1 10" DAY_HOUR);
            -> 1997-12-30 14:00:00
    mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
            -> 1997-12-02
    mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
           -> 1999
    mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
           -> 199907
    mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
           -> 20102

    如果你指定太短的間隔值(不包括type關鍵詞期望的間隔部分),MySQL假設你省掉了間隔值的最左面部分。例如,如果你指定一個type是DAY_SECOND,值expr被希望有天、小時、分鐘和秒部分。如果你象"1:10"這樣指定值,MySQL假設日子和小時部分是丟失的並且值代表分鐘和秒。換句話說,"1:10" DAY_SECOND以它等價于"1:10" MINUTE_SECOND的方式解釋,這對那MySQL解釋TIME值表示經過的時間而非作為一天的時間的方式有二義性。如果你使用確實不正確的日期,結果是NULL。如果你增加MONTH、YEAR_MONTH或YEAR並且結果日期大于新月份的最大值天數,日子在新月用最大的天調整。

    mysql> select DATE_ADD('1998-01-30', Interval 1 month);
            -> 1998-02-28

    注意,從前面的例子中詞INTERVAL和type關鍵詞不是區分大小寫的。  

TO_DAYS(date)
    給出一個日期date,返回一個天數(從0年的天數)。

    mysql> select TO_DAYS(950501);
            -> 728779
    mysql> select TO_DAYS('1997-10-07');
            -> 729669

    TO_DAYS()不打算用于使用格列高里歷(1582)出現前的值。
FROM_DAYS(N)
    給出一個天數N,返回一個DATE值。

    mysql> select FROM_DAYS(729669);
            -> '1997-10-07'

    TO_DAYS()不打算用于使用格列高里歷(1582)出現前的值。
DATE_FORMAT(date,format)
    根據format字符串格式化date值。下列修飾符可以被用在format字符串中:
    %M         月名字(January……December)
    %W         星期名字(Sunday……Saturday)
    %D         有英語前綴的月份的日期(1st, 2nd, 3rd, 等等。)
    %Y         年, 數字, 4 位
    %y         年, 數字, 2 位
    %a         縮寫的星期名字(Sun……Sat)
    %d         月份中的天數, 數字(00……31)
    %e         月份中的天數, 數字(0……31)
    %m         月, 數字(01……12)
    %c         月, 數字(1……12)
    %b         縮寫的月份名字(Jan……Dec)
    %j         一年中的天數(001……366)
    %H         小時(00……23)
    %k         小時(0……23)
    %h         小時(01……12)
    %I         小時(01……12)
    %l         小時(1……12)
    %i         分鐘, 數字(00……59)
    %r         時間,12 小時(hh:mm:ss [AP]M)
    %T         時間,24 小時(hh:mm:ss)
    %S         秒(00……59)
    %s         秒(00……59)
    %p         AM或PM
    %w         一個星期中的天數(0=Sunday ……6=Saturday )
    %U         星期(0……52), 這里星期天是星期的第一天
    %u         星期(0……52), 這里星期一是星期的第一天
    %%         一個文字“%”。

    所有的其他字符不做解釋被複制到結果中。

    mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
            -> 'Saturday October 1997'
    mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
            -> '22:23:00'
    mysql> select DATE_FORMAT('1997-10-04 22:23:00',
                              '%D %y %a %d %m %b %j');
            -> '4th 97 Sat 04 10 Oct 277'
    mysql> select DATE_FORMAT('1997-10-04 22:23:00',
                              '%H %k %I %r %T %S %w');
            -> '22 22 10 10:23:00 PM 22:23:00 00 6'

    MySQL3.23中,在格式修飾符字符前需要%。在MySQL更早的版本中,%是可選的。
TIME_FORMAT(time,format)
    這象上面的DATE_FORMAT()函數一樣使用,但是format字符串只能包含處理小時、分鐘和秒的那些格式修飾符。其他修飾符產生一個NULL值或0。
CURDATE()
     
CURRENT_DATE
    以'YYYY-MM-DD'或YYYYMMDD格式返回今天日期值,取決于函數是在一個字符串還是數字上下文被使用。

    mysql> select CURDATE();
            -> '1997-12-15'
    mysql> select CURDATE() + 0;
            -> 19971215

CURTIME()
     
CURRENT_TIME
    以'HH:MM:SS'或HHMMSS格式返回當前時間值,取決于函數是在一個字符串還是在數字的上下文被使用。

    mysql> select CURTIME();
            -> '23:50:26'
    mysql> select CURTIME() + 0;
            -> 235026

NOW()
     
SYSDATE()
     
CURRENT_TIMESTAMP
    以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回當前的日期和時間,取決于函數是在一個字符串還是在數字的上下文被使用。

    mysql> select NOW();
            -> '1997-12-15 23:50:26'
    mysql> select NOW() + 0;
            -> 19971215235026

UNIX_TIMESTAMP()
     
UNIX_TIMESTAMP(date)
    如果沒有參數調用,返回一個Unix時間戳記(從'1970-01-01 00:00:00'GMT開始的秒數)。如果UNIX_TIMESTAMP()用一個date參數被調用,它返回從'1970-01-01 00:00:00' GMT開始的秒數值。date可以是一個DATE字符串、一個DATETIME字符串、一個TIMESTAMP或以YYMMDD或YYYYMMDD格式的本地時間的一個數字。

    mysql> select UNIX_TIMESTAMP();
            -> 882226357
    mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');
            -> 875996580

    當UNIX_TIMESTAMP被用于一個TIMESTAMP列,函數將直接接受值,沒有隱含的“string-to-unix-timestamp”變換。
FROM_UNIXTIME(unix_timestamp)
    以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回unix_timestamp參數所表示的值,取決于函數是在一個字符串還是或數字上下文中被使用。

    mysql> select FROM_UNIXTIME(875996580);
            -> '1997-10-04 22:23:00'
    mysql> select FROM_UNIXTIME(875996580) + 0;
            -> 19971004222300

FROM_UNIXTIME(unix_timestamp,format)
    返回表示 Unix 時間標記的一個字符串,根據format字符串格式化。format可以包含與DATE_FORMAT()函數列出的條目同樣的修飾符。

    mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(),
                                '%Y %D %M %h:%i:%s %x');
            -> '1997 23rd December 03:43:30 x'

SEC_TO_TIME(seconds)
    返回seconds參數,變換成小時、分鐘和秒,值以'HH:MM:SS'或HHMMSS格式化,取決于函數是在一個字符串還是在數字上下文中被使用。

    mysql> select SEC_TO_TIME(2378);
            -> '00:39:38'
    mysql> select SEC_TO_TIME(2378) + 0;
            -> 3938

TIME_TO_SEC(time)
    返回time參數,轉換成秒。

    mysql> select TIME_TO_SEC('22:23:00');
            -> 80580
    mysql> select TIME_TO_SEC('00:39:38');
            -> 2378

7.4.12 其他函數

DATABASE()
    返回當前的數據庫名字。

    mysql> select DATABASE();
            -> 'test'

    如果沒有當前的數據庫,DATABASE()返回空字符串。
USER()
     
SYSTEM_USER()
     
SESSION_USER()
    返回當前MySQL用戶名。

    mysql> select USER();
            -> 'davida@localhost'

    在MySQL 3.22.11或以後版本中,這包括用戶名和客戶主機名。你可以象這樣只提取用戶名部分(值是否包括主機名部分均可工作):

    mysql> select substring_index(USER(),"@",1);
            -> 'davida'

PASSWORD(str)
    從純文本口令str計算一個口令字符串。該函數被用于為了在user授權表的Password列中存儲口令而加密MySQL口令。

    mysql> select PASSWORD('badpwd');
            -> '7f84554057dd964b'

    PASSWORD()加密是非可逆的。PASSWORD()不以與Unix口令加密的相同的方法執行口令加密。你不應該假定如果你的Unix 口令和你的MySQL口令是一樣的,PASSWORD()將導致與在Unix口令文件存儲的相同的加密值。見ENCRYPT()。
ENCRYPT(str[,salt])
    使用Unix crypt()系統調用加密str。salt參數應該是一個有2個字符的字符串。(MySQL 3.22.16中,salt可以長于2個字符。)

    mysql> select ENCRYPT("hello");
            -> 'VxuFAJXVARROc'

    如果crypt()在你的系統上不可用,ENCRYPT()總是返回NULL。ENCRYPT()只保留str起始8個字符而忽略所有其他,至少在某些系統上是這樣。這將由底層的crypt()系統調用的行為決定。
ENCODE(str,pass_str)
    使用pass_str作為口令加密str。為了解密結果,使用DECODE()。結果是一個二進制字符串,如果你想要在列中保存它,使用一個BLOB列類型。
DECODE(crypt_str,pass_str)
    使用pass_str作為口令解密加密的字符串crypt_str。crypt_str應該是一個由ENCODE()返回的字符串。
MD5(string)
    對字符串計算MD5校驗和。值作為一個32長的十六進制數字被返回可以,例如用作哈希(hash)鍵。

    mysql> select MD5("testing")
            -> 'ae2b1fca515949e5d54fb22b8ed95575'

    這是一個“RSA數據安全公司的MD5消息摘要算法”。
LAST_INSERT_ID([expr])
    返回被插入一個AUTO_INCREMENT列的最後一個自動產生的值。見20.4.29 mysql_insert_id()。

    mysql> select LAST_INSERT_ID();
            -> 195

    產生的最後ID以每個連接為基礎在服務器被維護,它不會被其他客戶改變。如果你更新另外一個有非魔術值(即,不是NULL和不是0的一個值)的AUTO_INCREMENT列,它甚至不會被改變。如果expr作為一個參數在一個UPDATE子句的LAST_INSERT_ID()里面給出,那麼參數值作為一個LAST_INSERT_ID()值被返回。這可以用來模仿順序:首先創建表:

    mysql> create table sequence (id int not null);
    mysql> insert into sequence values (0);

    然後表能被用來產生順序號,象這樣:

    mysql> update sequence set id=LAST_INSERT_ID(id+1);

    你可以不調用LAST_INSERT_ID()而產生順序,但是這樣使用函數的實用程序在服務器上自動維護ID值作為最後自動產生的值。你可以檢索新的ID值,就像你能讀入正常MySQL中的任何正常的AUTO_INCREMENT值一樣。例如,LAST_INSERT_ID()(沒有一個參數 )將返回新ID。C API函數mysql_insert_id()也可被用來得到值。
FORMAT(X,D)
    格式化數字X為類似于格式'#,###,###.##',四舍五入到D為小數。如果D為0,結果將沒有小數點和小數部分。

    mysql> select FORMAT(12332.123456, 4);
            -> '12,332.1235'
    mysql> select FORMAT(12332.1,4);
            -> '12,332.1000'
    mysql> select FORMAT(12332.2,0);
            -> '12,332'

VERSION()
    返回表明MySQL服務器版本的一個字符串。

    mysql> select VERSION();
            -> '3.22.19b-log'

GET_LOCK(str,timeout)
    試圖獲得由字符串str給定的一個名字的鎖定,第二個timeout為超時。如果鎖定成功獲得,返回1,如果嘗試超時了,返回0,或如果發生一個錯誤,返回NULL(例如從存儲器溢出或線程用mysqladmin kill被殺死)。當你執行RELEASE_LOCK()時、執行一個新的GET_LOCK()或線程終止時,一個鎖定被釋放。該函數可以用來實現應用鎖或模擬記錄鎖,它阻止其他客戶用同樣名字的鎖定請求;贊成一個給定的鎖定字符串名字的客戶可以使用字符串執行子協作建議的鎖定。

    mysql> select GET_LOCK("lock1",10);
            -> 1
    mysql> select GET_LOCK("lock2",10);
            -> 1
    mysql> select RELEASE_LOCK("lock2");
            -> 1
    mysql> select RELEASE_LOCK("lock1");
            -> NULL

    注意,第二個RELEASE_LOCK()調用返回NULL,因為鎖"lock1"自動地被第二個GET_LOCK()調用釋放。
RELEASE_LOCK(str)
    釋放字符串str命名的通過GET_LOCK()獲得的鎖。如果鎖被釋放,返回1,如果鎖沒被這個線程鎖定(在此情況下鎖沒被釋放)返回0,並且如果命名的鎖不存在,返回NULL。如果鎖從來沒有通過調用GET_LOCK()獲得或如果它已經被釋放了,鎖將不存在。
BENCHMARK(count,expr)
    BENCHMARK()函數重複countTimes次執行表達式expr,它可以用于計時MySQL處理表達式有多快。結果值總是0。意欲用于mysql客戶,它報告查詢的執行時間。

    mysql> select BENCHMARK(1000000,encode("hello","goodbye"));
    +----------------------------------------------+
    | BENCHMARK(1000000,encode("hello","goodbye")) |
    +----------------------------------------------+
    |                                            0 |
    +----------------------------------------------+
    1 row in set (4.74 sec)

    報告的時間是客戶端的經過時間,不是在服務器端的CPU時間。執行BENCHMARK()若幹次可能是明智的,並且注意服務器機器的負載有多重來解釋結果。

7.4.13 與GROUP BY子句一起使用的函數

如果你在不包含GROUP BY子句的一個語句中使用聚合函數,它等價于聚合所有行。

COUNT(expr)
    返回由一個SELECT語句檢索出來的行的非NULL值的數目。

    mysql> select student.student_name,COUNT(*)
               from student,course
               where student.student_id=course.student_id
               GROUP BY student_name;

    COUNT(*)在它返回的檢索出來的行數目上有些不同,不管他們是否包含NULL值。如果SELECT從一個表檢索,或沒有檢索出其他列並且沒有WHERE子句,COUNT(*)被優化以便快速地返回。例如:

    mysql> select COUNT(*) from student;
      

COUNT(DISTINCT expr,[expr...])
    返回一個不同值的數目。

    mysql> select COUNT(DISTINCT results) from student;

    在MySQL中,你可以通過給出一個表達式列表以得到不同的表達式組合的數目。在 ANSI SQL中,你可能必須在CODE(DISTINCT ..)內進行所有表達式的連接。
AVG(expr)
    返回expr的平均值。

    mysql> select student_name, AVG(test_score)
               from student
               GROUP BY student_name;
      

MIN(expr)
     
MAX(expr)
    返回expr的最小或最大值。MIN()和MAX()可以有一個字符串參數;在這種的情況下,他們返回最小或最大的字符串值。

    mysql> select student_name, MIN(test_score), MAX(test_score)
               from student
               GROUP BY student_name;
     

SUM(expr)
    返回expr的和。注意,如果返回的集合沒有行,它返回NULL!
STD(expr)
     
STDDEV(expr)
    返回expr標准差(deviation)。這是對 ANSI SQL 的擴展。該函數的形式STDDEV()是提供與Oracle的兼容性。
BIT_OR(expr)
    返回expr里所有位的位或。計算用 64 位(BIGINT)精度進行。
BIT_AND(expr)
    返回expr里所有位的位與。計算用 64 位(BIGINT)精度進行。

MySQL擴展了GROUP BY的用法。你可以不出現在的GROUP BY部分的SELECT表達式中使用列或計算,這表示這個組的任何可能值。你可以使用它是性能更好,避免在不必要的項目上排序和分組。例如,你在下列查詢中不需要在customer.name上聚合:

mysql> select order.custid,customer.name,max(payments)
       from order,customer
       where order.custid = customer.custid
       GROUP BY order.custid;

在 ANSI SQL中,你將必須將customer.name加到GROUP BY子句。在MySQL中,名字是冗余的。

如果你從GROUP BY部分省略的列在組中不是唯一的,不要使用這個功能。

在某些情況下,你可以使用MIN()和MAX()獲得一個特定的列值,即使它不是唯一的。下例給出從包含sort列中最小值的行的column值:

substr(MIN(concat(sort,space(6-length(sort)),column),7,length(column)))

注意,如果你正在使用MySQL 3.22(或更早)或如果你正在試圖遵從ANSI SQL,你不能在GROUP BY或ORDER BY子句中使用表達式。你可以通過使用表達式的一個別名解決此限制:

mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
           GROUP BY id,val ORDER BY val;

在MySQL3.23中,你可以這樣做:

mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();

7.5 CREATE DATABASE句法

CREATE DATABASE db_name

CREATE DATABASE用給定的名字創建一個數據庫。允許的數據庫名字規則在7.1.5 數據庫、桌子、索引、列和別名命名中給出。如果數據庫已經存在,發生一個錯誤。

在MySQL中的數據庫實現成包含對應數據庫中表的文件的目錄。因為數據庫在初始創建時沒有任何表,CREATE DATABASE語句只是在MySQL數據目錄下面創建一個目錄。

你也可以用mysqladmin創建數據庫。見12.1 不同的MySQL程序的概述。

7.6 DROP DATABASE句法

DROP DATABASE [IF EXISTS] db_name

DROP DATABASE刪除數據庫中的所有表和數據庫。要小心地使用這個命令!

DROP DATABASE返回從數據庫目錄被刪除的文件的數目。通常,這3倍于表的數量,因為每張表對應于一個“.MYD”文件、一個“.MYI”文件和一個“.frm”文件。

在MySQL 3.22或以後版本中,你可以使用關鍵詞IF EXISTS阻止一個錯誤的發生,如果數據庫不存在。

你也可以用mysqladmin丟棄數據庫。見12.1 不同的 MySQL 程序的概述。

7.7 CREATE TABLE句法

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]

create_definition:
  col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
            [PRIMARY KEY] [reference_definition]
  or    PRIMARY KEY (index_col_name,...)
  or    KEY [index_name] (index_col_name,...)
  or    INDEX [index_name] (index_col_name,...)
  or    UNIQUE [INDEX] [index_name] (index_col_name,...)
  or    [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
            [reference_definition]
  or    CHECK (expr)

type:
        TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  or    SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  or    MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  or    INT[(length)] [UNSIGNED] [ZEROFILL]
  or    INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  or    BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  or    REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  or    NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  or    CHAR(length) [BINARY]
  or    VARCHAR(length) [BINARY]
  or    DATE
  or    TIME
  or    TIMESTAMP
  or    DATETIME
  or    TINYBLOB
  or    BLOB
  or    MEDIUMBLOB
  or    LONGBLOB
  or    TINYTEXT
  or    TEXT
  or    MEDIUMTEXT
  or    LONGTEXT
  or    ENUM(value1,value2,value3,...)
  or    SET(value1,value2,value3,...)

index_col_name:
        col_name [(length)]

reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options:
        TYPE = {ISAM | MYISAM | HEAP}
or        AUTO_INCREMENT = #
or        AVG_ROW_LENGTH = #
or        CHECKSUM = {0 | 1}
or        COMMENT = "string"
or        MAX_ROWS = #
or        MIN_ROWS = #
or        PACK_KEYS = {0 | 1}
or        PASSWORD = "string"
or        DELAY_KEY_WRITE = {0 | 1}
or      ROW_FORMAT= { default | dynamic | static | compressed }

select_statement:
        [IGNORE | REPLACE] SELECT ...  (Some legal select statement)

CREATE TABLE在當前數據庫中用給出的名字創建一個數據庫表。允許的表名的規則在7.1.5 數據庫,桌子,索引,列和別名命名中給出。如果當前數據庫不存在或如果表已經存在,出現一個錯誤。

在MySQL3.22或以後版本中,表名可以被指定為db_name.tbl_name,不管有沒有當前的數據庫都可以。

在MySQL3.23中,當你創建一張表時,你可以使用TEMPORARY關鍵詞。如果一個連接死掉,臨時表將自動被刪除,並且其名字是按連接命名。這意味著,2個不同的連接能使用相同的暫時表的名字而不會彼此衝突或與相同名字的現有數據庫表衝突。(現有的表被隱蔽直到臨時表被刪除)。

在MySQL3.23或以後版本中,你可以使用關鍵詞IF NOT EXISTS以便如果表已經存在不發生一個錯誤。注意,無法証實表結構是相同的。

每張表tbl_name由在數據庫目錄的一些文件表示。在MyISAM類型的表的情況下,你將得到:
文件         目的
tbl_name.frm         表定義(表格)文件
tbl_name.MYD         數據文件
tbl_name.MYI         索引文件

對于各種列類型的性質的更多信息,見7.3 列類型。

    * 如果既不指定NULL也不指定NOT NULL,列被視為指定了NULL。
    * 整型列可以有附加的屬性AUTO_INCREMENT。當你插入NULL值(推薦)或0到一個AUTO_INCREMENT列中時,列被設置為value+1,在此value是當前表中的列的最大值。AUTO_INCREMENT順序從1開始。見20.4.29 mysql_insert_id()。如果你刪除了包含一個AUTO_INCREMENT列的最大值的行,值將被重新使用。如果你刪除表中所有的行,順序重新開始。注意:每個表只能有一個AUTO_INCREMENT列,並且它必須被索引。為了使做MySQL兼容一些 ODBC 應用程序,用下列查詢你可以找出最後插入的行:

      SELECT * FROM tbl_name WHERE auto_col IS NULL

    * NULL值對于TIMESTAMP列的處理不同于其他列類型。你不能在一個TIMESTAMP列中存儲一個文字NULL;設置列為NULL將把它設成當前的日期和時間。因為TIMESTAMP列表現就這樣,NULL和NOT NULL屬性不以一般方式運用並且如果你指定它們,將被忽略。在另一方面,為了使它MySQL客戶更容易地使用TIMESTAMP列,服務器報告這樣的列可以被賦值NULL( 它是對的),盡管TIMESTAMP實際上絕不包含一個NULL值。當你使用DESCRIBE tbl_name得到有關你的表的描述時,你就會明白。注意,設置一個TIMESTAMP列為0不同于將它設置為NULL,因為0是一個有效的TIMESTAMP值。
    * 如果沒有為列指定DEFAULT值,MySQL自動地分配一個。如果列可以取NULL作為值,缺省值是NULL。如果列被聲明為NOT NULL,缺省值取決于列類型:
          o 對于沒有聲明AUTO_INCREMENT屬性的數字類型,缺省值是0。對于一個AUTO_INCREMENT列,缺省值是在順序中的下一個值。
          o 對于除TIMESTAMP的日期和時間類型,缺省值是該類型適當的“零”值。對于表中第一個TIMESTAMP列,缺省值是當前的日期和時間。見7.3.6 日期和時間類型。
          o 對于除ENUM的字符串類型,缺省是空字符串。對于ENUM,缺省值是第一個枚舉值。
    * KEY是INDEX的一個同義詞。
    * 在MySQL中,一個UNIQUE鍵只能有不同的值。如果你試圖用匹配現有行的鍵來增加新行,發生一個錯誤。
    * A PRIMARY KEY是一個唯一KEY,它有額外的限制,即所有的關鍵列必須被定義為NOT NULL。在MySQL中,鍵被命名為PRIMARY。一張表只能有一個PRIMARY KEY。如果在表中你沒有一個PRIMARY KEY並且一些應用程序要求PRIMARY KEY,MySQL將返回第一個UNIQUE鍵,它沒有任何NULL列,作為PRIMARY KEY。
    * 一個PRIMARY KEY可以是一個多列索引。然而,你不能在一個列說明中使用PRIMARY KEY的關鍵字屬性創建一個多列索引。這樣做將僅僅標記單個列作為主鍵。你必須使用PRIMARY KEY(index_col_name, ...)語法。
    * 如果你不能給索引賦予一個名字,這個索引將賦予與第一個index_col_name相同的名字,用一個可選的suffix(_2, _3, ...)使它唯一。你能使用SHOW INDEX FROM tbl_name看到一張表的索引名字。見7.21 SHOW句法(得到表、列等的信息)。
    * 只有MyISAM表類型支持可以有NULL值的列上的索引。在其他情況下,你必須聲明這樣的列為NOT NULL,否則導致一個錯。
    * 用col_name(length)語法,你可以指定僅使用部分的CHAR或VARCHAR列的一個索引。這能使索引文件變得更小。見7.3.9 列索引。
    * 只有MyISAM表類型支持BLOB和TEXT列的索引。當在一個BLOB或TEXT列上放置索引時,你必須總是指定索引的長度:

      CREATE TABLE test (blob_col BLOB, index(blob_col(10)));

    * 當你與TEXT或BLOB列一起使用ORDER BY或GROUP BY時,只使用頭max_sort_length個字節。見7.3.7.2 BLOB和TEXT類型。
    * FOREIGN KEY、CHECK和REFERENCES子句實際上不做任何事情,其語法僅僅提供兼容性,使得它更容易從其他的SQL服務器移植代碼並運行借助引用創建表的應用。見5.4 MySQL缺少的功能。
    * 每個NULL列占據額外一位,取舍到最接近的字節。
    * 最大記錄長度以字節計可以如下計算:

      row length = 1
                   + (sum of column lengths)
                   + (number of NULL columns + 7)/8
                   + (number of variable-length columns)

    * table_options和SELECT選項只在MySQL 3.23和以後版本中被實現。不同的表類型是:
      ISAM         原來的表處理器
      MyISAM         全新二進制可移植的表處理器
      HEAP         用于該表的數據僅僅存儲在內存中

      見9.4 MySQL 表類型。其他表選項被用來優化表的行為。在大多數情況下,你不必指定他們任何一個。選項對所有表都適用,如果不是則說明。
      AUTO_INCREMENT         你想要為你的表設定的下一個 auto_increment 值 ( MyISAM )
      AVG_ROW_LENGTH         你的表的平均行長度的近似值。你只需要為有變長記錄的表設置它。
      CHECKSUM         如果你想要MySQL對每行維持一個校驗和(使表變得更慢以更新但是使它更容易找出損壞的表)設置它為1 ( MyISAM )
      COMMENT         對于你的表的一篇60個字符的注釋
      MAX_ROWS         你計劃在表中存儲的行的最大數目
      MIN_ROWS         你計劃在表中存儲的行的最小數目
      PACK_KEYS         如果你想要有更小的索引,將它設為1。這通常使的更新更慢並且讀取更快(MyISAM,ISAM)。
      PASSWORD         用一個口令加密.frm文件。該選項在標准MySQL版本中不做任何事情。
      DELAY_KEY_WRITE         如果想要推遲關鍵表的更新直到表被關閉(MyISAM),將它設置為1。
      ROW_FORMAT         定義行應該如何被存儲(為了將來)。

      當你使用一個MyISAM表時,MySQL使用max_rows * avg_row_length的乘積決定最終的表將有多大。如果你不指定上面的任何選項,對一個表的最大尺寸將是4G(或2G,如果你的操作系統僅支持2G的表)。
    * 如果你在CREATE語句後指定一個SELECT,MySQL將為在SELECT中所有的單元創鍵新字段。例如:

      mysql> CREATE TABLE test (a int not null auto_increment,
                 primary key (a), key(b))
                 TYPE=HEAP SELECT b,c from test2;

      這將創建一個有3個列的HEAP表。注意如果在拷貝數據進表時發生任何錯誤,表將自動被刪除。

7.7.1 隱含的列說明改變

在某些情況下,MySQL隱含地改變在一個CREATE TABLE語句給出的一個列說明。(這也可能在ALTER TABLE。)

    * 長度小于4的VARCHAR被改變為CHAR。
    * 如果在一個表中的任何列有可變長度,結果是整個行是變長的。因此, 如果一張表包含任何變長的列(VARCHAR、TEXT或BLOB),所有大于3個字符的CHAR列被改變為VARCHAR列。這在任何方面都不影響你如何使用列;在MySQL中,VARCHAR只是存儲字符的一個不同方法。MySQL實施這種改變,是因為它節省空間並且使表操作更快捷。見10.6 選擇一種表格類型。
    * TIMESTAMP的顯示尺寸必須是偶數且在2 ~ 14的範圍內。如果你指定0顯示尺寸或比14大,尺寸被強制為14。從1~13範圍內的奇數值尺寸被強制為下一個更大的偶數。
    * 你不能在一個TIMESTAMP列里面存儲一個文字NULL;將它設為NULL將設置為當前的日期和時間。因為TIMESTAMP列表現就是這樣,NULL和NOT NULL屬性不以一般的方式運用並且如果你指定他們,將被忽略。DESCRIBE tbl_name總是報告該TIMESTAMP列可能賦予了NULL值。
    * MySQL將其他SQL數據庫供應商使用的某個列類型映射到MySQL類型。見7.3.11 只用其他數據庫引擎的類型。

如果你想要知道MySQL是否使用了除你指定的以外的一種列類型,在創建或改變你的表之後,發出一個DESCRIBE tbl_name語句即可。

如果你使用myisampack壓縮一個表,可能會發生改變某些其他的列類型。見10.6.3 壓縮表的特征。
7.8 ALTER TABLE句法

ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]

alter_specification:
        ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
  or    ADD INDEX [index_name] (index_col_name,...)
  or    ADD PRIMARY KEY (index_col_name,...)
  or    ADD UNIQUE [index_name] (index_col_name,...)
  or    ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  or    CHANGE [COLUMN] old_col_name create_definition
  or    MODIFY [COLUMN] create_definition
  or    DROP [COLUMN] col_name
  or    DROP PRIMARY KEY
  or    DROP INDEX index_name
  or    RENAME [AS] new_tbl_name
  or    table_options

ALTER TABLE允許你修改一個現有表的結構。例如,你可以增加或刪除列、創造或消去索引、改變現有列的類型、或重新命名列或表本身。你也能改變表的注釋和表的類型。見7.7 CREATE TABLE句法。

如果你使用ALTER TABLE修改一個列說明但是DESCRIBE tbl_name顯示你的列並沒有被修改,這可能是MySQL因為在7.7.1 隱含的列說明改變中描述的原因之一而忽略了你的修改。例如,如果你試圖將一個VARCHAR改為CHAR,MySQL將仍然使用VARCHAR,如果表包含其他變長的列。

ALTER TABLE通過制作原來表的一個臨時副本來工作。修改在副本上施行,然後原來的表被刪除並且重新命名一個新的。這樣做使得所有的修改自動地轉向到新表,沒有任何失敗的修改。當ALTER TABLE正在執行時,原來的桌可被其他客戶讀取。更新和寫入表被延遲到新表准備好了為止。

    * 為了使用ALTER TABLE,你需要在表上的select、insert、delete、update、create和drop的權限。
    * IGNORE是MySQL對ANSI SQL92 的一個擴充,如果在新表中的唯一鍵上有重複,它控制ALTER TABLE如何工作。如果IGNORE沒被指定,副本被放棄並且恢複原狀。如果IGNORE被指定,那麼對唯一鍵有重複的行,只有使用第一行;其余被刪除。
    * 你可以在單個ALTER TABLE語句中發出多個ADD、ALTER、DROP和CHANGE子句。這是MySQL對ANSI SQL92的一個擴充,SQL92在每個ALTER TABLE語句中只允許一個子句。
    * CHANGE col_name、DROP col_name和DROP INDEX是MySQL對 ANSI SQL92 的擴充。
    * MODIFY是 Oracle 對ALTER TABLE的擴充。
    * 可選的詞COLUMN是一個純粹的噪音且可以省略。
    * 如果你使用ALTER TABLE tbl_name RENAME AS new_name而沒有任何其他選項,MySQL簡單地重命名對應于表tbl_name的文件。沒有必要創建臨時表。
    * create_definition子句使用CREATE TABLE相同的ADD和CHANGE語法。注意語法包括列名字,不只列類型。見7.7 CREATE TABLE句法。
    * 你可以使用CHANGE old_col_name create_definition子句重命名一個列。為了這樣做,指定舊的和新的列名字和列當前有的類型。例如,重命名一個INTEGER列,從a到b,你可以這樣做:

      mysql> ALTER TABLE t1 CHANGE a b INTEGER;

      如果你想要改變列的類型而非名字,就算他們是一樣的,CHANGE語法仍然需要2個列名。例如:

      mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;

      然而,在MySQL3.22.16a,你也可以使用MODIFY來改變列的類型而不是重命名它:

      mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

    * 如果你使用CHANGE或MODIFY縮短一個列,一個索引存在于該列的部分(例如,如果你有一個VARCHAR列的頭10個字符的索引),你不能使列短于被索引的字符數目。
    * 當你使用CHANGE或MODIFY改變一個列類型時,MySQL盡可能試圖很好地變換數據到新類型。
    * 在MySQL3.22或以後,你能使用FIRST或ADD ... AFTER col_name在一個表的行內在一個特定的位置增加列。缺省是增加到最後一列。
    * ALTER COLUMN為列指定新的缺省值或刪除老的缺省值。如果老的缺省值被刪除且列可以是NULL,新缺省值是NULL。如果列不能是NULL,MySQL賦予一個缺省值。缺省值賦值在7.7 CREATE TABLE句法中描述。
    * DROP INDEX刪除一個索引。這是MySQL對 ANSI SQL92 的一個擴充。
    * 如果列從一張表中被丟棄,列也從他們是組成部分的任何索引中被刪除。如果組成一個索引的所有列被丟棄,該索引也被丟棄。
    * DROP PRIMARY KEY丟棄主索引。如果這樣的索引不存在,它丟棄表中第一個UNIQUE索引。(如果沒有明確地指定PRIMARY KEY,MySQL標記第一個UNIQUE鍵為PRIMARY KEY。)
    * 用 C API 函數mysql_info(),你能找出多少記錄被拷貝, 和(當使用IGNORE時)由于唯一鍵值的重複多少記錄被刪除。
    * FOREIGN KEY、CHECK和REFERENCES子句實際上不做任何事情,他們的句法僅僅提供兼容性,使得更容易地從其他SQL服務器移植代碼並且運行借助引用來創建表的應用程序。見5.4 MySQL缺少的功能。

這里是一個例子,顯示了一些ALTER TABLE用法。我們以一個如下創建的表t1開始:

mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

重命名表,從t1到t2:

mysql> ALTER TABLE t1 RENAME t2;

為了改變列a,從INTEGER改為TINYINT NOT NULL(名字一樣),並且改變列b,從CHAR(10)改為CHAR(20),同時重命名它,從b改為c:

mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

增加一個新TIMESTAMP列,名為d:

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

在列d上增加一個索引,並且使列a為主鍵:

mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

刪出列c:

mysql> ALTER TABLE t2 DROP COLUMN c;

增加一個新的AUTO_INCREMENT整數列,命名為c:

mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
           ADD INDEX (c);

注意,我們索引了c,因為AUTO_INCREMENT柱必須被索引,並且另外我們聲明c為NOT NULL,因為索引了的列不能是NULL。

當你增加一個AUTO_INCREMENT列時,自動地用順序數字填入列值。
7.9 OPTIMIZE TABLE句法

OPTIMIZE TABLE tbl_name

如果你刪除了一個表的大部分或如果你用變長的行對一個表(有VARCHAR、BLOB或TEXT列的表)做了改變,應該使用OPTIMZE TABLE。刪除的記錄以一個鏈接表維持並且隨後的INSERT操作再次使用老記錄的位置。你可以使用OPTIMIZE TABLE回收閒置的空間。

OPTIMIZE TABLE通過制作原來的表的一個臨時副本來工作。老的表子被拷貝到新表中(沒有閒置的行),然後原來的表被刪除並且重命名一個新的。這樣做使得所有更新自動轉向新的表,沒有任何失敗的更新。當時OPTIMIZE TABLE正在執行時,原來的表可被另外的客戶讀取。對表的更新和寫入延遲到新表是准備好為止。
7.10 DROP TABLE句法

DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...]

DROP TABLE刪除一個或多個數據庫表。所有表中的數據和表定義均被刪除,故小心使用這個命令!

在MySQL 3.22或以後版本,你可以使用關鍵詞IF EXISTS類避免不存在表的一個錯誤發生。

7.11 DELETE句法

DELETE [LOW_PRIORITY] FROM tbl_name
    [WHERE where_definition] [LIMIT rows]

DELETE從tbl_name表中刪除滿足由where_definition給出的條件的行,並且返回刪除記錄的個數。

如果你發出一個沒有WHERE子句的DELETE,所有行都被刪除。MySQL通過創建一個空表來完成,它比刪除每行要快。在這種情況下,DELETE返回零作為受影響記錄的數目。(MySQL不能返回實際上被刪除的行數,因為進行再創建而不是打開數據文件。只要表定義文件“tbl_name.frm”是有效的,表才能這樣被再創建,即使數據或索引文件破壞了)。

如果你確實想要知道在你正在刪除所有行時究竟有對少記錄被刪除,並且願意承受速度上的懲罰,你可以這種形式的一個ELETE語句:

mysql> DELETE FROM tbl_name WHERE 1>0;

注意這比沒有WHERE子句的DELETE FROM tbl_name慢的多了,因為它一次刪除一行。

如果你指定關鍵詞LOW_PRIORITY,DELETE的執行被推遲到沒有其他客戶讀取表後。

刪除的記錄以一個鏈接表維持並且隨後的INSERT操作再次使用老的記錄位置。為了回收閒置的空間並減小文件大小,使用OPTIMIZE TABLE語句或myisamchk實用程序重新組織表。OPTIMIZE TABLE較容易,但是myisamchk更快。見7.9 OPTIMIZE TABLE句法和13.4.3 表優化。

MySQL對DELETE特定的LIMIT rows選項告訴服務器在控制被返回到客戶之前,將要刪除的最大行數,這可以用來保証一個特定DELETE命令不會花太多的時間。你可以簡單地重複DELETE命令直到受影響的行數小于LIMIT值。
7.12 SELECT句法

SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [HIGH_PRIORITY]
       [DISTINCT | DISTINCTROW | ALL]
    select_expression,...
    [INTO {OUTFILE | DUMPFILE} 'file_name' export_options]
    [FROM table_references
        [WHERE where_definition]
        [GROUP BY col_name,...]
        [HAVING where_definition]
        [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] ,...]
        [LIMIT [offset,] rows]
        [PROCEDURE procedure_name] ]

SELECT被用來檢索從一個或多個表中精選的行。select_expression指出你想要檢索的列。SELECT也可以用來檢索不引用任何表的計算行。例如:

mysql> SELECT 1 + 1;
         -> 2

所有使用的關鍵詞必須精確地以上面的順序給出。例如,一個HAVING子句必須跟在GROUP BY子句之後和ORDER BY子句之前。

    * 一個SELECT表達式可以用一個AS給定一個別名,別名被用作表達式的列名並且能使用在ORDER BY或HAVING子句中。例如:

      mysql> select concat(last_name,', ',first_name) AS full_name
          from mytable ORDER BY full_name;

    * FROM table_references子句指出從哪個表中檢索行。如果你命名多個表,你正在執行一個聯結(join)。對于聯結的句法信息,見7.13 JOIN句法。
    * 你可以引用一個列為col_name、tbl_name.col_name或db_name.tbl_name.col_name,你不必在一個SELECT語句中指定一個tbl_name或db_name.tbl_name是一個列引用的前綴,除非引用有二義性。見7.1.5 數據庫、表、索引、列和別名命名。對于二義性的例子要求更加顯式的列引用格式。
    * 一個表引用可以使用tbl_name [AS] alias_name起一個別名。

      mysql> select t1.name, t2.salary from employee AS t1, info AS t2
                 where t1.name = t2.name;
      mysql> select t1.name, t2.salary from employee t1, info t2
                 where t1.name = t2.name;

    * 精選輸出的列可以用列名、列別名或列位置在ORDER BY和GROUP BY子句引用,列位置從1開始。

      mysql> select college, region, seed from tournament
                 ORDER BY region, seed;
      mysql> select college, region AS r, seed AS s from tournament
                 ORDER BY r, s;
      mysql> select college, region, seed from tournament
                 ORDER BY 2, 3;

      為了以降序排列,把DESC(下降 )關鍵詞加到ORDER BY子句中你要排序的列名前。缺省是升序;這也可以用ASC關鍵詞明確指定。
    * HAVING子句能引用任何列或在select_expression中命名的別名,它最後運用,就在項目被送到客戶之前,沒有優化。不要對因該在WHERE子句中的項目使用HAVING。例如,不能寫成這樣:

      mysql> select col_name from tbl_name HAVING col_name > 0;

      相反寫成這樣:

      mysql> select col_name from tbl_name WHERE col_name > 0;

      在MySQL 3.22.5或以後,你也能這樣寫查詢:

      mysql> select user,max(salary) from users group by user HAVING max(salary)>10;

      在里面更老的MySQL版本中,你能這樣寫:

      mysql> select user,max(salary) AS sum from users
                 group by user HAVING sum>10;

    * SQL_SMALL_RESULT、SQL_BIG_RESULT、STRAIGHT_JOIN和HIGH_PRIORITY是MySQL對ANSI SQL92的擴展。
    * STRAIGHT_JOIN強制優化器以其列在FROM子句的次序聯結(join)桌子。如果優化器以非最佳次序聯結表,你能使用它加速查詢。見7.22 EXPLAIN句法(得到關于SELECT的信息)。
    * SQL_SMALL_RESULT能與GROUP BY或DISTINCT一起使用告訴優化器結果集將很小。在這種情況下,MySQL將使用快速臨時表存儲最終的表而不是使用排序。 SQL_SMALL_RESULT是一個MySQL擴展。
    * SQL_BIG_RESULT能與GROUP BY或DISTINCT一起使用以告訴優化器結果集合將有很多行。在這種情況下,如果需要,MySQL將直接使用基于磁盤的臨時表。 MySQL在這種情況下將選擇用GROUP BY單元上的鍵值進行排序而不是做一個臨時表。
    * HIGH_PRIORITY將賦予SELECT比一個更新表的語句更高的優先級,你應該僅對非常快的並且必須一次完成的查詢使用它。 如果表為讀而鎖定或甚至有一個等待表釋放的更新語句,一個SELECT HIGH_PRIORITY將運行。
    * LIMIT子句可以被用來限制SELECT語句返回的行數。LIMIT取1個或2個數字參數,如果給定2個參數,第一個指定要返回的第一行的偏移量,第二個指定返回行的最大數目。初始行的偏移量是0(不是1)。

      mysql> select * from table LIMIT 5,10;  # Retrieve rows 6-15

      如果給定一個參數,它指出返回行的最大數目。

      mysql> select * from table LIMIT 5;     # Retrieve first 5 rows

      換句話說,LIMIT n等價于LIMIT 0,n。
    * SELECT ... INTO OUTFILE 'file_name'格式的SELECT語句將選擇的行寫入一個文件。文件在服務器主機上被創建,並且不能是已經存在的(不管別的,這可阻止數據庫表和文件例如“/etc/passwd”被破壞)。在服務器主機上你必須有file權限以使用這種SELECT。SELECT ... INTO OUTFILE是LOAD DATA INFILE逆操作;語句的export_options部分的語法與用在LOAD DATA INFILE語句中的FIELDS和LINES子句的相同。見7.16 LOAD DATA INFILE句法。在最終的文本文件中,只有下列字符由ESCAPED BY字符轉義:
          o ESCAPED BY字符
          o 在FIELDS TERMINATED BY中的第一個字符
          o 在LINES TERMINATED BY中的第一個字符

      另外,ASCII 0被變換到ESCAPED BY後跟0(ASCII 48)。上述的原因是你必須轉義任何FIELDS TERMINATED BY、ESCAPED BY或LINES TERMINATED BY字符以便能可靠地能讀回文件。ASCII 0被轉義使它更容易用分頁器觀看。因為最終的文件不必須遵循SQL句法,沒有別的東西需要轉義。

如果你使用INTO DUMPFILE而不是INTO OUTFILE,MySQL將只寫一行到文件中,沒有任何列或行結束並且沒有任何轉義。如果你想要在一個文件存儲一個blob,這是很有用的。
7.13 JOIN句法

MySQL支持下列用于SELECT語句的JOIN句法:

table_reference, table_reference
table_reference [CROSS] JOIN table_reference
table_reference INNER JOIN table_reference
table_reference STRAIGHT_JOIN table_reference
table_reference LEFT [OUTER] JOIN table_reference ON conditional_expr
table_reference LEFT [OUTER] JOIN table_reference USING (column_list)
table_reference NATURAL LEFT [OUTER] JOIN table_reference
{ oj table_reference LEFT OUTER JOIN table_reference ON conditional_expr }

上述最後的LEFT OUTER JOIN的句法只是為了與ODBC兼容而存在的。

    * 一個表可以是使用aliasedtbl_name AS alias_name或tbl_name alias_name的起的別名。

      mysql> select t1.name, t2.salary from employee AS t1, info AS t2
                 where t1.name = t2.name;

    * INNER JOIN和,(逗號)在語義上是等價的,都是進行一個在使用的表之間的全聯結。通常,你指定表應該如何用WHERE條件聯結起來。
    * ON條件是可以用在一個WHERE子句形式的任何條件。
    * 如果在一個LEFT JOIN中沒有右表的匹配記錄,一個所有列設置為NULL的行被用于右表。你可以使用這個事實指出表中在另一個表中沒有對應記錄的記錄:

      mysql> select table1.* from table1
                 LEFT JOIN table2 ON table1.id=table2.id
                 where table2.id is NULL;

      這個例子找出在table1中所有的行,其id值在table2中不存在(即,所有table1中的在table2中沒有對應行的行)。當然這假定table2.id被聲明為NOT NULL。
    * USING (column_list)子句命名一系列必須存在于兩個表中的列。 例如一個USING子句:

      A LEFT JOIN B USING (C1,C2,C3,...)

      被定義成在語義上等同一個這樣的ON表達式:

      A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...

    * 2個表的NATURAL LEFT JOIN被定義為在語義上等同于一個有USING子句命名在兩表中存在的所有列的一個LEFT JOIN。
    * STRAIGHT_JOIN等同于JOIN,除了左表在右表之前被讀入,這能用于這些情況,聯結優化器將表的順序放錯了。

一些例子:

mysql> select * from table1,table2 where table1.id=table2.id;
mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> select * from table1 LEFT JOIN table2 USING (id);
mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id
           LEFT JOIN table3 ON table2.id=table3.id;

見10.5.4 MySQL怎樣優化LEFT JOIN。
7.14 INSERT句法

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
或  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
或  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name
        SET col_name=expression, col_name=expression, ...

INSERT把新行插入到一個存在的表中,INSERT ... VALUES形式的語句基于明確指定的值插入行,INSERT ... SELECT形式插入從其他表選擇的行,有多個值表的INSERT ... VALUES的形式在MySQL 3.22.5或以後版本中支持,col_name=expression語法在MySQL 3.22.10或以後版本中支持。

tbl_name是行應該被插入其中的表。列名表或SET子句指出語句為那一列指定值。

    * 如果你為INSERT ... VALUES或INSERT ... SELECT不指定列表,所有列的值必須在VALUES()表或由SELECT提供。如果你不知道表中列的順序,使用DESCRIBE tbl_name來找出。
    * 任何沒有明確地給出值的列被設置為它的缺省值。例如,如果你指定一個列表並沒命名表中所有列,未命名的列被設置為它們的缺省值。缺省值賦值在7.7 CREATE TABLE句法中描述。
    * 一個expression可以引用在一個值表先前設置的任何列。例如,你能這樣:

      mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);

      但不能這樣:

      mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);

    * 如果你指定關鍵詞LOW_PRIORITY,INSERT的執行被推遲到沒有其他客戶正在讀取表。在這種情況下,客戶必須等到插入語句完成後,如果表頻繁使用,它可能花很長時間。這與INSERT DELAYED讓客馬上繼續正好相反。
    * 如果你在一個有許多值行的INSERT中指定關鍵詞IGNORE,表中任何複制一個現有PRIMARY或UNIQUE鍵的行被忽略並且不被插入。如果你不指定IGNORE,插入如果有任何複制現有關鍵值的行被放棄。你可用C API函數mysql_info()檢查多少行被插入到表中。
    * 如果MySQL用DONT_USE_DEFAULT_FIELDS選項配置,INSERT語句產生一個錯誤,除非你明確對需要一個非NULL值的所有列指定值。見4.7.3 典型configure選項。
    * INSERT INTO ... SELECT語句滿足下列條件:
          o 查詢不能包含一個ORDER BY子句。
          o INSERT語句的目的表不能出現在SELECT查詢部分的FROM子句,因為這在ANSI SQL中被禁止讓從你正在插入的表中SELECT。(問題是SELECT將可能發現在同一個運行期間內先前被插入的記錄。當使用子選擇子句時,情況能很容易混淆)
          o AUTO_INCREMENT列象往常一樣工作。

如果你使用INSERT ... SELECT或INSERT ... VALUES語句有多個值列表,你可以使用C API函數mysql_info()得到查詢的信息。信息字符串的格式如下:

Records: 100 Duplicates: 0 Warnings: 0

Duplicates指出不能被插入的行的數量,因為他們與現有的唯一的索引值重複。Warnings指出在出現某些問題時嘗試插入列值的次數。在下列任何條件下都可能發生錯誤:

    * 插入NULL到被聲明了NOT NULL的列,列被設置為它的缺省值。
    * 將超出列範圍的值設置給一個數字列,值被剪切為範圍內適當的端點值。
    * 將數字列設成例如'10.34 a'的值,拖尾的垃圾被剝去並仍然是數字部分被插入。如果值根本不是一個數字,列被設置到0。
    * 把一個字符串插入到超過列的最大長度的一個CHAR、VARCHAR、TEXT或BLOB列中。值被截斷為列的最大長度。
    * 把一個對列類型不合法的值插入到一個日期或時間列。列被設置為該列類型適當的“零”值。

對于INSERT語句的DELAYED選項是MySQL專屬的選項-如果你客戶有不能等到INSERT完成,它是很有用的。當你為日記登錄使用MySQL時,而且你也周期性地運行花很長時間完成的SELECT語句,這是一個常見的問題。DELAYED在面MySQL 3.22.15中被引入,它是MySQL對 ANSI SQL92 的一個擴展。

當你使用INSERT DELAYED時,客戶將馬上准備好,並且當表不被任何其他的線程使用時,行將被插入。

另一個使用INSERT DELAYED的主要好處是從很多客戶插入被捆綁在一起並且寫進一個塊。這比做很多單獨的插入要來的快。

注意,當前排隊的行只是存儲在內存中,直到他們被插入到表中。這意味著,如果你硬要殺死mysqld(kill -9)或如果mysqld出人意料地死掉,沒被寫進磁盤的任何排隊的行被丟失!

下列詳細描述當你為INSERT或REPLACE使用DELAYED選項時,發生什麼。在這個描述中,“線程”是收到一個INSERT DELAYED命令的線程並且“處理器”是處理所有對于一個特定表的INSERT DELAYED語句。

    * 當一個線程對一個表執行一個DELAYED語句時,如果不存在這樣的處理程序,一個處理器線程被創建以處理對于該表的所有DELAYED語句。
    * 線程檢查處理程序是否已經獲得了一個DELAYED鎖;如果沒有,它告訴處理程序去獲得。即使其他的線程有在表上的一個READ或WRITE鎖,也能獲得DELAYED鎖。然而,處理程序將等待所有ALTER TABLE鎖或FLUSH TABLES以保証表結構是最新的。
    * 線程執行INSERT語句,但不是將行寫入表,它把最後一行的副本放進被處理器線程管理的一個隊列。任何語法錯誤都能被線程發覺並報告給客戶程序。
    * 顧客不能報告結果行的重複次數或AUTO_INCREMENT值;它不能從服務器獲得它們,因為INSERT在插入操作完成前返回。如果你使用C API,同樣原因,mysql_info()函數不返回任何有意義的東西。
    * 當行被插入到表中時,更新日志有處理器線程更新。在多行插入的情況下,當第一行被插入時,更新日志被更新。
    * 在每寫入delayed_insert_limit行後,處理器檢查是否任何SELECT語句仍然是未完成,如果這樣,在繼續之前允許執行這些語句。
    * 當處理器在它的隊列中沒有更多行時,表被解鎖。如果在delayed_insert_timeout秒內沒有收到新的INSERT DELAYED命令,處理器終止。
    * 如果已經有多于delayed_queue_size行在一個特定的處理器隊列中未解決,線程等待直到隊列有空間。這有助于保証mysqld服務器對延遲的內存隊列不使用所有內存。
    * 處理器線程將在Command列的MySQL進程表中顯示delayed_insert。如果你執行一個FLUSH TABLES命令或以KILL thread_id殺死它,它將被殺死,然而,它在退出前首先將所有排隊的行存進表中。在這期間,這次它將不從其他線程接受任何新的INSERT命令。如果你在它之後執行一個INSERT DELAYED,將創建一個新的處理器線程。
    * 注意,上述意味著,如果有一個INSERT DELAYED處理器已經運行,INSERT DELAYED命令有比正常INSERT更高的優先級!其他更新命令將必須等到INSERT DELAY排隊變空、殺死處理器線程(用KILL thread_id)或執行FLUSH TABLES。
    * 下列狀態變量提供了關于INSERT DELAYED命令的信息:
      Delayed_insert_threads         處理器線程數量
      Delayed_writes         用INSERT DELAYED被寫入的行的數量
      Not_flushed_delayed_rows         等待被寫入的行數字

      你能通過發出一個SHOW STATUS語句或通過執行一個mysqladmin extended-status命令察看這些變量。

注意如果桌子不在使用,INSERT DELAYED比一個正常的INSERT慢。對服務器也有額外開銷來處理你對它使用INSERT DELAYED的每個表的一個單獨線程。這意味著,你應該只在你確實肯定需要它的時候才使用INSERT DELAYED!

7.15 REPLACE句法

    REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...)
或  REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
或  REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name
        SET col_name=expression, col_name=expression,...


REPLACE功能與INSERT完全一樣,除了如果在表中的一個老記錄具有在一個唯一索引上的新記錄有相同的值,在新記錄被插入之前,老記錄被刪除。見7.14 INSERT句法。

7.16 LOAD DATA INFILE句法

LOAD DATA [LOW_PRIORITY] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [FIELDS
        [TERMINATED BY '\t']
        [OPTIONALLY] ENCLOSED BY '']
        [ESCAPED BY '\\' ]]
    [LINES TERMINATED BY '\n']
    [IGNORE number LINES]
    [(col_name,...)]

LOAD DATA INFILE語句從一個文本文件中以很高的速度讀入一個表中。如果指定LOCAL關鍵詞,從客戶主機讀文件。如果LOCAL沒指定,文件必須位于服務器上。(LOCAL在MySQL3.22.6或以後版本中可用。)

為了安全原因,當讀取位于服務器上的文本文件時,文件必須處于數據庫目錄或可被所有人讀取。另外,為了對服務器上文件使用LOAD DATA INFILE,在服務器主機上你必須有file的權限。見6.5 由MySQL提供的權限。

如果你指定關鍵詞LOW_PRIORITY,LOAD DATA語句的執行被推遲到沒有其他客戶讀取表後。

使用LOCAL將比讓服務器直接存取文件慢些,因為文件的內容必須從客戶主機傳送到服務器主機。在另一方面,你不需要file權限裝載本地文件。

你也可以使用mysqlimport實用程序裝載數據文件;它由發送一個LOAD DATA INFILE命令到服務器來運作。 --local選項使得mysqlimport從客戶主機上讀取數據。如果客戶和服務器支持壓縮協議,你能指定--compress在較慢的網絡上獲得更好的性能。

當在服務器主機上尋找文件時,服務器使用下列規則:

    * 如果給出一個絕對路徑名,服務器使用該路徑名。
    * 如果給出一個有一個或多個前置部件的相對路徑名,服務器相對服務器的數據目錄搜索文件。
    * 如果給出一個沒有前置部件的一個文件名,服務器在當前數據庫的數據庫目錄尋找文件。

注意這些規則意味著一個像“./myfile.txt”給出的文件是從服務器的數據目錄讀取,而作為“myfile.txt”給出的一個文件是從當前數據庫的數據庫目錄下讀取。也要注意,對于下列哪些語句,對db1文件從數據庫目錄讀取,而不是db2:

mysql> USE db1;
mysql> LOAD DATA INFILE "./data.txt" INTO TABLE db2.my_table;

REPLACE和IGNORE關鍵詞控制對現有的唯一鍵記錄的重複的處理。如果你指定REPLACE,新行將代替有相同的唯一鍵值的現有行。如果你指定IGNORE,跳過有唯一鍵的現有行的重複行的輸入。如果你不指定任何一個選項,當找到重複鍵鍵時,出現一個錯誤,並且文本文件的余下部分被忽略時。

如果你使用LOCAL關鍵詞從一個本地文件裝載數據,服務器沒有辦法在操作的當中停止文件的傳輸,因此缺省的行為好像IGNORE被指定一樣。

LOAD DATA INFILE是SELECT ... INTO OUTFILE的逆操作,見7.12 SELECT句法。為了將一個數據庫的數據寫入一個文件,使用SELECT ... INTO OUTFILE,為了將文件讀回數據庫,使用LOAD DATA INFILE。兩個命令的FIELDS和LINES子句的語法是相同的。兩個子句是可選的,但是如果指定兩個,FIELDS必須在LINES之前。

如果你指定一個FIELDS子句,它的每一個子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BY和ESCAPED BY)也是可選的,除了你必須至少指定他們之一。

如果你不指定一個FIELDS子句,缺省值與如果你這樣寫的相同:

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

如果你不指定一個LINES子句,缺省值與如果你這樣寫的相同:

LINES TERMINATED BY '\n'

換句話說,缺省值導致讀取輸入時,LOAD DATA INFILE表現如下:

    * 在換行符處尋找行邊界
    * 在定位符處將行分進字段
    * 不要期望字段由任何引號字符封裝
    * 將由“\”開頭的定位符、換行符或“\”解釋是字段值的部分字面字符

相反,缺省值導致在寫入輸出時,SELECT ... INTO OUTFILE表現如下:

    * 在字段之間寫定位符
    * 不用任何引號字符封裝字段
    * 使用“\”轉義出現在字段中的定位符、換行符或“\”字符
    * 在行尾處寫換行符

注意,為了寫入FIELDS ESCAPED BY '\\',對作為一條單個的反斜線被讀取的值,你必須指定2條反斜線值。

IGNORE number LINES選項可被用來忽略在文件開始的一個列名字的頭:

mysql> LOAD DATA INFILE "/tmp/file_name" into table test IGNORE 1 LINES;

當你與LOAD DATA INFILE一起使用SELECT ... INTO OUTFILE將一個數據庫的數據寫進一個文件並且隨後馬上將文件讀回數據庫時,兩個命令的字段和處理選項必須匹配,否則,LOAD DATA INFILE將不能正確解釋文件的內容。假定你使用SELECT ... INTO OUTFILE將由逗號分隔的字段寫入一個文件:

mysql> SELECT * FROM table1 INTO OUTFILE 'data.txt'
           FIELDS TERMINATED BY ','
           FROM ...

為了將由逗號分隔的文件讀回來,正確的語句將是:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
           FIELDS TERMINATED BY ',';

相反,如果你試圖用下面顯示的語句讀取文件,它不會工作,因為它命令LOAD DATA INFILE在字段之間尋找定位符:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
           FIELDS TERMINATED BY '\t';

可能的結果是每個輸入行將被解釋為單個的字段。

LOAD DATA INFILE能被用來讀取從外部來源獲得的文件。例如,以dBASE格式的文件將有由逗號分隔並用雙引號包圍的字段。如果文件中的行由換行符終止,下面顯示的命令說明你將用來裝載文件的字段和行處理選項:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
           LINES TERMINATED BY '\n';

任何字段或行處理選項可以指定一個空字符串('')。如果不是空,FIELDS [OPTIONALLY] ENCLOSED BY和FIELDS ESCAPED BY值必須是一個單個字符。FIELDS TERMINATED BY和LINES TERMINATED BY值可以是超過一個字符。例如,寫入由回車換行符對(CR+LF)終止的行,或讀取包含這樣行的一個文件,指定一個LINES TERMINATED BY '\r\n'子句。

FIELDS [OPTIONALLY] ENCLOSED BY控制字段的包圍字符。對于輸出(SELECT ... INTO OUTFILE),如果你省略OPTIONALLY,所有的字段由ENCLOSED BY字符包圍。對于這樣的輸出的一個例子(使用一個逗號作為字段分隔符)顯示在下面:

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

如果你指定OPTIONALLY,ENCLOSED BY字符僅被用于包圍CHAR和VARCHAR字段:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

注意,一個字段值中的ENCLOSED BY字符的出現通過用ESCAPED BY字符作為其前綴來轉義。也要注意,如果你指定一個空ESCAPED BY值,可能產生不能被LOAD DATA INFILE正確讀出的輸出。例如,如果轉義字符為空,上面顯示的輸出顯示如下。注意到在第四行的第二個字段包含跟隨引號的一個逗號,它(錯誤地)好象要終止字段:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

對于輸入,ENCLOSED BY字符如果存在,它從字段值的尾部被剝去。(不管是否指定OPTIONALLY都是這樣;OPTIONALLY對于輸入解釋不起作用)由ENCLOSED BY字符領先的ESCAPED BY字符出現被解釋為當前字段值的一部分。另外,出現在字段中重複的ENCLOSED BY被解釋為單個ENCLOSED BY字符,如果字段本身以該字符開始。例如,如果ENCLOSED BY '"'被指定,引號如下處理:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY控制如何寫入或讀出特殊字符。如果FIELDS ESCAPED BY字符不是空的,它被用于前綴在輸出上的下列字符:

    * FIELDS ESCAPED BY字符
    * FIELDS [OPTIONALLY] ENCLOSED BY字符
    * FIELDS TERMINATED BY和LINES TERMINATED BY值的第一個字符
    * ASCII 0(實際上將後續轉義字符寫成 ASCII'0',而不是一個零值字節)

如果FIELDS ESCAPED BY字符是空的,沒有字符被轉義。指定一個空轉義字符可能不是一個好主意,特別是如果在你數據中的字段值包含剛才給出的表中的任何字符。

對于輸入,如果FIELDS ESCAPED BY字符不是空的,該字符的出現被剝去並且後續字符在字面上作為字段值的一個部分。例外是一個轉義的“0”或“N”(即,\0或\N,如果轉義字符是“\”)。這些序列被解釋為ASCII 0(一個零值字節)和NULL。見下面關于NULL處理的規則。

對于更多關于“\”- 轉義句法的信息,見7.1 文字:怎樣寫字符串和數字。

在某些情況下,字段和行處理選項相互作用:

    * 如果LINES TERMINATED BY是一個空字符串並且FIELDS TERMINATED BY是非空的,行也用FIELDS TERMINATED BY終止。
    * 如果FIELDS TERMINATED BY和FIELDS ENCLOSED BY值都是空的(''),一個固定行(非限定的)格式被使用。用固定行格式,在字段之間不使用分隔符。相反,列值只用列的“顯示”寬度被寫入和讀出。例如,如果列被聲明為INT(7),列的值使用7個字符的字段被寫入。對于輸入,列值通過讀取7個字符獲得。固定行格式也影響NULL值的處理;見下面。注意如果你正在使用一個多字節字符集,固定長度格式將不工作。

NULL值的處理有多種,取決于你使用的FIELDS和LINES選項:

    * 對于缺省FIELDS和LINES值,對輸出,NULL被寫成\N,對輸入,\N被作為NULL讀入(假定ESCAPED BY字符是“\”)。
    * 如果FIELDS ENCLOSED BY不是空的,包含以文字詞的NULL作為它的值的字段作為一個NULL值被讀入(這不同于包圍在FIELDS ENCLOSED BY字符中的字NULL,它作為字符串'NULL'讀入)。
    * 如果FIELDS ESCAPED BY是空的,NULL作為字NULL被寫入。
    * 用固定行格式(它發生在FIELDS TERMINATED BY和FIELDS ENCLOSED BY都是空的時候),NULL作為一個空字符串被寫入。注意,在寫入文件時,這導致NULL和空字符串在表中不能區分,因為他們都作為空字符串被寫入。如果在讀回文件時需要能區分這兩者,你應該不使用固定行格式。

一些不被LOAD DATA INFILE支持的情況:

    * 固定長度的行(FIELDS TERMINATED BY和FIELDS ENCLOSED BY都為空)和BLOB或TEXT列。
    * 如果你指定一個分隔符與另一個相同,或是另一個的前綴,LOAD DATA INFILE不能正確地解釋輸入。例如,下列FIELDS子句將導致問題:

      FIELDS TERMINATED BY '"' ENCLOSED BY '"'

    * 如果FIELDS ESCAPED BY是空的,一個包含跟隨FIELDS TERMINATED BY值之後的FIELDS ENCLOSED BY或LINES TERMINATED BY的字段值將使得LOAD DATA INFILE過早地終止讀取一個字段或行。這是因為LOAD DATA INFILE不能正確地決定字段或行值在哪兒結束。

下列例子裝載所有persondata表的行:

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

沒有指定字段表,所以LOAD DATA INFILE期望輸入行對每個表列包含一個字段。使用缺省FIELDS和LINES值。

如果你希望僅僅裝載一張表的某些列,指定一個字段表:

mysql> LOAD DATA INFILE 'persondata.txt'
           INTO TABLE persondata (col1,col2,...);

如果在輸入文件中的字段順序不同于表中列的順序,你也必須指定一個字段表。否則,MySQL不能知道如何匹配輸入字段和表中的列。

如果一個行有很少的字段,對于不存在輸入字段的列被設置為缺省值。缺省值賦值在7.7 CREATE TABLE句法中描述。

如果字段值缺省,空字段值有不同的解釋:

    * 對于字符串類型,列被設置為空字符串。
    * 對于數字類型,列被設置為0。
    * 對于日期和時間類型,列被設置為該類型的適當“零”值。見7.3.6 日期和時間類型。

如果列有一個NULL,或(只對第一個TIMESTAMP列)在指定一個字段表時,如果TIMESTAMP列從字段表省掉,TIMESTAMP列只被設置為當前的日期和時間。

如果輸入行有太多的字段,多余的字段被忽略並且警告數字加1。

LOAD DATA INFILE認為所有的輸入是字符串,因此你不能像你能用INSERT語句的ENUM或SET列的方式使用數字值。所有的ENUM和SET值必須作為字符串被指定!

如果你正在使用C API,當LOAD DATA INFILE查詢完成時,你可通過調用API函數mysql_info()得到有關查詢的信息。信息字符串的格式顯示在下面:

Records: 1 Deleted: 0 Skipped: 0 Warnings: 0

當值通過INSERT語句插入時,在某些情況下出現警告(見7.14 INSERT句法),除了在輸入行中有太少或太多的字段時,LOAD DATA INFILE也產生警告。警告沒被存儲在任何地方;警告數字僅能用于表明一切是否順利。如果你得到警告並且想要確切知道你為什麼得到他們,一個方法是使用SELECT ... INTO OUTFILE到另外一個文件並且把它與你的原版輸入文件比較。

對于有關INSERT相對LOAD DATA INFILE的效率和加快LOAD DATA INFILE的更多信息,見10.5.6 加速INSERT查詢。

 
7.17 UPDATE句法

UPDATE [LOW_PRIORITY] tbl_name SET col_name1=expr1,col_name2=expr2,...
    [WHERE where_definition] [LIMIT #]

UPDATE用新值更新現存表中行的列,SET子句指出哪個列要修改和他們應該被給定的值,WHERE子句,如果給出,指定哪個行應該被更新,否則所有行被更新。

如果你指定關鍵詞LOW_PRIORITY,執行UPDATE被推遲到沒有其他客戶正在讀取表時。

如果你從一個表達式的tbl_name存取列,UPDATE使用列的當前值。例如,下列語句設置age為它的當前值加1:

mysql> UPDATE persondata SET age=age+1;

UPDATE賦值是從左到右計算。例如,下列語句兩倍age列,然後加1:

mysql> UPDATE persondata SET age=age*2, age=age+1;

如果你設置列為其它當前有的值,MySQL注意到這點並且不更新它。

UPDATE返回實際上被改變的行的數量。在MySQL 3.22或以後版本中,C API函數mysql_info()返回被匹配並且更新的行數和在UPDATE期間發生警告的數量。

在MySQL3.23中,你可使用LIMIT #來保証只有一個給定數量的行被改變。

 
7.18 USE句法

USE db_name

USE db_name語句告訴MySQL使用db_name數據庫作為隨後的查詢的缺省數據庫。數據庫保持到會話結束,或發出另外一個USE語句:

mysql> USE db1;
mysql> SELECT count(*) FROM mytable;      # selects from db1.mytable
mysql> USE db2;
mysql> SELECT count(*) FROM mytable;      # selects from db2.mytable

利用USE語句使得一個特定的數據庫稱為當前數據庫並不阻止你訪問在另外的數據庫中的表。下面的例子訪問db1數據庫中的author表和db2數據庫中的editor表:

mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
           WHERE author.editor_id = db2.editor.editor_id;

USE語句提供了Sybase的兼容性。

 
7.19 FLUSH句法(清除緩存)

FLUSH flush_option [,flush_option]

如果你想要清除一些MySQL使用內部緩存,你應該使用FLUSH命令。為了執行FLUSH,你必須有reload權限。

flush_option可以是下列任何東西:
HOSTS         清空主機緩存表。如果你的某些主機改變IP數字,或如果你得到錯誤消息Host ... is blocked,你應該清空主機表。當在連接MySQL服務器時,對一台給定的主機有多于max_connect_errors個錯誤連續不斷地發生,MySQL認定某些東西錯了並且阻止主機進一步的連接請求。清空主機表允許主機再嘗試連接。見18.2.3 Host '...' is blocked錯誤)。你可用-O max_connection_errors=999999999啟動mysqld來避免這條錯誤消息。
LOGS         關閉並且再打開標准和更新記錄文件。如果你指定了一個沒有擴展名的更新記錄文件,新的更新記錄文件的擴展數字將相對先前的文件加1。
PRIVILEGES         從mysql數據庫授權表中重新裝載權限。
TABLES         關閉所有打開的表。
STATUS         重置大多數狀態變量到0。

你也可以用mysqladmin實用程序,使用flush-hosts, flush-logs, reload或flush-tables命令來訪問上述的每一個命令。

 
7.20 KILL句法

KILL thread_id

每個對mysqld的連接以一個單獨的線程運行。你可以用看SHOW PROCESSLIST命令察看哪個線程正在運行,並且用KILL thread_id命令殺死一個線程。

如果你有process權限,你能看到並且殺死所有線程。否則,你只能看到並且殺死你自己的線程。

你也可以使用mysqladmin processlist和mysqladmin kill命令檢查並殺死線程。

TOP

7.21 SHOW句法 (得到表,列等的信息)

   SHOW DATABASES [LIKE wild]
or SHOW TABLES [FROM db_name] [LIKE wild]
or SHOW COLUMNS FROM tbl_name [FROM db_name] [LIKE wild]
or SHOW INDEX FROM tbl_name [FROM db_name]
or SHOW STATUS
or SHOW VARIABLES [LIKE wild]
or SHOW [FULL] PROCESSLIST
or SHOW TABLE STATUS [FROM db_name] [LIKE wild]
or SHOW GRANTS FOR user

SHOW提供關于數據庫、桌子、列或服務器的信息。如果使用LIKE wild部分,wild字符串可以是一個使用SQL的“%”和“_”通配符的字符串。

你能使用db_name.tbl_name作為tbl_name FROM db_name句法的另一種選擇。這兩個語句是相等的:

mysql> SHOW INDEX FROM mytable FROM mydb;
mysql> SHOW INDEX FROM mydb.mytable;

SHOW DATABASES列出在MySQL服務器主機上的數據庫。你也可以用mysqlshow命令得到這張表。

SHOW TABLES列出在一個給定的數據庫中的表。你也可以用mysqlshow db_name命令得到這張表。

注意:如果一個用戶沒有一個表的任何權限,表將不在SHOW TABLES或mysqlshow db_name中的輸出中顯示。

SHOW COLUMNS列出在一個給定表中的列。如果列類型不同于你期望的是基于CREATE TABLE語句的那樣,注意,MySQL有時改變列類型。見7.7.1 隱含的列說明變化。

DESCRIBE語句提供了類似SHOW COLUMNS的信息。見7.23 DESCRIBE 句法 (得到列的信息)。

SHOW TABLE STATUS(在版本3.23引入)運行類似SHOW STATUS,但是提供每個表的更多信息。你也可以使用mysqlshow --status db_name命令得到這張表。下面的列被返回:
列         含義
Name         表名
Type         表的類型 (ISAM,MyISAM或HEAP)
Row_format         行存儲格式 (固定, 動態, 或壓縮)
Rows         行數量
Avg_row_length         平均行長度
Data_length         數據文件的長度
Max_data_length         數據文件的最大長度
Index_length         索引文件的長度
Data_free         已分配但未使用了字節數
Auto_increment         下一個 autoincrement(自動加1)值
Create_time         表被創造的時間
Update_time         數據文件最後更新的時間
Check_time         最後對表運行一個檢查的時間
Create_options         與CREATE TABLE一起使用的額外選項
Comment         當創造表時,使用的注釋 (或為什麼MySQL不能存取表信息的一些信息)。

SHOW FIELDS是SHOW COLUMNS一個同義詞,SHOW KEYS是SHOW INDEX一個同義詞。你也可以用mysqlshow db_name tbl_name或mysqlshow -k db_name tbl_name 列出一張表的列或索引。

SHOW INDEX以非常相似于ODBC的SQLStatistics調用的格式返回索引信息。下面的列被返回:
列         含義
Table         表名
Non_unique         0,如果索引不能包含重複。
Key_name         索引名
Seq_in_index         索引中的列順序號, 從 1 開始。
Column_name         列名。
Collation         列怎樣在索引中被排序。在MySQL中,這可以有值A(升序) 或NULL(不排序)。
Cardinality         索引中唯一值的數量。這可通過運行isamchk -a更改.
Sub_part         如果列只是部分被索引,索引字符的數量。NULL,如果整個鍵被索引。

SHOW STATUS提供服務器的狀態信息(象mysqladmin extended-status一樣)。輸出類似于下面的顯示,盡管格式和數字可以有點不同:

+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| Aborted_clients          | 0      |
| Aborted_connects         | 0      |
| Connections              | 17     |
| Created_tmp_tables       | 0      |
| Delayed_insert_threads   | 0      |
| Delayed_writes           | 0      |
| Delayed_errors           | 0      |
| Flush_commands           | 2      |
| Handler_delete           | 2      |
| Handler_read_first       | 0      |
| Handler_read_key         | 1      |
| Handler_read_next        | 0      |
| Handler_read_rnd         | 35     |
| Handler_update           | 0      |
| Handler_write            | 2      |
| Key_blocks_used          | 0      |
| Key_read_requests        | 0      |
| Key_reads                | 0      |
| Key_write_requests       | 0      |
| Key_writes               | 0      |
| Max_used_connections     | 1      |
| Not_flushed_key_blocks   | 0      |
| Not_flushed_delayed_rows | 0      |
| Open_tables              | 1      |
| Open_files               | 2      |
| Open_streams             | 0      |
| Opened_tables            | 11     |
| Questions                | 14     |
| Slow_queries             | 0      |
| Threads_connected        | 1      |
| Threads_running          | 1      |
| Uptime                   | 149111 |
+--------------------------+--------+

上面列出的狀態變量有下列含義:
Aborted_clients         由于客戶沒有正確關閉連接已經死掉,已經放棄的連接數量。
Aborted_connects         嘗試已經失敗的MySQL服務器的連接的次數。
Connections         試圖連接MySQL服務器的次數。
Created_tmp_tables         當執行語句時,已經被創造了的隱含臨時表的數量。
Delayed_insert_threads         正在使用的延遲插入處理器線程的數量。
Delayed_writes         用INSERT DELAYED寫入的行數。
Delayed_errors         用INSERT DELAYED寫入的發生某些錯誤(可能重複鍵值)的行數。
Flush_commands         執行FLUSH命令的次數。
Handler_delete         請求從一張表中刪除行的次數。
Handler_read_first         請求讀入表中第一行的次數。
Handler_read_key         請求數字基于鍵讀行。
Handler_read_next         請求讀入基于一個鍵的一行的次數。
Handler_read_rnd         請求讀入基于一個固定位置的一行的次數。
Handler_update         請求更新表中一行的次數。
Handler_write         請求向表中插入一行的次數。
Key_blocks_used         用于關鍵字緩存的塊的數量。
Key_read_requests         請求從緩存讀入一個鍵值的次數。
Key_reads         從磁盤物理讀入一個鍵值的次數。
Key_write_requests         請求將一個關鍵字塊寫入緩存次數。
Key_writes         將一個鍵值塊物理寫入磁盤的次數。
Max_used_connections         同時使用的連接的最大數目。
Not_flushed_key_blocks         在鍵緩存中已經改變但是還沒被清空到磁盤上的鍵塊。
Not_flushed_delayed_rows         在INSERT DELAY隊列中等待寫入的行的數量。
Open_tables         打開表的數量。
Open_files         打開文件的數量。
Open_streams         打開流的數量(主要用于日志記載)
Opened_tables         已經打開的表的數量。
Questions         發往服務器的查詢的數量。
Slow_queries         要花超過long_query_time時間的查詢數量。
Threads_connected         當前打開的連接的數量。
Threads_running         不在睡眠的線程數量。
Uptime         服務器工作了多少秒。

關于上面的一些注釋:

    * 如果Opened_tables太大,那麼你的table_cache變量可能太小。
    * 如果key_reads太大,那麼你的key_cache可能太小。緩存命中率可以用key_reads/key_read_requests計算。
    * 如果Handler_read_rnd太大,那麼你很可能有大量的查詢需要MySQL掃描整個表或你有沒正確使用鍵值的聯結(join)。

SHOW VARIABLES顯示出一些MySQL系統變量的值,你也能使用mysqladmin variables命令得到這個信息。如果缺省值不合適,你能在mysqld啟動時使用命令行選項來設置這些變量的大多數。輸出類似于下面的顯示,盡管格式和數字可以有點不同:

+------------------------+--------------------------+
| Variable_name          | Value                    |
+------------------------+--------------------------+
| back_log               | 5                        |
| connect_timeout        | 5                        |
| basedir                | /my/monty/               |
| datadir                | /my/monty/data/          |
| delayed_insert_limit   | 100                      |
| delayed_insert_timeout | 300                      |
| delayed_queue_size     | 1000                     |
| join_buffer_size       | 131072                   |
| flush_time             | 0                        |
| interactive_timeout    | 28800                    |
| key_buffer_size        | 1048540                  |
| language               | /my/monty/share/english/ |
| log                    | OFF                      |
| log_update             | OFF                      |
| long_query_time        | 10                       |
| low_priority_updates   | OFF                      |
| max_allowed_packet     | 1048576                  |
| max_connections        | 100                      |
| max_connect_errors     | 10                       |
| max_delayed_threads    | 20                       |
| max_heap_table_size    | 16777216                 |
| max_join_size          | 4294967295               |
| max_sort_length        | 1024                     |
| max_tmp_tables         | 32                       |
| net_buffer_length      | 16384                    |
| port                   | 3306                     |
| protocol-version       | 10                       |
| record_buffer          | 131072                   |
| skip_locking           | ON                       |
| socket                 | /tmp/mysql.sock          |
| sort_buffer            | 2097116                  |
| table_cache            | 64                       |
| thread_stack           | 131072                   |
| tmp_table_size         | 1048576                  |
| tmpdir                 | /machine/tmp/            |
| version                | 3.23.0-alpha-debug       |
| wait_timeout           | 28800                    |
+------------------------+--------------------------+

見10.2.3 調節服務器參數。

SHOW PROCESSLIST顯示哪個線程正在運行,你也能使用mysqladmin processlist命令得到這個信息。如果你有process權限, 你能看見所有的線程,否則,你僅能看見你自己的線程。見7.20 KILL句法。如果你不使用FULL選項,那麼每個查詢只有頭100字符被顯示出來。

SHOW GRANTS FOR user列出對一個用戶必須發出以重複授權的授權命令。

mysql> SHOW GRANTS FOR root@localhost;
+---------------------------------------------------------------------+
| Grants for root@localhost                                           |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root''localhost' WITH GRANT OPTION  |
+---------------------------------------------------------------------+
  

7.22 EXPLAIN句法(得到關于SELECT的信息)

    EXPLAIN tbl_name
or  EXPLAIN SELECT select_options

EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name的一個同義詞。

當你在一條SELECT語句前放上關鍵詞EXPLAIN,MySQL解釋它將如何處理SELECT,提供有關表如何聯結和以什麼次序聯結的信息。

借助于EXPLAIN,你可以知道你什麼時候必須為表加入索引以得到一個使用索引找到記錄的更快的SELECT。你也能知道優化器是否以一個最佳次序聯結表。為了強制優化器對一個SELECT語句使用一個特定聯結次序,增加一個STRAIGHT_JOIN子句。

對于非簡單的聯結,EXPLAIN為用于SELECT語句中的每個表返回一行信息。表以他們將被讀入的順序被列出。MySQL用一邊掃描多次聯結的方式解決所有聯結,這意味著MySQL從第一個表中讀一行,然後找到在第二個表中的一個匹配行,然後在第3個表中等等。當所有的表被處理完,它輸出選擇的列並且回溯表列表直到找到一個表有更多的匹配行,從該表讀入下一行並繼續處理下一個表。

從EXPLAIN的輸出包括下面列:

table
    輸出的行所引用的表。
type
    聯結類型。各種類型的信息在下面給出。
possible_keys
    possible_keys列指出MySQL能使用哪個索引在該表中找到行。注意,該列完全獨立于表的次序。這意味著在possible_keys中的某些鍵實際上不能以生成的表次序使用。如果該列是空的,沒有相關的索引。在這種情況下,你也許能通過檢驗WHERE子句看是否它引用某些列或列不是適合索引來提高你的查詢性能。如果是這樣,創造一個適當的索引並且在用EXPLAIN檢查查詢。見7.8 ALTER TABLE句法。為了看清一張表有什麼索引,使用SHOW INDEX FROM tbl_name。
key
    key列顯示MySQL實際決定使用的鍵。如果沒有索引被選擇,鍵是NULL。
key_len
    key_len列顯示MySQL決定使用的鍵長度。如果鍵是NULL,長度是NULL。注意這告訴我們MySQL將實際使用一個多部鍵值的幾個部分。
ref
    ref列顯示哪個列或常數與key一起用于從表中選擇行。
rows
    rows列顯示MySQL相信它必須檢驗以執行查詢的行數。
Extra
    如果Extra列包括文字Only index,這意味著信息只用索引樹中的信息檢索出的。通常,這比掃描整個表要快。如果Extra列包括文字where used,它意味著一個WHERE子句將被用來限制哪些行與下一個表匹配或發向客戶。

不同的聯結類型列在下面,以最好到最差類型的次序:

system
    桌子僅有一行(=系統表)。這是const聯結類型的一個特例。
const
    桌子有最多一個匹配行,它將在查詢開始時被讀取。因為僅有一行,在這行的列值可被剩下的優化器認為是常數。 const表很快,因為它們只讀取一次!
eq_ref
    對于每個來自于先前的表的行組合,從該表中讀取一行。這可能是最好的聯結類型,除了const類型。它用在一個索引的所有部分被聯結使用並且索引是UNIQUE或PRIMARY KEY。
ref
    對于每個來自于先前的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯結只使用鍵的最左面前綴,或如果鍵不是UNIQUE或PRIMARY KEY(換句話說,如果聯結不能基于鍵值選擇單個行的話),使用ref。如果被使用的鍵僅僅匹配一些行,該聯結類型是不錯的。
range
    只有在一個給定範圍的行將被檢索,使用一個索引選擇行。ref列顯示哪個索引被使用。
index
    這與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引文件通常比數據文件小。
ALL
    對于每個來自于先前的表的行組合,將要做一個完整的表掃描。如果表格是第一個沒標記const的表,這通常不好,並且通常在所有的其他情況下很差。你通常可以通過增加更多的索引來避免ALL,使得行能從早先的表中基于常數值或列值被檢索出。

通過相乘EXPLAIN輸出的rows行的所有值,你能得到一個關于一個聯結要多好的提示。這應該粗略地告訴你MySQL必須檢驗多少行以執行查詢。當你使用max_join_size變量限制查詢時,也用這個數字。見10.2.3 調節服務器參數。

下列例子顯示出一個JOIN如何能使用EXPLAIN提供的信息逐步被優化。

假定你有顯示在下面的SELECT語句,你使用EXPLAIN檢驗:

EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
            tt.ProjectReference, tt.EstimatedShipDate,
            tt.ActualShipDate, tt.ClientID,
            tt.ServiceCodes, tt.RepetitiveID,
            tt.CurrentProcess, tt.CurrentDPPerson,
            tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
            et_1.COUNTRY, do.CUSTNAME
        FROM tt, et, et AS et_1, do
        WHERE tt.SubmitTime IS NULL
            AND tt.ActualPC = et.EMPLOYID
            AND tt.AssignedPC = et_1.EMPLOYID
            AND tt.ClientID = do.CUSTNMBR;

對于這個例子,假定:

    * 被比較的列被聲明如下:
      表         列         列類型
      tt         ActualPC         CHAR(10)
      tt         AssignedPC         CHAR(10)
      tt         ClientID         CHAR(10)
      et         EMPLOYID         CHAR(15)
      do         CUSTNMBR         CHAR(15)
    * 表有顯示在下面的索引:
      表         索引
      tt         ActualPC
      tt         AssignedPC
      tt         ClientID
      et         EMPLOYID(主鍵)
      do         CUSTNMBR(主鍵)
    * tt.ActualPC值不是均勻分布的。

開始,在任何優化被施行前,EXPLAIN語句產生下列信息:

table type possible_keys                key  key_len ref  rows  Extra
et    ALL  PRIMARY                      NULL NULL    NULL 74
do    ALL  PRIMARY                      NULL NULL    NULL 2135
et_1  ALL  PRIMARY                      NULL NULL    NULL 74
tt    ALL  AssignedPC,ClientID,ActualPC NULL NULL    NULL 3872
      range checked for each record (key map: 35)

因為type對每張表是ALL,這個輸出顯示MySQL正在對所有表進行一個完整聯結!這將花相當長的時間,因為必須檢驗每張表的行數的乘積次數!對于一個實例,這是74 * 2135 * 74 * 3872 = 45,268,558,720行。如果表更大,你只能想象它將花多長時間……

如果列聲明不同,這里的一個問題是MySQL(還)不能高效地在列上使用索引。在本文中,VARCHAR和CHAR是相同的,除非他們聲明為不同的長度。因為tt.ActualPC被聲明為CHAR(10)並且et.EMPLOYID被聲明為CHAR(15),有一個長度失配。

為了修正在列長度上的不同,使用ALTER TABLE將ActualPC的長度從10個字符變為15個字符:

mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);

現在tt.ActualPC和et.EMPLOYID都是VARCHAR(15),再執行EXPLAIN語句產生這個結果:

table type   possible_keys   key     key_len ref         rows    Extra
tt    ALL    AssignedPC,ClientID,ActualPC NULL NULL NULL 3872    where used
do    ALL    PRIMARY         NULL    NULL    NULL        2135
      range checked for each record (key map: 1)
et_1  ALL    PRIMARY         NULL    NULL    NULL        74
      range checked for each record (key map: 1)
et    eq_ref PRIMARY         PRIMARY 15      tt.ActualPC 1

這不是完美的,但是是好一些了(rows值的乘積少了一個74一個因子),這個版本在幾秒內執行。

第2種改變能消除tt.AssignedPC = et_1.EMPLOYID和tt.ClientID = do.CUSTNMBR比較的列的長度失配:

mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
                      MODIFY ClientID   VARCHAR(15);

現在EXPLAIN產生的輸出顯示在下面:

table type   possible_keys   key     key_len ref            rows     Extra
et    ALL    PRIMARY         NULL    NULL    NULL           74
tt    ref    AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used
et_1  eq_ref PRIMARY         PRIMARY 15      tt.AssignedPC  1
do    eq_ref PRIMARY         PRIMARY 15      tt.ClientID    1

這“幾乎”象它能得到的一樣好。

剩下的問題是,缺省地,MySQL假設在tt.ActualPC列的值是均勻分布的,並且對tt表不是這樣。幸好,很容易告訴MySQL關于這些:

shell> myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt
shell> mysqladmin refresh

現在聯結是“完美”的了,而且EXPLAIN產生這個結果:

table type   possible_keys   key     key_len ref            rows    Extra
tt    ALL    AssignedPC,ClientID,ActualPC NULL NULL NULL    3872    where used
et    eq_ref PRIMARY         PRIMARY 15      tt.ActualPC    1
et_1  eq_ref PRIMARY         PRIMARY 15      tt.AssignedPC  1
do    eq_ref PRIMARY         PRIMARY 15      tt.ClientID    1

注意在從EXPLAIN輸出的rows列是一個來自MySQL聯結優化器的“教育猜測”;為了優化查詢,你應該檢查數字是否接近事實。如果不是,你可以通過在你的SELECT語句里面使用STRAIGHT_JOIN並且試著在在FROM子句以不同的次序列出表,可能得到更好的性能。

 
7.23 DESCRIBE句法 (得到列的信息)

{DESCRIBE | DESC} tbl_name {col_name | wild}

DESCRIBE提供關于一張表的列的信息。col_name可以是一個列名字或包含SQL的“%”和“_”通配符的一個字符串。

如果列類型不同于你期望的是基于一個CREATE TABLE語句,注意MySQL有時改變列類型。見7.7.1 隱含的列說明變化。

這個語句為了與 Oracle 兼容而提供的。

SHOW語句提供類似的信息。見7.21 SHOW句法(得到表,列的信息)。

 
7.24 LOCK TABLES/UNLOCK TABLES句法

LOCK TABLES tbl_name [AS alias] {READ | [LOW_PRIORITY] WRITE}
            [, tbl_name {READ | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES

LOCK TABLES為當前線程鎖定表。UNLOCK TABLES釋放被當前線程持有的任何鎖。當線程發出另外一個LOCK TABLES時,或當服務器的連接被關閉時,當前線程鎖定的所有表自動被解鎖。

如果一個線程獲得在一個表上的一個READ鎖,該線程(和所有其他線程)只能從表中讀。如果一個線程獲得一個表上的一個WRITE鎖,那麼只有持鎖的線程READ或WRITE表,其他線程被阻止。

每個線程等待(沒有超時)直到它獲得它請求的所有鎖。

WRITE鎖通常比READ鎖有更高的優先級,以確保更改盡快被處理。這意味著,如果一個線程獲得READ鎖,並且然後另外一個線程請求一個WRITE鎖, 隨後的READ鎖請求將等待直到WRITE線程得到了鎖並且釋放了它。當線程正在等待WRITE鎖時,你可以使用LOW_PRIORITY WRITE允許其他線程獲得READ鎖。如果你肯定終于有個時刻沒有線程將有一個READ鎖,你應該只使用LOW_PRIORITY WRITE。

當你使用LOCK TABLES時,你必須鎖定你將使用的所有表!如果你正在一個查詢中多次使用一張表(用別名),你必須對每個別名得到一把鎖!這條政策保証表鎖定不會死鎖。

注意你應該不鎖定任何你正在用INSERT DELAYED使用的表,這是因為在這種情況下,INSERT被一個不同的線程執行。

通常,你不必鎖定表,因為所有單個UPDATE語句是原語;沒有其他線程能防礙任何其它正在執行SQL語句的線程。當你想鎖定表,有一些情況:

    * 如果你將在一堆表上運行許多操作,鎖定你將使用的表是較快的。當然缺點是,沒有其他線程能更新一個READ鎖定的表並且沒有其他線程能讀一個WRITE-鎖定的表。
    * MySQL不支持事務環境,所以如果你想要保証在一個SELECT和一個UPDATE之間沒有其他線程到來,你必須使用LOCK TABLES。下面顯示的例子要求LOCK TABLES以便安全地執行:

      mysql> LOCK TABLES trans READ, customer WRITE;
      mysql> select sum(value) from trans where customer_id= some_id;
      mysql> update customer set total_value=sum_from_previous_statement
                 where customer_id=some_id;
      mysql> UNLOCK TABLES;

沒有LOCK TABLES,另外一個線程可能有一個機會在執行SELECT和UPDATE語句之間往trans表中插入一個新行。

通過使用漸增更改(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函數,在很多情況下你能使用LOCK TABLES來避免。

你也可以使用用戶級鎖定函數GET_LOCK()和RELEASE_LOCK()解決一些情況,這些鎖保存在服務器的一張哈希表中並且用pthread_mutex_lock()和pthread_mutex_unlock()實現以獲得高速度。見7.4.12 其他函數。

有關鎖定政策的更多信息,見10.2.8 MySQL 怎樣鎖定表。

7.25 SET OPTION句法

SET [OPTION] SQL_VALUE_OPTION= value, ...

SET OPTION設置影響服務器或你的客戶操作的各種選項。你設置的任何選擇保持有效直到當前會話結束,或直到你設置選項為不同的值。

CHARACTER SET character_set_name | DEFAULT
    這用給定的映射表從/到客戶映射所有字符串。對character_set_name當前唯一的選項是 cp1251_koi8,但是你能容易通過編輯在MySQL源代碼分發的“sql/convert.cc”文件增加新的映射。缺省映射能用character_set_name的DEFAULT值恢複。注意設置CHARACTER SET選項的語法不同于設置其他選項目的語法。
PASSWORD = PASSWORD('some password')
    設置當前用戶的口令。任何非匿名的用戶能改變他自己的口令!
PASSWORD FOR user = PASSWORD('some password')
    設置當前服務器主機上的一個特定用戶的口令。只有具備存取mysql數據庫的用戶可以這樣做。用戶應該以user@hostname格式給出,這里user和hostname完全與他們列在mysql.user表條目的User和Host列一樣。例如,如果你有一個條目其User和Host字段是'bob'和'%.loc.gov',你將寫成:

    mysql> SET PASSWORD FOR bob@"%.loc.gov" = PASSWORD("newpass");

    或

    mysql> UPDATE mysql.user SET password=PASSWORD("newpass") where user="bob' and host="%.loc.gov";

SQL_AUTO_IS_NULL = 0 | 1
    如果設置為1(缺省 ),那麼對于一個具有一個自動加1的行的表,用下列構件能找出最後插入的行:WHERE auto_increment_column IS NULL。這被一些 ODBC 程序入Access使用。
SQL_BIG_TABLES = 0 | 1
    如果設置為1,所有臨時表存在在磁盤上而非內存中。這將更慢一些,但是對需要大的臨時表的大SELECT操作,你將不會得到The table tbl_name is full的錯誤。對于一個新連接的缺省值是0(即,使用內存中的臨時表)。
SQL_BIG_SELECTS = 0 | 1
    如果設置為0,如果一個SELECT嘗試可能花很長的時間,MySQL將放棄。這在一個不妥當的WHERE語句發出時是有用的。一個大的查詢被定義為一個將可能必須檢驗多于max_join_size行的SELECT。對一個新連接的缺省值是1(它將允許所有SELECT語句)。
SQL_LOW_PRIORITY_UPDATES = 0 | 1
    如果設置為1,所有INSERT、UPDATE、DELETE和LOCK TABLE WRITE語句等待,直到在受影響的表上沒有未解決的SELECT或LOCK TABLE READ。
SQL_SELECT_LIMIT = value | DEFAULT
    從SELECT語句返回的記錄的最大數量。如果一個SELECT有一個LIMIT子句,LIMIT優先與SQL_SELECT_LIMIT值。對一個新連接的缺省值是“無限”的。如果你改變了限制,缺省值能用SQL_SELECT_LIMIT的一個DEFAULT值恢複。
SQL_LOG_OFF = 0 | 1
    如果設置為1,如果客戶有process權限,對該客戶沒有日志記載到標准的日志文件中。這不影響更新日志記錄!
SQL_LOG_UPDATE = 0 | 1
    如果設置為0, 如果客戶有process權限,對該客戶沒有日志記載到更新日志中。這不影響標准日志文件!
TIMESTAMP = timestamp_value | DEFAULT
    為該客戶設置時間。如果你使用更新日志恢複行,這被用來得到原來的時間標記。
LAST_INSERT_ID = #
    設置從LAST_INSERT_ID()返回的值。當你在更新一個表的命令中使用LAST_INSERT_ID()時,它存儲在更新日志中。
INSERT_ID = #
    設置當插入一個AUTO_INCREMENT值時,由INSERT命令使用的值。這主要與更新日志一起使用。

7.26 GRANT和REVOKE句法

GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
    ON {tbl_name | * | *.* | db_name.*}
    TO user_name [IDENTIFIED BY 'password']
        [, user_name [IDENTIFIED BY 'password'] ...]
    [WITH GRANT OPTION]

REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
    ON {tbl_name | * | *.* | db_name.*}
    FROM user_name [, user_name ...]

GRANT在MySQL 3.22.11或以後版本中實現。對于更早MySQL版本,GRANT語句不做任何事情。

GRANT和REVOKE命令允許系統主管在4個權限級別上授權和撤回賦予MySQL用戶的權利:

全局級別
    全局權限作用于一個給定服務器上的所有數據庫。這些權限存儲在mysql.user表中。
數據庫級別
    數據庫權限作用于一個給定數據庫的所有表。這些權限存儲在mysql.db和mysql.host表中。
表級別
    表權限作用于一個給定表的所有列。這些權限存儲在mysql.tables_priv表中。
列級別
    列權限作用于在一個給定表的單個列。這些權限存儲在mysql.columns_priv表中。

對于GRANT如何工作的例子,見6.11 為MySQL增加新的用戶權限。

對于GRANT和REVOKE語句,priv_type可以指定下列的任何一個:

ALL PRIVILEGES      FILE                RELOAD
ALTER               INDEX               SELECT
CREATE              INSERT              SHUTDOWN
DELETE              PROCESS             UPDATE
DROP                REFERENCES          USAGE

ALL是ALL PRIVILEGES的一個同義詞,REFERENCES還沒被實現,USAGE當前是“沒有權限”的一個同義詞。它能用在你想要創建一個沒有權限用戶的時候。

為了從一個用戶撤回grant的權限,使用GRANT OPTION的一個priv_type值:

REVOKE GRANT OPTION ON ... FROM ...;

對于表,你能指定的唯一priv_type值是SELECT、INSERT、UPDATE、DELETE、CREATE、DROP、GRANT、INDEX和ALTER。

對于列,你能指定的唯一priv_type值是(即,當你使用一個column_list子句時)是SELECT、INSERT和UPDATE。

你能通過使用ON *.*語法設置全局權限,你能通過使用ON db_name.*語法設置數據庫權限。如果你指定ON *並且你有一個當前數據庫,你將為該數據庫設置權限。(警告:如果你指定ON *而你沒有一個當前數據庫,你將影響全局權限!)

為了容納對任意主機的用戶授予的權利,MySQL支持以user@host格式指定user_name值。如果你想要指定一個特殊字符的一個user字符串(例如“-”),或一個包含特殊字符或通配符的host字符串(例如“%”),你可以用括號括起能用戶或主機名字 (例如,'test-user'@'test-hostname')。

你能在主機名中指定通配符。例如,user@"%.loc.gov"適用于在loc.gov域中任何主機的user,並且user@"144.155.166.%"適用于在144.155.166類 C 子網中任何主機的user。

簡單形式的user是user@"%"的一個同義詞。注意:如果你允許匿名用戶連接MySQL服務器(它是缺省的),你也應該增加所有本地用戶如user@localhost,因為否則,當用戶試圖從本地機器上登錄到MySQL服務器時,對于mysql.user表中的本地主機的匿名用戶條目將被使用!匿名用戶通過插入有User=''的條目到mysql.user表中來定義。通過執行這個查詢,你可以檢驗它是否作用于你:

mysql> SELECT Host,User FROM mysql.user WHERE User='';

目前,GRANT僅支持最長60個字符的主機、表、數據庫和列名。一個用戶名字能最多到16個字符。

對與一個表或列的權限是由4個權限級別的邏輯或形成的。例如,如果mysql.user表指定一個用戶有一個全局select權限,它不能被數據庫、表或列的一個條目否認。

對于一個列的權限能如下計算:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

在大多數情況下,你只授予用戶一個權限級別上的權限,因此現實通常不象上面所說的那樣複雜。 權限檢查過程的細節在6 MySQL 存取權限系統中給出。

如果你為一個在mysql.user表中不存在的用戶/主機名組合授權,一個條目被增加並且保留直到用一個DELETE命令刪除。換句話說,GRANT可以創建user表的條目,但是REVOKE將不刪除;你必須明確地使用DELETE刪除.

在MySQL 3.22.12或以後,如果創建一個新用戶或如果你有全局授予權限,用戶的口令將被設置為由IDENTIFIED BY子句指定的口令,如果給出一個。如果用戶已經有了一個口令,它被一個新的代替。

警告:如果你創造一個新用戶但是不指定一個IDENTIFIED BY子句,用戶沒有口令。這是不安全的。

口令也能用SET PASSWORD命令設置。見7.25 SET OPTION句法。

如果你為一個數據庫授權,如果需要在mysql.db表中創建一個條目。當所有為數據庫的授權用REVOKE刪除時,這個條目被刪除。

如果一個用戶沒有在一個表上的任何權限,當用戶請求一系列表時,表不被顯示(例如,用一個SHOW TABLES語句)。

WITH GRANT OPTION子句給與用戶有授予其他用戶在指定的權限水平上的任何權限的能力。你應該謹慎對待你授予他grant權限的用戶,因為具有不同權限的兩個用戶也許能合並權限!

你不能授予其他用戶你自己不具備的權限; agree權限允許你放棄你僅僅擁有的那些權限。

要知道,當你將一個特定權限級別上的grant授予其他用戶,用戶已經擁有(或在未來被授予!)的在該級別上的任何權限也可由該用戶授權。假定你授權一個用戶在一個數據庫上的insert權限,那麼如果你授權在數據庫上select權限並且指定WITH GRANT OPTION,用戶能不僅放棄select權限,還有insert。如果你授權用戶在數據庫上的update權限,用戶能放棄insert、select和update。

你不應該將alter權限授予一個一般用戶。如果你這樣做,用戶可以通過重命名表試圖顛覆權限系統!

注意,如果你正在使用即使一個用戶的表或列的權限,服務器要檢查所有用戶的表和列權限並且這將使MySQL慢下來一點。

當mysqld啟動時,所有的權限被讀入存儲器。數據庫、表和列權限馬上生效,而用戶級權限在下一次用戶連接時生效。你用GRANT或REVOKE對受權表執行的更改立即被服務器知曉。如果你手工修改授權表(使用INSERT、UPDATE等等),你應該執行一個FLUSH PRIVILEGES語句或運行mysqladmin flush-privileges告訴服務器再次裝載授權表。見6.9 權限變化何時生效。

ANSI SQL版本的GRANT與MySQL版本之間的最大差別:

    * ANSI SQL 沒有全局或數據庫級別權限,並且 ANSI SQL 不支持所有MySQL支持的權限。
    * 當你在 ANSI SQL 拋棄一張表時,表的所有權限均被撤消。如果你在 ANSI SQL 撤銷權限,所有基于該權限的授權也被也被撤消。在MySQL中,權限只能用明確的REVOKE命令或操作MySQL授權表拋棄。

 
7.27 CREATE INDEX句法

CREATE [UNIQUE] INDEX index_name ON tbl_name (col_name[(length)],... )

CREATE INDEX語句在MySQL版本 3.22 以前不做任何事情。在 3.22 或以後版本中,CREATE INDEX被映射到一個ALTER TABLE語句來創建索引。見7.8 ALTER TABLE句法。

通常,你在用CREATE TABLE創建表本身時創建表的所有索引。見7.7 CREATE TABLE句法。CREATE INDEX允許你把索引加到現有表中。

一個(col1,col2,...)形式的列表創造一個多列索引。索引值有給定列的值串聯而成。

對于CHAR和VARCHAR列,索引可以只用一個列的部分來創建,使用col_name(length)句法。(在BLOB和TEXT列上需要長度)。下面顯示的語句使用name列的頭10個字符創建一個索引:

mysql> CREATE INDEX part_of_name ON customer (name(10));

因為大多數名字通常在頭10個字符不同,這個索引應該不比從整個name列的創建的索引慢多少。另外,在索引使用部分的列能使這個索引成為更小的文件大部分, 它能保存很多磁盤空格並且可能也加快INSERT操作!

注意,如果你正在使用MySQL版本 3.23.2 或更新並且正在使用MyISAM桌子類型,你只能在可以有NULL值的列或一個BLOB/TEXT列上增加一個索引,

關于MySQL如何使用索引的更多信息,見10.4 MySQL索引的使用。

 
7.28 DROP INDEX句法

DROP INDEX index_name ON tbl_name

DROP INDEX從tbl_name表拋棄名為index_name的索引。DROP INDEX在MySQL 3.22 以前的版本中不做任何事情。在 3.22 或以後,DROP INDEX被映射到一個ALTER TABLE語句來拋棄索引。見7.8 ALTER TABLE句法。

7.29 注釋句法

MySQL服務器支持# to end of line、-- to end of line和/* in-line or multiple-line */注釋風格:

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;

注意--注釋風格要求你在--以後至少有一個空格!

盡管服務者理解剛才描述的注釋句法,mysql客戶分析/* ... */注釋的方式上有一些限制:

    * 單引號和雙引號字符被用來標志一個括起來的字符串的開始,即使在一篇注釋內。如果引號在主室內沒被第2個引號匹配,分析器不知道注釋已經結束。如果你正在交互式運行mysql,你能告知有些混亂,因為提示符從mysql>變為'>或">。
    * 一個分號被用來指出當前的SQL語句結束並且跟隨它的任何東西表示下一行的開始。

當你交互式運行mysql時和當你把命令放在一個文件中並用mysql < some-file告訴mysql從那個文件讀它的輸入時,這些限制都適用。

MySQL不支持‘--’的ANSI SQL注釋風格。見5.4.7 ‘--’作為一篇注釋的開始。

 
7.30 CREATE FUNCTION/DROP FUNCTION句法

CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER}
       SONAME shared_library_name

DROP FUNCTION function_name

一個用戶可定義函數(UDF)是用一個像MySQL的原生(內置)函數如ABS()和CONCAT()的新函數來擴展MySQL的方法。

AGGREGATE是MySQL 3.23的一個新選項。一個AGGREGATE函數功能就像一個原生MySQL GROUP函數如SUM或COUNT()。

CREATE FUNCTION在mysql.func系統表中保存函數名、類型和共享庫名。你必須對mysql數據庫有insert和delete權限以創建和拋棄函數。

所有活躍的函數在每次服務器啟動時被重新裝載,除非你使用--skip-grant-tables選項啟動mysqld,在這種情況下,UDF初始化被跳過並且UDF是無法獲得的。(一個活躍函數是一個已經用CREATE FUNCTION裝載並且沒用DROP FUNCTION刪除的函數。)

關于編寫用戶可定義函數的指令,見14 為MySQL增加新函數。對于UDF的工作機制,函數必須用 C 或 C++ 編寫,你的操作系統必須支持動態裝載並且你必須動態編譯了mysqld(不是靜態)。

 
7.31 MySQL對保留詞很挑剔嗎?

一個常見的問題源自于試圖使用MySQL內置的數據類型或函數名同名的列來創建數據庫表,例如TIMESTAMP或GROUP。你允許這樣做(例如,ABS是一個允許的列名),但是當使用其名字也是列名的函數時,在一個函數名和“ ( ”之間不允許白空。

下列詞明確地在MySQL中被保留。他們的大多數被 ANSI SQL92 禁止作為列或表名(例如,group)。一些被保留因為MySQL需要他們並且正在(當前)使用一個yacc分析器:
action         add         aggregate         all
alter         after         and         as
asc         avg         avg_row_length         auto_increment
between         bigint         bit         binary
blob         bool         both         by
cascade         case         char         character
change         check         checksum         column
columns         comment         constraint         create
cross         current_date         current_time         current_timestamp
data         database         databases         date
datetime         day         day_hour         day_minute
day_second         dayofmonth         dayofweek         dayofyear
dec         decimal         default         delayed
delay_key_write         delete         desc         describe
distinct         distinctrow         double         drop
end         else         escape         escaped
enclosed         enum         explain         exists
fields         file         first         float
float4         float8         flush         foreign
from         for         full         function
global         grant         grants         group
having         heap         high_priority         hour
hour_minute         hour_second         hosts         identified
ignore         in         index         infile
inner         insert         insert_id         int
integer         interval         int1         int2
int3         int4         int8         into
if         is         isam         join
key         keys         kill         last_insert_id
leading         left         length         like
lines         limit         load         local
lock         logs         long         longblob
longtext         low_priority         max         max_rows
match         mediumblob         mediumtext         mediumint
middleint         min_rows         minute         minute_second
modify         month         monthname         myisam
natural         numeric         no         not
null         on         optimize         option
optionally         or         order         outer
outfile         pack_keys         partial         password
precision         primary         procedure         process
processlist         privileges         read         real
references         reload         regexp         rename
replace         restrict         returns         revoke
rlike         row         rows         second
select         set         show         shutdown
smallint         soname         sql_big_tables         sql_big_selects
sql_low_priority_updates         sql_log_off         sql_log_update         sql_select_limit
sql_small_result         sql_big_result         sql_warnings         straight_join
starting         status         string         table
tables         temporary         terminated         text
then         time         timestamp         tinyblob
tinytext         tinyint         trailing         to
type         use         using         unique
unlock         unsigned         update         usage
values         varchar         variables         varying
varbinary         with         write         when
where         year         year_month         zerofill

下列符號(來自上表)被ANSI SQL禁止但是被MySQL允許作為列/表名。這是因為這些名字的一些是很自然的名字並且很多人已經使用了他們。

    * ACTION
    * BIT
    * DATE
    * ENUM
    * NO
    * TEXT
    * TIME
    * TIMESTAMP

TOP

踏破鐵鞋無覓處,真是太棒了
非常謝謝大大您的提供!

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。