mysql-logo.gif (3082 bytes)MySQL中文參考手冊

譯者:晏子 (clyan@sohu.com)      主頁:http://linuxdb.yeah.net

譯者:晏子 (clyan@sohu.com
GB 碼主頁:http://linuxdb.yeah.net

Big5 轉碼者:statue (statue@bbs.yzu.edu.tw
詞彙轉換:彭武興 (wilson@mailbox.com.tw)
Big5 碼主頁: http://cnpa.yzu.edu.tw/~cfc/docs/mysqldoc_big5/manual_toc.html
Big5 碼分站: http://php.wilson.gs/mysqldoc/big5/manual_toc.html


第一章, 前一章, 下一章, 最後一章目錄.


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的先前版本,命名規則如下:

建議你不使用像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_namedb_name.tbl_name前綴,除非引用會有二義性。例如,假定表t1t2,每個均包含列c,並且你用一個使用t1t2SELECT語句檢索c。在這種情況下,c有二義性,因為它在使用表的語句中不是唯一的,因此你必須通過寫出t1.ct2.c來指明你想要哪個表。同樣,如果你從資料庫db1中一個表t和在資料庫db2的一個表t檢索,你必須用db1.t.col_namedb2.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;

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

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

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。

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

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

TINYINT[(M)] [UNSIGNED] [ZEROFILL]
一個很小的整數。有符號的範圍是-128127,無符號的範圍是0255
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
一個小整數。有符號的範圍是-3276832767,無符號的範圍是065535
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
一個中等大小整數。有符號的範圍是-83886088388607,無符號的範圍是016777215
INT[(M)] [UNSIGNED] [ZEROFILL]
一個正常大小整數。有符號的範圍是-21474836482147483647,無符號的範圍是04294967295
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
這是INT的一個同義詞。
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
一個大整數。有符號的範圍是-92233720368547758089223372036854775807,無符號的範圍是018446744073709551615。注意,所有算術運算用有符號的BIGINTDOUBLE值完成,因此你不應該使用大於9223372036854775807(63位)的有符號大整數,除了位函數!注意,當兩個參數是INTEGER值時,-+*將使用BIGINT運算!這意味著如果你乘2個大整數(或來自於返回整數的函數),如果結果大於9223372036854775807,你可以得到意外的結果。一個浮點數字,不能是無符號的,對一個單精度浮點數,其精度可以<=24,對一個雙精度浮點數,是在25 和53之間,這些類型如FLOATDOUBLE類型馬上在下面描述。FLOAT(X)有對應的FLOATDOUBLE相同的範圍,但是顯示尺寸和小數位數是未定義的。在MySQL3.23中,這是一個真正的浮點值。在更早的MySQL版本中,FLOAT(precision)總是有2位小數。該句法為了ODBC兼容性而提供。
FLOAT[(M,D)] [ZEROFILL]
一個小(單精密)浮點數字。不能無符號。允許的值是-3.402823466E+38-1.175494351E-3801.175494351E-383.402823466E+38。M是顯示寬度而D是小數的位數。沒有參數的FLOAT或有<24 的一個參數表示一個單精密浮點數字。
DOUBLE[(M,D)] [ZEROFILL]
一個正常大小(雙精密)浮點數字。不能無符號。允許的值是-1.7976931348623157E+308-2.2250738585072014E-30802.2250738585072014E-3081.7976931348623157E+308。M是顯示寬度而D是小數位數。沒有一個參數的DOUBLEFLOAT(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列,實際的範圍可以通過MD的選擇被限制。如果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年的某時。MySQLYYYYMMDDHHMMSSYYMMDDHHMMSSYYYYMMDDYYMMDD格式來顯示TIMESTAMP值,取決於是否M14(或省略)、1286,但是允許你使用字符串或數字把值賦給TIMESTAMP列。一個TIMESTAMP列對於記錄一個INSERTUPDATE操作的日期和時間是有用的,因為如果你不自己給它賦值,它自動地被設置為最近操作的日期和時間。你以可以通過賦給它一個NULL值設置它為當前的日期和時間。見7.3.6 日期和時間類型
TIME
一個時間。範圍是'-838:59:59''838:59:59'MySQL'HH:MM:SS'格式來顯示TIME值,但是允許你使用字符串或數字把值賦給TIME列。
YEAR[(2|4)]
一個2或4位數字格式的年(內定是4位)。允許的值是19012155,和0000(4位年格式),如果你使用2位,1970-2069( 70-69)。MySQLYYYY格式來顯示YEAR值,但是允許你把使用字符串或數字值賦給YEAR列。(YEAR類型在MySQL3.22中是新類型。)
CHAR(M) [BINARY]
一個定長字符串,當儲存時,總是是用空格填滿右邊到指定的長度。M的範圍是1 ∼ 255個字符。當值被檢索時,空格尾部被刪除。CHAR值根據內定字符集以大小寫不區分的方式排序和比較,除非給出BINARY關鍵詞。NATIONAL CHAR(短形式NCHAR)是ANSI SQL的方式來定義CHAR列應該使用內定字符集。這是MySQL的內定。CHARCHARACTER的一個縮寫。
[NATIONAL] VARCHAR(M) [BINARY]
一個變長字符串。注意:當值被儲存時,尾部的空格被刪除(這不同於ANSI SQL規範)。M的範圍是1 ∼ 255個字符。 VARCHAR值根據內定字符集以大小寫不區分的方式排序和比較,除非給出BINARY關鍵詞值。見7.7.1 隱式列指定變化VARCHARCHARACTER VARYING一個縮寫。
TINYBLOB
 
TINYTEXT
一個BLOBTEXT列,最大長度為255(2^8-1)個字符。見7.7.1 隱式列指定變化
BLOB
 
TEXT
一個BLOBTEXT列,最大長度為65535(2^16-1)個字符。見7.7.1 隱式列指定變化
MEDIUMBLOB
 
MEDIUMTEXT
一個BLOBTEXT列,最大長度為16777215(2^24-1)個字符。見7.7.1 隱式列指定變化
LONGBLOB
 
LONGTEXT
一個BLOBTEXT列,最大長度為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 <= M1 <= 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個成員)

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

BLOBTEXT類型需要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)。關鍵詞INTINTEGER的一個同義詞,而關鍵詞DECDECIMAL一個同義詞。

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

salary DECIMAL(9,2) 

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

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

DECIMALNUMERIC值得最大的範圍與DOUBLE一樣,但是對於一個給定的DECIMALNUMERIC列,實際的範圍可由制由給定列的precisionscale限制。當這樣的列賦給了小數點後面的位超過指定scale所允許的位的值,該值根據scale四捨五入。當一個DECIMALNUMERIC列被賦給了其大小超過指定(或內定的)precisionscale隱含的範圍的值,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個數字。用這個選項,第一個數字繼續表示在字節計算的值儲存需求,而第二個數字指定要被儲存的和顯示跟隨小數點後的位數(就像DECIMALNUMERIC)。當MySQL要求為這樣一個列,一個小數點後的小數位超過列指定的值,儲存值時,該值被四捨五入,去掉額外的位。

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

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

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

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

對於ALTER TABLELOAD DATA INFILEUPDATE和多行INSERT語句,由於剪切所發生的變換作為“警告”被報告。

7.3.6 日期和時間類型

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

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

7.3.6.1 Y2K問題和日期類型

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

對於DATETIME, DATE, TIMESTAMPYEAR類型,MySQL使用下列規則的解釋二義性的年份值:

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

7.3.6.2 DATETIME, DATETIMESTAMP類型

DATETIME, DATETIMESTAMP類型是相關的。本節描述他們的特徵,他們是如何類似的而又不同的。

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列類型提供一種類型,你可以使用它自動地用當前的日期和時間標記INSERTUPDATE的操作。如果你有多個TIMESTAMP列,只有第一個自動更新。

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

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

通過明確地設置希望的值,你可以設置任何TIMESTAMP列為不同於當前日期和時間的值,即使對第一個TIMESTAMP列也是這樣。例如,如果,當你創建一個行時,你想要一個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範圍的奇數值尺寸被強制為下一個更大的偶數。

使用一個常用的格式集的任何一個,你可以指定DATETIMEDATETIMESTAMP值:

不合法DATETIME, DATETIMESTAMP值被變換到適當類型的“零”值('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位長,它被假定以YYYYMMDDYYYYMMDDHHMMSS格式並且年份由頭4位數字給出。如果數字是6或12位長,它被假定是以YYMMDDYYMMDDHHMMSS格式且年份由頭2位數字給出。不是這些長度之一的數字通過填補前頭的零到最接近的長度來解釋。

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

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

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

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

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值:

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

將“短的”TIME值賦值給一個TIME行列是要格外小心。MySQL使用最右位代表秒的假設來解釋值。(MySQLTIME值解釋為經過的時間,而非作為一天的時間 )例如,你可能想到'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值,其範圍是19012155

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

不合法YEAR值被變換到0000

7.3.7 字符串類型

字符串類型是CHARVARCHARBLOBTEXTENUMSET

7.3.7.1 CHARVARCHAR類型

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

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

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

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

下表顯示了兩種類型的列的不同,通過演示儲存變長字符串值到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列上被刪除。

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

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

MySQL在表創建時可以隱含地改變一個CHARVARCHAR列的類型。見7.7.1 隱含的的列說明改變

7.3.7.2 BLOBTEXT類型

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

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

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

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

MyODBC定義BLOBLONGVARBINARYTEXT值為LONGVARCHAR

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

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

7.3.7.3 ENUM類型

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

在下列的某個情形下,值也可以空字符串("")或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 為列選擇正確的類型

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

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

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

7.3.9 列索引

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

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

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

KEY index_name (col_name(length)) 

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

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

對於BLOBTEXT列,你必須索引列的前綴,你不能索引列的全部。

7.3.10 多列索引

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

一個多重列索引可以認為是包含通過合並(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_namefirst_name上的索引,這個索引將被用於在last_namelast_namefirst_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 用在SELECTWHERE子句中的函數

在一個SQL語句中的select_expressionwhere_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
 
&&
邏輯與。如果任何一個參數是0NULL,返回0,否則返回1
mysql> select 1 && NULL;
        -> 0
mysql> select 1 && 0;
        -> 0
   

7.4.5 比較運算符

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

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

內定地,字符串使用當前的字符集以大小寫敏感的方式進行(內定為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對大於或等於minexpr是小於或等於maxBETWEEN返回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)
如果exprNULLISNULL()返回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,否則返回0RLIKEREGEXP的一個同義詞,提供了與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
當決定一個字符的類型時,REGEXPRLIKE使用當前的字符集(內定為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操作符強制跟隨它後面的字符串為一個二進制字符串。即使列沒被定義為BINARYBLOB,這是一個強制列比較區分大小寫的簡易方法。
mysql> select "a" = "A";
        -> 1
mysql> select BINARY "a" = "A";
        -> 0

BINARYMySQL 3.23.0中被引入。

7.4.8 控制流函數

IFNULL(expr1,expr2)
如果expr1不是NULLIFNULL()返回expr1,否則它返回expr2IFNULL()返回一個數字或字符串值,取決於它被使用的上下文環境。
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<>0expr1<>NULL),那麼IF()返回expr2,否則它返回expr3IF()返回一個數字或字符串值,取決於它被使用的上下文。
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)
返回參數的符號,為-101,取決於X是否是負數、零或正數。
mysql> select SIGN(-32);
        -> -1
mysql> select SIGN(0);
        -> 0
mysql> select SIGN(234);
        -> 1
   
MOD(N,M)
 
%
模 (類似C中的%操作符)。返回NM除的餘數。
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為小數的一個數字。如果D0,結果將沒有小數點或小數部分。
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)
返回值XY次冪。
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不在-11的範圍,返回NULL
mysql> select ACOS(1);
        -> 0.000000
mysql> select ACOS(1.0001);
        -> NULL
mysql> select ACOS(0);
        -> 1.570796
 
ASIN(X)
返回X反正弦值,即其正弦值是XL如果X不在-11的範圍,返回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個變數XY的反正切。它類似於計算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)
返回在範圍01.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個以上的參數,返回最小(最小值)的參數。參數使用下列規則進行比較:
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位小數。如果D0,結果將沒有小數點或小數部分。
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。如果strNULL,返回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)。如果NNULL,返回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)。如果NNULL,返回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填補直到strlen個字符長。
mysql> select LPAD('hi',4,'??');
        -> '??hi'
 
RPAD(str,len,padstr)
返回字符串str,右面用字符串padstr填補直到strlen個字符長。  
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前綴或後綴被刪除了。如果沒有修飾符BOTHLEADINGTRAILING給出,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,返回一個空字符串。如果strcountNULL,返回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或大於參數個數,返回NULLELT()FIELD()反運算。
mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo');
        -> 'ej'
mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo');
        -> 'foo'
FIELD(str,str1,str2,str3,...)
返回strstr1, str2, str3, ...清單的索引。如果str沒找到,返回0FIELD()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之中,返回一個1N的值。一個字符串表是被“,”分隔的子串組成的一個字符串。如果第一個參數是一個常數字符串並且第二個參數是一種類型為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()

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

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的月份中日期,在131範圍內。
mysql> select DAYOFMONTH('1998-02-03');
        -> 3
DAYOFYEAR(date)
返回date在一年中的日數, 在1366範圍內。
mysql> select DAYOFYEAR('1998-02-03');
        -> 34
MONTH(date)
返回date的月份,範圍112
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一年中的季度,範圍14
mysql> select QUARTER('98-04-01');
        -> 2
 
WEEK(date)
 
WEEK(date,first)
對於星期天是一周的第一天的地方,有一個單個參數,返回date的周數,範圍在052。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的年份,範圍在10009999
mysql> select YEAR('98-02-03');
        -> 1998
HOUR(time)
返回time的小時,範圍是023
mysql> select HOUR('10:05:03');
        -> 10
MINUTE(time)
返回time的分鐘,範圍是059
mysql> select MINUTE('98-02-03 10:05:03');
        -> 5
SECOND(time)
回來time的秒數,範圍是059
mysql> select SECOND('10:05:03');
        -> 3
PERIOD_ADD(P,N)
增加N個月到階段P(以格式YYMMYYYYMM)。以格式YYYYMM返回值。注意階段參數P不是日期值。
mysql> select PERIOD_ADD(9801,2);
        -> 199803
PERIOD_DIFF(P1,P2)
返回在時期P1P2之間月數,P1P2應該以格式YYMMYYYYMM。注意,時期參數P1P2不是日期值。
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是一個指定開始日期的DATETIMEDATE值,expr是指定加到開始日期或從開始日期減去的間隔值一個表達式,expr是一個字符串﹔它可以以一個“-”開始表示負間隔。type是一個關鍵詞,指明表達式應該如何被解釋。EXTRACT(type FROM date)函數從日期中返回“type”間隔。下表顯示了typeexpr參數怎樣被關聯:
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"

MySQLexpr格式中允許任何標點分隔符。表示顯示的是建議的分隔符。如果date參數是一個DATE值並且你的計算僅僅包含YEARMONTHDAY部分(即,沒有時間部分),結果是一個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假設你省掉了間隔值的最左面部分。例如,如果你指定一個typeDAY_SECOND,值expr被希望有天、小時、分鐘和秒部分。如果你像"1:10"這樣指定值,MySQL假設日子和小時部分是丟失的並且值代表分鐘和秒。換句話說,"1:10" DAY_SECOND以它等價於"1:10" MINUTE_SECOND的方式解釋,這對那MySQL解釋TIME值表示經過的時間而非作為一天的時間的方式有二義性。如果你使用確實不正確的日期,結果是NULL。如果你增加MONTHYEAR_MONTHYEAR並且結果日期大於新月份的最大值天數,日子在新月用最大的天調整。

mysql> select DATE_ADD('1998-01-30', Interval 1 month);
        -> 1998-02-28
注意,從前面的例子中詞INTERVALtype關鍵詞不是區分大小寫的。  
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 AMPM
%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或以YYMMDDYYYYMMDD格式的本地時間的一個數字。
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()系統調用加密strsalt參數應該是一個有2個字符的字符串。(MySQL 3.22.16中,salt可以長於2個字符。)
mysql> select ENCRYPT("hello");
        -> 'VxuFAJXVARROc'

如果crypt()在你的系統上不可用,ENCRYPT()總是返回NULLENCRYPT()只保留str起始8個字符而忽略所有其他,至少在某些系統上是這樣。這將由底層的crypt()系統調用的行為決定。

ENCODE(str,pass_str)
使用pass_str作為密碼加密str。為了解密結果,使用DECODE()。結果是一個二進制字符串,如果你想要在列中保存它,使用一個BLOB列類型。
DECODE(crypt_str,pass_str)
使用pass_str作為密碼解密加密的字符串crypt_strcrypt_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為小數。如果D0,結果將沒有小數點和小數部分。
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 BYORDER 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 列類型

7.7.1 隱含的列說明改變

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

如果你想要知道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改為CHARMySQL將仍然使用VARCHAR,如果表包含其他變長的列。

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

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

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

重命名表,從t1t2:

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柱必須被索引,並且另外我們聲明cNOT NULL,因為索引了的列不能是NULL

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

7.9 OPTIMIZE TABLE句法

OPTIMIZE TABLE tbl_name

如果你刪除了一個表的大部分或如果你用變長的行對一個表(有VARCHARBLOBTEXT列的表)做了改變,應該使用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]

DELETEtbl_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_PRIORITYDELETE的執行被推遲到沒有其他客戶讀取表後。

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

MySQLDELETE特定的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子句之前。

如果你使用INTO DUMPFILE而不是INTO OUTFILEMySQL將只寫一行到文件中,沒有任何列或行結束並且沒有任何轉義。如果你想要在一個文件儲存一個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兼容而存在的。

一些例子:

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 ... SELECTINSERT ... VALUES語句有多個值列表,你可以使用C API函數mysql_info()得到查詢的資訊。資訊字符串的格式如下:

Records: 100 Duplicates: 0 Warnings: 0 

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

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

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

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

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

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

注意如果桌子不在使用,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沒指定,文件必須位於伺服器上。(LOCALMySQL3.22.6或以後版本刈莃用。)

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

如果你指定關鍵詞LOW_PRIORITYLOAD 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; 

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

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

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

如果你指定一個FIELDS子句,它的每一個子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BYESCAPED 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 BYFIELDS ESCAPED BY值必須是一個單個字符。FIELDS TERMINATED BYLINES 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"

如果你指定OPTIONALLYENCLOSED BY字符僅被用於包圍CHARVARCHAR字段:

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

對於更多關於“\”- 轉義句法的資訊,見7.1 文字:怎樣寫字符串和數字

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

NULL值的處理有多種,取決於你使用的FIELDSLINES選項:

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

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

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

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

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

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

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

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

如果字段值內定,空字段值有不同的解釋:

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

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

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

如果你正在使用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, reloadflush-tables命令來訪問上述的每一個命令。

 

7.20 KILL句法

KILL thread_id 

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

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

你也可以使用mysqladmin processlistmysqladmin kill命令檢查並殺死執行緒。

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 TABLESmysqlshow 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 FIELDSSHOW COLUMNS一個同義詞,SHOW KEYSSHOW INDEX一個同義詞。你也可以用mysqlshow db_name tbl_namemysqlshow -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 伺服器工作了多少秒。

關於上面的一些注釋:

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_nameDESCRIBE tbl_nameSHOW COLUMNS FROM tbl_name的一個同義詞。

當你在一條SELECT語句前放上關鍵詞EXPLAINMySQL解釋它將如何處理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類型。它用在一個索引的所有部分被聯結使用並且索引是UNIQUEPRIMARY KEY
ref
對於每個來自於先前的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯結只使用鍵的最左面前綴,或如果鍵不是UNIQUEPRIMARY 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;

對於這個例子,假定:

開始,在任何最佳化被施行前,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(還)不能高效地在列上使用索引。在本文中,VARCHARCHAR是相同的,除非他們聲明為不同的長度。因為tt.ActualPC被聲明為CHAR(10)並且et.EMPLOYID被聲明為CHAR(15),有一個長度失配。

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

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

現在tt.ActualPCet.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.EMPLOYIDtt.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鎖,那麼只有持鎖的執行緒READWRITE表,其他執行緒被阻止。

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

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

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

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

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

沒有LOCK TABLES,另外一個執行緒可能有一個機會在執行SELECTUPDATE語句之間往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_nameDEFAULT值恢復。注意設置CHARACTER SET選項的語法不同於設置其他選項目的語法。
PASSWORD = PASSWORD('some password')
設置當前用戶的密碼。任何非匿名的用戶能改變他自己的密碼!
PASSWORD FOR user = PASSWORD('some password')
設置當前伺服器主機上的一個特定用戶的密碼。只有具備存取mysql資料庫的用戶可以這樣做。用戶應該以user@hostname格式給出,這裡userhostname完全與他們列在mysql.user表條目的UserHost列一樣。例如,如果你有一個條目其UserHost字段是'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,所有INSERTUPDATEDELETELOCK TABLE WRITE語句等待,直到在受影響的表上沒有未解決的SELECTLOCK 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 GRANTREVOKE句法

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 ...]

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

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

全局級別
全局權限作用於一個給定伺服器上的所有資料庫。這些權限儲存在mysql.user表中。
資料庫級別
資料庫權限作用於一個給定資料庫的所有表。這些權限儲存在mysql.dbmysql.host表中。
表級別
表權限作用於一個給定表的所有列。這些權限儲存在mysql.tables_priv表中。
列級別
列權限作用於在一個給定表的單個列。這些權限儲存在mysql.columns_priv表中。

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

對於GRANTREVOKE語句,priv_type可以指定下列的任何一個:

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

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

為了從一個用戶撤回grant的權限,使用GRANT OPTION的一個priv_type值:

REVOKE GRANT OPTION ON ... FROM ...;

對於表,你能指定的唯一priv_type值是SELECTINSERTUPDATEDELETECREATEDROPGRANTINDEXALTER

對於列,你能指定的唯一priv_type值是(即,當你使用一個column_list子句時)是SELECTINSERTUPDATE

你能通過使用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

簡單形式的useruser@"%"的一個同義詞。注意:如果你允許匿名用戶連接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權限,用戶能放棄insertselectupdate

你不應該將alter權限授予一個一般用戶。如果你這樣做,用戶可以通過重命名表試圖顛覆權限系統!

注意,如果你正在使用即使一個用戶的表或列的權限,伺服器要檢查所有用戶的表和列權限並且這將使MySQL慢下來一點。

mysqld啟動時,所有的權限被讀入儲存器。資料庫、表和列權限馬上生效,而用戶級權限在下一次用戶連接時生效。你用GRANTREVOKE對受權表執行的更改立即被伺服器知曉。如果你手工修改授權表(使用INSERT、UPDATE等等),你應該執行一個FLUSH PRIVILEGES語句或運行mysqladmin flush-privileges告訴伺服器再次裝載授權表。見6.9 權限變化何時生效

ANSI SQL版本的GRANTMySQL版本之間的最大差別:

 

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,...)形式的列表創造一個多列索引。索引值有給定列的值串聯而成。

對於CHARVARCHAR列,索引可以只用一個列的部分來創建,使用col_name(length)句法。(在BLOBTEXT列上需要長度)。下面顯示的語句使用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 INDEXtbl_name表拋棄名為index_name的索引。DROP INDEXMySQL 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客戶分析/* ... */注釋的方式上有一些限制:

當你交互式運行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的方法。

AGGREGATEMySQL 3.23的一個新選項。一個AGGREGATE函數功能就像一個原生MySQL GROUP函數如SUMCOUNT()

CREATE FUNCTIONmysql.func系統表中保存函數名、類型和共享庫名。你必須對mysql資料庫有insertdelete權限以創建和拋棄函數。

所有活躍的函數在每次伺服器啟動時被重新裝載,除非你使用--skip-grant-tables選項啟動mysqld,在這種情況下,UDF初始化被跳過並且UDF是無法獲得的。(一個活躍函數是一個已經用CREATE FUNCTION裝載並且沒用DROP FUNCTION刪除的函數。)

關於編寫用戶可定義函數的指令,見14 為MySQL增加新函數。對於UDF的工作機制,函數必須用 C 或 C++ 編寫,你的作業系統必須支援動態裝載並且你必須動態編譯了mysqld(不是靜態)。

 

7.31 MySQL對保留詞很挑剔嗎?

一個常見的問題源自於試圖使用MySQL內置的數據類型或函數名同名的列來創建資料庫表,例如TIMESTAMPGROUP。你允許這樣做(例如,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允許作為列/表名。這是因為這些名字的一些是很自然的名字並且很多人已經使用了他們。


第一章, 前一章, 下一章, 最後一章目錄.