譯者:晏子 (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
一個字符串是一個字符序列,由單引號(“'”)或雙引號(“"”)字符(後者只有你不在ANSI模式運行)包圍。例如:
'a string' "another string"
在字符串內,某個順序有特殊的意義。這些順序的每一個以一條反斜線(“\”)開始,稱為轉義字符。MySQL識別下列轉義字符:
\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
\
'
"
如果你寫C代碼,你可以使用C API函數mysql_escape_string()
來為INSERT
語句轉義字符。見20.3 C API 函數概述。在 Perl中,你可以使用DBI
包中的quote
方法變換特殊的字符到正確的轉義序列。見20.5.2 DBI
介面。
你應該在任何可能包含上述任何特殊字符的字符串上使用轉義函數!
整數表示為一個數字順序。浮點數使用“.”作為一個十進制分隔符。這兩種類型的數字可以前置“-”表明一個負值。
有效整數的例子:
1221 0 -32
有效浮點數的例子:
294.42 -32032.6809e+10 148.00
一個整數可以在浮點上下文使用﹔它解釋為等值的浮點數。
MySQL支援十六進制值。在數字上下文,它們表現類似於一個整數(64位精度)。在字符串上下文,它們表現類似於一個二進制字符串,這裡每一對十六進制數字被變換為一個字符。
mysql> SELECT 0xa+0 -> 10 mysql> select 0x5061756c; -> Paul
十六進制字符串經常被ODBC使用,給出BLOB列的值。
NULL
值NULL
值意味著“無數據”並且不同於例如數字類型的0
為或字符串類型的空字符串。見18.15 NULL
值問題。
當使用文本文件導入或導出格式(LOAD DATA INFILE
, SELECT
... INTO OUTFILE
)時,NULL
可以用\N
表示。見7.16 LOAD DATA INFILE
句法。
資料庫、表、索引、列和別名的名字都遵守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_name
或db_name.tbl_name
前綴,除非引用會有二義性。例如,假定表t1
和t2
,每個均包含列c
,並且你用一個使用t1
和t2
的SELECT
語句檢索c
。在這種情況下,c
有二義性,因為它在使用表的語句中不是唯一的,因此你必須通過寫出t1.c
或t2.c
來指明你想要哪個表。同樣,如果你從資料庫db1
中一個表t
和在資料庫db2
的一個表t
檢索,你必須用db1.t.col_name
和db2.t.col_name
引用這些數據表的列。
句法.tbl_name
意味著在當前的資料庫中的表tbl_name
,該句法為了ODBC的兼容性被接受,因為一些ODBC程式用一個“.”字符作為資料庫表名的前綴。
在MySQL中,資料庫和表對應於在那些目錄下的目錄和文件,因而,內在的作業系統的敏感性決定資料庫和表命名的大小寫敏感性。這意味著資料庫和表名在Unix上是區分大小寫的,而在Win32上忽略大小寫。
注意:在Win32上,盡管資料庫和表名是忽略大小寫的,你不應該在同一個查詢中使用不同的大小寫來引用一個給定的資料庫和表。下列查詢將不工作,因為它作為my_table
和作為MY_TABLE
引用一個表:
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
列名在所有情況下都是忽略大小寫的。
表的別名是區分大小寫的。下列查詢將不工作,
:
因為它用a
和A
引用別名:
mysql> SELECT col_name FROM tbl_name AS a WHERE a.col_name = 1 OR A.col_name = 2;
列的別名是忽略大小寫的。
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 | +----------------------+------+------+------+
(這裡,我們不得不使用:=
句法,因為=
是為比較保留的)
MySQL支援大量的列類型,它可以被分為3類:數字類型、日期和時間類型以及字符串(字符)類型。本節首先給出可用類型的一個概述,並且總結每個列類型的儲存需求,然後提供每個類中的類型性質的更詳細的描述。概述有意簡化,更詳細的說明應該考慮到有關特定列類型的附加資訊,例如你能為其指定值的允許格式。
由MySQL支援的列類型列在下面。下列代碼字母用於描述中:
M
D
M
-2。
方括號(“[”和“]”)指出可選的類型修飾符的部分。
注意,如果你指定一個了為ZEROFILL
,MySQL將為該列自動地增加UNSIGNED
屬性。
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
-128
到127
,無符號的範圍是0
到255
。
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
-32768
到32767
,無符號的範圍是0
到65535
。
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
-8388608
到8388607
,無符號的範圍是0
到16777215
。
INT[(M)] [UNSIGNED] [ZEROFILL]
-2147483648
到2147483647
,無符號的範圍是0
到4294967295
。
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
INT
的一個同義詞。 BIGINT[(M)] [UNSIGNED] [ZEROFILL]
-9223372036854775808
到9223372036854775807
,無符號的範圍是0
到18446744073709551615
。注意,所有算術運算用有符號的BIGINT
或DOUBLE
值完成,因此你不應該使用大於9223372036854775807
(63位)的有符號大整數,除了位函數!注意,當兩個參數是INTEGER
值時,-
、+
和*
將使用BIGINT
運算!這意味著如果你乘2個大整數(或來自於返回整數的函數),如果結果大於9223372036854775807
,你可以得到意外的結果。一個浮點數字,不能是無符號的,對一個單精度浮點數,其精度可以
是<=24
,對一個雙精度浮點數,是在25
和53之間,這些類型如FLOAT
和DOUBLE
類型馬上在下面描述。FLOAT(X)
有對應的FLOAT
和DOUBLE
相同的範圍,但是顯示尺寸和小數位數是未定義的。在MySQL3.23中,這是一個真正的浮點值。在更早的MySQL版本中,FLOAT(precision)
總是有2位小數。該句法為了ODBC兼容性而提供。
FLOAT[(M,D)] [ZEROFILL]
-3.402823466E+38
到-1.175494351E-38
,0
和1.175494351E-38
到3.402823466E+38
。M是顯示寬度而D是小數的位數。沒有參數的FLOAT
或有<24
的一個參數表示一個單精密浮點數字。
DOUBLE[(M,D)] [ZEROFILL]
-1.7976931348623157E+308
到-2.2250738585072014E-308
、
0
和2.2250738585072014E-308
到1.7976931348623157E+308
。M是顯示寬度而D是小數位數。沒有一個參數的DOUBLE
或FLOAT(X)
(25
< = X < = 53)代表一個雙精密浮點數字。 DOUBLE PRECISION[(M,D)] [ZEROFILL]
REAL[(M,D)] [ZEROFILL]
DOUBLE
同義詞。 DECIMAL[(M[,D])] [ZEROFILL]
CHAR
列:“未壓縮”意味著數字作為一個字符串被儲存,值的每一位使用一個字符。小數點,並且對於負數,“-”符號不在M中計算。如果D
是0,值將沒有小數點或小數部分。DECIMAL
值的最大範圍與DOUBLE
相同,但是對一個給定的DECIMAL
列,實際的範圍可以通過M
和D
的選擇被限制。如果D
被省略,它被設置為0。如果M
被省掉,它被設置為10。注意,在MySQL3.22裡,M
參數包括符號和小數點。
NUMERIC(M,D) [ZEROFILL]
DECIMAL
的一個同義詞。 DATE
'1000-01-01'
到'9999-12-31'
。MySQL以'YYYY-MM-DD'
格式來顯示DATE
值,但是允許你使用字符串或數字把值賦給DATE
列。
DATETIME
'1000-01-01 00:00:00'
到'9999-12-31
23:59:59'
。MySQL以'YYYY-MM-DD HH:MM:SS'
格式來顯示DATETIME
值,但是允許你使用字符串或數字把值賦給DATETIME
的列。
TIMESTAMP[(M)]
'1970-01-01 00:00:00'
到2037
年的某時。MySQL以YYYYMMDDHHMMSS
、YYMMDDHHMMSS
、YYYYMMDD
或YYMMDD
格式來顯示TIMESTAMP
值,取決於是否M
是14
(或省略)、12
、8
或6
,但是允許你使用字符串或數字把值賦給TIMESTAMP
列。一個TIMESTAMP
列對於記錄一個INSERT
或UPDATE
操作的日期和時間是有用的,因為如果你不自己給它賦值,它自動地被設置為最近操作的日期和時間。你以可以通過賦給它一個NULL
值設置它為當前的日期和時間。見7.3.6 日期和時間類型。 TIME
'-838:59:59'
到'838:59:59'
。MySQL以'HH:MM:SS'
格式來顯示TIME
值,但是允許你使用字符串或數字把值賦給TIME
列。
YEAR[(2|4)]
1901
到2155
,和0000
(4位年格式),如果你使用2位,1970-2069(
70-69)。MySQL以YYYY
格式來顯示YEAR
值,但是允許你把使用字符串或數字值賦給YEAR
列。(YEAR
類型在MySQL3.22中是新類型。) CHAR(M) [BINARY]
M
的範圍是1
∼ 255個字符。當值被檢索時,空格尾部被刪除。CHAR
值根據內定字符集以大小寫不區分的方式排序和比較,除非給出BINARY
關鍵詞。NATIONAL
CHAR
(短形式NCHAR
)是ANSI SQL的方式來定義CHAR列應該使用內定字符集。這是MySQL
的內定。CHAR
是CHARACTER
的一個縮寫。
[NATIONAL] VARCHAR(M) [BINARY]
VARCHAR
值根據內定字符集以大小寫不區分的方式排序和比較,除非給出BINARY
關鍵詞值。見7.7.1 隱式列指定變化。 VARCHAR
是CHARACTER
VARYING
一個縮寫。 TINYBLOB
TINYTEXT
BLOB
或TEXT
列,最大長度為255(2^8-1)個字符。見7.7.1 隱式列指定變化。 BLOB
TEXT
BLOB
或TEXT
列,最大長度為65535(2^16-1)個字符。見7.7.1 隱式列指定變化。 MEDIUMBLOB
MEDIUMTEXT
BLOB
或TEXT
列,最大長度為16777215(2^24-1)個字符。見7.7.1 隱式列指定變化。 LONGBLOB
LONGTEXT
BLOB
或TEXT
列,最大長度為4294967295(2^32-1)個字符。見7.7.1 隱式列指定變化 ENUM('value1','value2',...)
'value1'
、'value2'
,
...
,或NULL
。一個ENUM
最多能有65535不同的值。
SET('value1','value2',...)
'value1'
,
'value2'
, ...
選出。一個SET
最多能有64個成員。
對於每個由MySQL支援的列類型的儲存需求在下面按類列出。
列類型 | 需要的儲存量 |
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 ) |
列類型 | 需要的儲存量 |
DATE |
3 個字節 |
DATETIME |
8 個字節 |
TIMESTAMP |
4 個字節 |
TIME |
3 個字節 |
YEAR |
1 字節 |
列類型 | 需要的儲存量 |
CHAR(M) |
M 字節,1 <= M <= 255 |
VARCHAR(M) |
L +1 字節, 在此L <= M 和1 <= M <= 255
|
TINYBLOB , TINYTEXT |
L +1 字節, 在此L < 2 ^ 8 |
BLOB , TEXT |
L +2 字節, 在此L < 2 ^ 16 |
MEDIUMBLOB , MEDIUMTEXT |
L +3 字節, 在此L < 2 ^ 24 |
LONGBLOB , LONGTEXT |
L +4 字節, 在此L < 2 ^ 32 |
ENUM('value1','value2',...) |
1 或 2 個字節, 取決於枚舉值的數目(最大值65535) |
SET('value1','value2',...) |
1,2,3,4或8個字節, 取決於集合成員的數量(最多64個成員) |
VARCHAR
和BLOB
和TEXT
類型是變長類型,對於其儲存需求取決於列值的實際長度(在前面的表格以 L
表示),而不是取決於類型的最大可能尺寸。例如,一個VARCHAR(10)
列能保存最大長度為10個字符的一個字符串,實際的儲存需要是字符串的長度(L
),加上1個字節以記錄字符串的長度。對於字符串'abcd'
,L
是4而儲存要求是5個字節。
BLOB
和TEXT
類型需要1,2,3或4個字節來記錄列值的長度,這取決於類型的最大可能長度。
如果一個表包括任何變長的列類型,記錄格式將也是變長的。注意,當一個表被創建時,MySQL可能在某些條件下將一個列從一個變長類型改變為一個定長類型或相反。見7.7.1 隱式列指定變化。
一個ENUM
對像的大小由不同枚舉值的數量決定。1字節被用於枚舉,最大到255個可能的值﹔2個字節用於枚舉,最大到65535
值。
一個SET
對像的大小由不同的集合成員的數量決定。如果集合大小是N
,對像占據(N+7)/8
個字節,四捨五入為1,2,3,4或8
個字節。一個SET
最多能有64個成員。
MySQL支援所有的ANSI/ISO SQL92的數字類型。這些類型包括準確數字的數據類型(NUMERIC
,
DECIMAL
, INTEGER
,和SMALLINT
),也包括近似數字的數據類型(FLOAT
,
REAL
,和DOUBLE PRECISION
)。關鍵詞INT
是INTEGER
的一個同義詞,而關鍵詞DEC
是DECIMAL
一個同義詞。
NUMERIC
和DECIMAL
類型被MySQL實現為同樣的類型,這在SQL92標準允許。他們被用於保存值,該值的準確精度是極其重要的值,例如與金錢有關的數據。當聲明一個類是這些類型之一時,精度和規模的能被(並且通常是)指定﹔例如:
salary DECIMAL(9,2)
在這個例子中,9
(precision
)代表將被用於儲存值的總的小數位數,而2
(scale
)代表將被用於儲存小數點後的位數。因此,在這種情況下,能被儲存在salary
列中的值的範圍是從-9999999.99
到9999999.99
。在ANSI/ISO
SQL92中,句法DECIMAL(p)
等價於DECIMAL(p,0)
。同樣,句法DECIMAL
等價於DECIMAL(p,0)
,這裡實現被允許決定值p
。MySQL當前不支援DECIMAL
/NUMERIC
數據類型的這些變種形式的任一種。這一般說來不是一個嚴重的問題,因為這些類型的主要益處得自於明顯地控制精度和規模的能力。
DECIMAL
和NUMERIC
值作為字符串儲存,而不是作為二進制浮點數,以便保存那些值的小數精度。一個字符用於值的每一位、小數點(如果scale
>0)和“-”符號(對於負值)。如果scale
是0,DECIMAL
和NUMERIC
值不包含小數點或小數部分。
DECIMAL
和NUMERIC
值得最大的範圍與DOUBLE
一樣,但是對於一個給定的DECIMAL
或NUMERIC
列,實際的範圍可由制由給定列的precision
或scale
限制。當這樣的列賦給了小數點後面的位超過指定scale
所允許的位的值,該值根據scale
四捨五入。當一個DECIMAL
或NUMERIC
列被賦給了其大小超過指定(或內定的)precision
和scale
隱含的範圍的值,MySQL儲存表示那個範圍的相應的端點值。
作為對ANSI/ISO SQL92標準的擴展,MySQL也支援上表所列的整型類型TINYINT
、MEDIUMINT和BIGINT
。另一個擴展是MySQL支援可選地指定一個整型值顯示的寬度,用括號跟在基本關鍵詞之後(例如,INT(4)
)。這個可選的寬度指定被用於其寬度小於列指定寬度的值得左填補顯示,但是不限制能在列中被儲存的值的範圍,也不限制值將被顯示的位數,其寬度超過列指定的寬度。當與可選的擴展屬性ZEROFILL
一起使用時,內定的空格填補用零代替。例如,對於聲明為INT(5)
ZEROFILL
的列,一個為4的值作為00004
被檢索。注意,如果你在一個整型列儲存超過顯示寬度的更大值,當MySQL對於某些複雜的聯結(join)產生臨時表時,你可能會遇到問題,因為在這些情況下,MySQL相信數據確實適合原來的列寬度。
所有的整型類型可以有一個可選(非標準的)屬性UNSIGNED
。當你想要在列中僅允許正數並且你需要一個稍大一點的列範圍,可以使用無符號值。
FLOAT
類型被用來標示近似數字的數據類型。ANSI/ISO SQL92標準允許一個可選的精度說明(但不是指數的範圍),跟在關鍵詞FLOAT
後面的括號內位數。MySQL實現也支援這個可選的精度說明。當關鍵詞FLOAT
被用於一個列類型而沒有精度說明時,MySQL使用4個字節儲存值。一個變種的句法也被支援,在FLOAT
關鍵詞後面的括號給出2個數字。用這個選項,第一個數字繼續表示在字節計算的值儲存需求,而第二個數字指定要被儲存的和顯示跟隨小數點後的位數(就像DECIMAL
和NUMERIC
)。當MySQL要求為這樣一個列,一個小數點後的小數位超過列指定的值,儲存值時,該值被四捨五入,去掉額外的位。
REAL
和DOUBLE PRECISION
類型不接受精度說明。作為對
ANSI/ISO SQL92 標準的擴展,MySQL識別出DOUBLE
作為DOUBLE
PRECISION
類型的一個同義詞。與REAL
精度比用於DOUBLE
PRECISION
的更小的標準要求相反,MySQL實現了兩種,作為8字節雙精度浮點值(當運行不是“Ansi模式”時)。為了最大的移植性,近似數字的數據值的儲存所需代碼應該使用沒有精度或小數位數說明的FLOAT
或DOUBLE
PRECISION
。
當要求在數字的列儲存超出該列類型允許的範圍的值時,MySQL剪切該值到範圍內的正確端點值並且儲存剪切後的結果值。
例如,一個INT
列的範圍是-2147483648
到2147483647
。如果你試圖插入-9999999999
到一個INT
列中,值被剪切到範圍的低部端點,並儲存-2147483648
。同樣,如果你試圖插入9999999999
,2147483647
被儲存。
如果INT
列是UNSIGNED
,列的範圍的大小是相同的,但是它的端點移到了0
和4294967295
。如果你試圖儲存-9999999999
和9999999999
,在列被儲存的值變為0
和4294967296
。
對於ALTER TABLE
、LOAD DATA INFILE
、UPDATE
和多行INSERT
語句,由於剪切所發生的變換作為“警告”被報告。
日期和時間類型是DATETIME
、DATE
、TIMESTAMP
、TIME
和YEAR
。這些的每一個都有合法值的一個範圍,而“零”當你指定確實不合法的值時被使用。注意,MySQL允許你儲存某個“不嚴格地”合法的日期值,例如1999-11-31
,原因我們認為它是應用程式的責任來處理日期檢查,而不是SQL伺服器。為了使日期檢查更“快”,MySQL僅檢查月份在0-12的範圍,天在0-31的範圍。上述範圍這樣被定義是因為MySQL允許你在一個DATE
或DATETIME
列中儲存日期,這裡的天或月是零。這對儲存你不知道準確的日期的一個生日的應用程式來說是極其有用的,在這種情況下,你簡單地儲存日期像1999-00-00
或1999-01-00
。(當然你不能期望從函數如DATE_SUB()
或DATE_ADD()
得到類似以這些日期的正確值)。
當用日期和時間工作時,這裡是的一些要記住的一般考慮:
'98-09-04'
),而不是以其他地方常用的月-日-年或日-月-年的次序(例如,'09-04-98'
、'04-09-98')。
TIME
值被剪切為適當的TIME
範圍端點值。)下表顯示對每種類型的“零”值的格式:
列類型 | “零”值 |
DATETIME |
'0000-00-00 00:00:00' |
DATE |
'0000-00-00' |
TIMESTAMP |
00000000000000 (長度取決於顯示尺寸) |
TIME |
'00:00:00' |
YEAR |
0000 |
'0'
或0
做到,
這更容易寫。 NULL
,因為ODBC不能處理這樣的值。
MySQL本身Y2K安全的(見1.6 2000年一致性),但是呈交給MySQL的輸入值可能不是。一個包含2位年份值的任何輸入是由二義性的,因為世紀是未知的。這樣的值必須被解釋成4位形式,因為MySQL內部使用4位儲存年份。
對於DATETIME
, DATE
, TIMESTAMP
和YEAR
類型,MySQL使用下列規則的解釋二義性的年份值:
00-69
的年值被變換到2000-2069
。 70-99
的年值被變換到1970-1999
。記得這些規則僅僅提供對於你數據的含義的合理猜測。如果MySQL使用的啟發規則不產生正確的值,你應該提供無二義的包含4位年值的輸入。
DATETIME
, DATE
和TIMESTAMP
類型DATETIME
, DATE
和TIMESTAMP
類型是相關的。本節描述他們的特徵,他們是如何類似的而又不同的。
DATETIME
類型用在你需要同時包含日期和時間資訊的值時。MySQL檢索並且以'YYYY-MM-DD
HH:MM:SS'
格式顯示DATETIME
值,支援的範圍是'1000-01-01
00:00:00'
到'9999-12-31 23:59:59'
。(“支援”意味著盡管更早的值可能工作,但不能保証他們可以。)
DATE
類型用在你僅需要日期值時,沒有時間部分。MySQL檢索並且以'YYYY-MM-DD'
格式顯示DATE
值,支援的範圍是'1000-01-01'
到'9999-12-31'
。
TIMESTAMP
列類型提供一種類型,你可以使用它自動地用當前的日期和時間標記INSERT
或UPDATE
的操作。如果你有多個TIMESTAMP
列,只有第一個自動更新。
自動更新第一個TIMESTAMP
列在下列任何條件下發生:
INSERT
或LOAD DATA INFILE
語句中指定。
UPDATE
語句中指定且一些另外的列改變值。(注意一個UPDATE
設置一個列為它已經有的值,這將不引起TIMESTAMP
列被更新,因為如果你設置一個列為它當前的值,MySQL為了效率而忽略更改。)TIMESTAMP
列為NULL
. 除第一個以外的TIMESTAMP
列也可以設置到當前的日期和時間,只要將列設為NULL
,或NOW()
。
通過明確地設置希望的值,你可以設置任何TIMESTAMP
列為不同於當前日期和時間的值,即使對第一個TIMESTAMP
列也是這樣。例如,如果,當你創建一個行時,你想要一個TIMESTAMP
被設置到當前的日期和時間,但在以後無論何時行被更新時都不改變,你可以使用這個屬性:
TIMESTAMP
列為它的當前值。
另一方面,你可能發現,當行被創建並且遠離隨後的更改時,很容易用一個你用NOW()
初始化的DATETIME
列。
TIMESTAMP
值可以從1970的某時的開始一直到2037年,精度為一秒,其值作為數字顯示。
在MySQL檢索並且顯示TIMESTAMP
值取決於顯示尺寸的格式如下表。“完整”TIMESTAMP
格式是14位,但是TIMESTAMP
列可以用更短的顯示尺寸創造:
列類型 | 顯示格式 |
TIMESTAMP(14) |
YYYYMMDDHHMMSS |
TIMESTAMP(12) |
YYMMDDHHMMSS |
TIMESTAMP(10) |
YYMMDDHHMM |
TIMESTAMP(8) |
YYYYMMDD |
TIMESTAMP(6) |
YYMMDD |
TIMESTAMP(4) |
YYMM |
TIMESTAMP(2) |
YY |
所有的TIMESTAMP
列都有同樣的儲存大小,不考慮顯示尺寸。最常見的顯示尺寸是6、8、12、和14。你可以在表創建時間指定一個任意的顯示尺寸,但是值0或比14大被強制到14。在從1∼13範圍的奇數值尺寸被強制為下一個更大的偶數。
使用一個常用的格式集的任何一個,你可以指定DATETIME
、DATE
和TIMESTAMP
值:
'YYYY-MM-DD HH:MM:SS'
或'YY-MM-DD HH:MM:SS'
格式的一個字符串。允許一種“寬鬆”的語法--任何標點可用作在日期部分和時間部分之間的分隔符。例如,'98-12-31
11:30:45'
、'98.12.31 11+30+45'
、'98/12/31 11*30*45'
和'98@12@31
11^30^45'
是等價的。 'YYYY-MM-DD'
或'YY-MM-DD'
格式的一個字符串。允許一種“寬鬆”的語法。例如,'98-12-31'
,
'98.12.31'
, '98/12/31'
和'98@12@31'
是等價的。 'YYYYMMDDHHMMSS'
或'YYMMDDHHMMSS'
格式的沒有任何分隔符的一個字符串,例如,'19970523091528'
和'970523091528'
被解釋為'1997-05-23
09:15:28'
,但是'971122459015'
是不合法的(它有毫無意義的分鐘部分)且變成'0000-00-00
00:00:00'
。 'YYYYMMDD'
或'YYMMDD'
格式的沒有任何分隔符的一個字符串,如果字符串認為是一個日期。例如,'19970523'
和'970523'
被解釋作為'1997-05-23'
,但是'971332'
是不合法的(
它有無意義的月和天部分)且變成'0000-00-00'
。 YYYYMMDDHHMMSS
或YYMMDDHHMMSS
格式的一個數字,如果數字認為是一個日期。例如,19830905132800
和830905132800
被解釋作為'1983-09-05
13:28:00'
。 YYYYMMDD
或YYMMDD
格式的一個數字,如果數字認為是一個日期。例如,19830905
和830905
被解釋作為'1983-09-05'
。
DATETIME
, DATE
或TIMESTAMP
上下文環境中接受的函數,例如NOW()
或CURRENT_DATE
。
不合法DATETIME
, DATE
或TIMESTAMP
值被變換到適當類型的“零”值('0000-00-00
00:00:00'
, '0000-00-00'
或00000000000000
)。
對於包括的日期部分分隔符的指定為字符串的值,不必要為小於10
的月或天的值指定2位數字,'1979-6-9'
與'1979-06-09'
是一樣的。同樣,
對於包括的時間部分分隔符的指定為字符串的值,不必為小於10
的小時、月或秒指定2位數字,'1979-10-30
1:2:3'
與'1979-10-30 01:02:03'
是一樣的。
指定為數字應該是6、8、12或14位長。如果數字是8或14位長,它被假定以YYYYMMDD
或YYYYMMDDHHMMSS
格式並且年份由頭4位數字給出。如果數字是6或12位長,它被假定是以YYMMDD
或YYMMDDHHMMSS
格式且年份由頭2位數字給出。不是這些長度之一的數字通過填補前頭的零到最接近的長度來解釋。
指定為無分隔符的字符串用它們給定的長度來解釋。如果字符串長度是8或14個字符,年份被假定頭4個字符給出,否則年份被假定由頭2個字符給出。對於字符串中呈現的多個部分,字符串從左到右邊被解釋,以找出年、月、日、小時、分鐘和秒值,這意味著,你不應該使用少於
6 個字符的字符串。例如,如果你指定'9903'
,認為將代表1999年3月,你會發現MySQL把一個“零”日期插入到你的表中,這是因為年份和月份值99
和03
,但是日期部分丟失(零),因此該值不是一個合法的日期。
TIMESTAMP
列使用被指定的值的完整精度的儲存合法的值,不考慮顯示大小。這有幾個含意:
TIMESTAMP(4)
或TIMESTAMP(2)
。否則,值將不是一個合法的日期並且0
將被儲存。
ALTER TABLE
拓寬一個狹窄的TIMESTAMP
列,以前被“隱蔽”的資訊將被顯示。
TIMESTAMP
列不會導致資訊失去,除了感覺上值在顯示時,較少的資訊被顯示出。
TIMESTAMP
值被儲存為完整精度,直接操作儲存值的唯一函數是UNIX_TIMESTAMP()
,其他函數操作在格式化了的檢索的值上,這意味著你不能使用函數例如HOUR()
或SECOND()
,除非TIMESTAMP
值的相關部分被包含在格式化的值中。例如,一個TIMESTAMP
列的HH
部分部被顯示,除非顯示大小至少是10,因此在更短的TIMESTAMP
值上試試使用HOUR()
產生一個無意義的結果。
在某種程度上,你可以把一種日期類型的值賦給一個不同的日期類型的對像。然而,這可能值有一些改變或資訊的損失:
DATE
值賦給一個DATETIME
或TIMESTAMP
對像,結果值的時間部分被設置為'00:00:00'
,因為DATE
值不包含時間資訊。
DATETIME
或TIMESTAMP
值賦給一個DATE
對像,結果值的時間部分被刪除,因為DATE
類型不儲存時間資訊。
DATETIME
, DATE
和TIMESTAMP
值全都可以用同樣的格式集來指定,但所有類型不都有同樣的值範圍。例如,TIMESTAMP
值不能比1970
早或比2037
網晚,這意味著,一個日期例如'1968-01-01'
,當作為一個DATETIME
或DATE
值合法時,它不是一個正確TIMESTAMP
值,並且如果賦值給這樣一個對像,它將被變換到0
。
當指定日期值時,當心某些缺陷:
'10:11:12'
可能看起來像時間值,因為“:”分隔符,但是如果在一個日期中使用,上下文將作為年份被解釋成'2010-11-12'
。值'10:45:15'
將被變換到'0000-00-00'
,因為'45'
不是一個合法的月份。
00-69
範圍的年值被變換到2000-2069
。 70-99
圍的年值被變換到1970-1999
。 TIME
類型MySQL檢索並以'HH:MM:SS'
格式顯示TIME
值(或對大小時值,'HHH:MM:SS'
格式)。TIME
值的範圍可以從'-838:59:59'
到'838:59:59'
。小時部分可能很大的的原因是TIME
類型不僅可以被使用在表示一天的時間(它必須是不到24個小時),而且用在表示在2個事件之間經過的時間或時間間隔(它可以是比24個小時大些,或甚至是負值)。
你能用多中格式指定TIME
值:
'HH:MM:SS'
格式的一個字符串。“寬鬆”的語法被允許--任何標點符號可用作時間部分的分隔符,例如,'10:11:12'
和'10.11.12'
是等價的。
'HHMMSS'
格式的一個字符串,如果它作為一個時間解釋。例如,'101112'
被理解為'10:11:12'
,但是'109712'
是不合法的(它有無意義的分鐘部分)並變成'00:00:00'
。
HHMMSS
格式的一個數字,如果它能解釋為一個時間。例如,101112
被理解為'10:11:12'
。
TIME
上下文接受的函數,例如CURRENT_TIME
。
對於作為包括一個時間分隔符的字符串被指定的TIME
值,不必為小於10
的小時、分鐘或秒值指定2位數字,'8:3:2'
與'08:03:02'
是一樣的。
將“短的”TIME
值賦值給一個TIME
行列是要格外小心。MySQL使用最右位代表秒的假設來解釋值。(MySQL將TIME
值解釋為經過的時間,而非作為一天的時間
)例如,你可能想到'11:12'
、'1112'
和1112
意味著'11:12:00'
(11點12分),但是MySQL解釋他們為'00:11:12'
(11分12秒)。同樣,'12'
和12
被解釋為'00:00:12'
。
但是超出TIME
範圍之外的值是樣合法的,它被剪切到範圍適當的端點值。例如,'-850:00:00'
和'850:00:00'
被變換到'-838:59:59'
和'838:59:59'
。
不合法的TIME
值被變換到'00:00:00'
。注意,既然'00:00:00'
本身是一個合法的TIME
值,沒有其他方法區分表中儲存的一個'00:00:00'
值,原來的值是否被指定為'00:00:00'
或它是否是不合法的。
YEAR
類型YEAR
類型是一個 1 字節類型用於表示年份。
MySQL檢索並且以YYYY
格式顯示YEAR
值,其範圍是1901
到2155
。
你能用多種格式指定YEAR
值:
'1901'
到'2155'
範圍的一個4位字符串。 1901
到2155
範圍的一個4位數字。 '00'
到'99'
範圍的一個2位字符串.在'00'
到'69'
和'70'
到'99'
範圍的值被變換到在2000
到2069
範圍和1970
到1999
的YEAR
值。1
到99
範圍的一個2位數字。在範圍1
到69
和70
到99
的值被變換到在範圍2001
到2069
和1970
到1999
的YEAR
的值。注意對於2位數字的範圍略微不同於2位數字字符串的範圍,因為你不能直接指定零作為一個數字並且把它解釋為2000
。你必須作為一個字符串'0'
或'00'
指定它,它將被解釋為0000
。
YEAR
上下文環境中接受的函數,例如NOW()
。
不合法YEAR
值被變換到0000
。
字符串類型是CHAR
、VARCHAR
、BLOB
、TEXT
、ENUM
和SET
。
CHAR
和VARCHAR
類型CHAR
和VARCHAR
類型是類似的,但是在他們被儲存和檢索的方式不同。
一個CHAR
列的長度被修正為在你創造表時你所聲明的長度。長度可以是1和255之間的任何值。(在MySQL
3.23中,CHAR
長度可以是0∼255。) 當CHAR
值被儲存時,他們被用空格在右邊填補到指定的長度。當CHAR
值被檢索時,拖後的空格被刪去。
在VARCHAR
列中的值是變長字符串。你可以聲明一個VARCHAR
列是在1和255之間的任何長度,就像對CHAR
列。然而,與CHAR
相反,VARCHAR
值只儲存所需的字符,外加一個字節記錄長度,值不被填補﹔相反,當值被儲存時,拖後的空格被刪去。(這個空格刪除不同於ANSI
SQL規範。)
如果你把一個超過列最大長度的值賦給一個CHAR
或VARCHAR
列,值被截斷以適合它。
下表顯示了兩種類型的列的不同,通過演示儲存變長字符串值到CHAR(4)
和VARCHAR(4)
列:
值 | CHAR(4) |
儲存需求 | VARCHAR(4) |
儲存需求 |
'' |
' ' |
4 個字節 | '' |
1 字節 |
'ab' |
'ab ' |
4 個字節 | 'ab' |
3 個字節 |
'abcd' |
'abcd' |
4 個字節 | 'abcd' |
5 個字節 |
'abcdefgh' |
'abcd' |
4 個字節 | 'abcd' |
5 個字節 |
從CHAR(4)
和VARCHAR(4)
列檢索的值在每種情況下都是一樣的,因為拖後的空格從檢索的CHAR
列上被刪除。
在CHAR
和VARCHAR
列中儲存和比較值是以大小寫不區分的方式進行的,除非當桌子被創建時,BINARY
屬性被指定。BINARY
屬性意味著該列的值根據MySQL伺服器正在運行的機器的ASCII順序以大小寫區分的方式儲存和比較。
BINARY
屬性是“粘性”的。這意味著,如果標記了BINARY
的列用於一個表達式中,整個的表達式作為一個BINARY
值被比較。
MySQL在表創建時可以隱含地改變一個CHAR
或VARCHAR
列的類型。見7.7.1 隱含的的列說明改變。
BLOB
和TEXT
類型一個BLOB
是一個能保存可變數量的數據的二進制的大對像。4個BLOB
類型TINYBLOB
、BLOB
、MEDIUMBLOB
和LONGBLOB
僅僅在他們能保存值的最大長度方面有所不同。見7.3.1 列類型儲存需求。
4個TEXT
類型TINYTEXT
、TEXT
、MEDIUMTEXT
和LONGTEXT
對應於4個BLOB
類型,並且有同樣的最大長度和儲存需求。在BLOB
和TEXT
類型之間的唯一差別是對BLOB
值的排序和比較以大小寫敏感方式執行,而對TEXT
值是大小寫不敏感的。換句話說,一個TEXT
是一個大小寫不敏感的BLOB
。
如果你把一個超過列類型最大長度的值賦給一個BLOB
或TEXT
列,值被截斷以適合它。
在大多數方面,你可以認為一個TEXT
行列是你所希望大的一個VARCHAR
列。同樣,你可以認為一個BLOB
列是一個VARCHAR
BINARY
列。差別是:
BLOB
和TEXT
列上索引。更舊的MySQL版本不支援這個。
BLOB
和TEXT
列沒有拖後空格的刪除,因為對VARCHAR
列有刪除。
BLOB
和TEXT
列不能有DEFAULT
值。
MyODBC定義BLOB
為LONGVARBINARY
,TEXT
值為LONGVARCHAR
。
因為BLOB
和TEXT
值可以是非常長的,當使用他們時,你可能遇到一些限制:
BLOB
或TEXT
列上使用GROUP BY
或ORDER
BY
,你必須將列值變換成一個定長對像。這樣做的標準方法是用SUBSTRING
函數。例如:
mysql> select comment from tbl_name,substring(comment,20) as substr ORDER BY substr;
如果你不這樣做,在排序時,只有列的首max_sort_length
個字節被使用,內定的max_sort_length
是1024﹔這個值能在啟動mysqld
伺服器時使用-O
選擇改變。你可以在包含BLOB
或TEXT
值得一個表達式上分組(group),通過指定列的位置或使用一個別名:
mysql> select id,substring(blob_col,1,100) from tbl_name GROUP BY 2; mysql> select id,substring(blob_col,1,100) as b from tbl_name GROUP BY b;
BLOB
或TEXT
對像的最大尺寸由其類型決定,但是你能在客戶與伺服器之間是實際傳輸的最大值由可用的內存數量和通訊緩衝區的大小來決定。你能改變消息緩衝區大小,但是你必須在伺服器和客戶兩端做。見10.2.3 調節伺服器參數。 注意,每個BLOB
或TEXT
值內部由一個獨立分配的對像表示。這與所有的其他列類型相反,它們是在打開表時,按列被分配一次儲存。
ENUM
類型一個ENUM
是一個字符對像,其值通常從一個在表創建時明確被列舉的允許值的一張表中選擇。
在下列的某個情形下,值也可以空字符串(""
)或NULL
:
ENUM
(即,一個不在允許的值列表中的字符串),空字符串作為一個特殊錯誤的值被插入。
ENUM
被聲明為NULL
,NULL
也是列的合法值,並且內定值是NULL
。如果一個ENUM
被聲明為NOT
NULL
,內定值是允許值的列表的第一成員。 每枚舉值有一個編號:
SELECT
語句找出被賦給無效ENUM
值的行:
mysql> SELECT * FROM tbl_name WHERE enum_col=0;
NULL
值的編號是NULL
。 例如,指定為ENUM("one", "two", "three")
的列可以有顯示在下面的值的任何一個。每個值的編號也被顯示:
值 | 編號 |
NULL |
NULL |
"" |
0 |
"one" |
1 |
"two" |
2 |
"three" |
3 |
枚舉可以有最大65535個成員。
當你把值賦給一個ENUM
列時,字母的大小寫是無關緊要的。然而,以後從列中檢索的值大小寫匹配在表創建時用來指定允許值的值的大小寫。
如果你在一個數字的上下文環境中檢索一個ENUM
,列值的編號被返回。如果你儲存一個數字到一個ENUM
中,數字被當作一個標號,並且儲存的值是該編號的枚舉成員。
ENUM
值根據列說明列舉的枚舉成員的次序被排序。(換句話說,ENUM
值根據他們的編號數字被排序)
例如,對ENUM("a", "b"),"a"
排在"b"
前面,但是對ENUM("b",
"a"),"b"
排在"a"
前面。空字符串排序非空字符串之前,並且NULL
排在所有其他枚舉值之前。
如果你想要得到一個ENUM
列的所有可能的值,你應該使用:SHOW
COLUMNS FROM table_name LIKE enum_column_name
並且分析在第二列的ENUM
定義。
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
定義。
為了最有效地使用儲存空間,試著在所有的情況下使用最精確的類型。例如,如果一個整數列被用於在之間1
和99999
的值,
MEDIUMINT UNSIGNED
是最好的類型。
貨幣值的精確表示是一個常見的問題。在MySQL,你應該使用DECIMAL
類型,它作為一個字符串被儲存,不會發生精確性的損失。如果精確性不是太重要,DOUBLE
類型也是足夠好的。
對高精度,你總是能變換到以一個BIGINT
儲存的定點類型。這允許你用整數做所有的計算,並且僅在必要時將結果轉換回浮點值。見10.6 選擇一個表類型。
所有的MySQL列類型能被索引。在相關的列上的使用索引是改進SELECT
操作性能的最好方法。
一個表最多可有16個索引。最大索引長度是256個字節,盡管這可以在編譯MySQL時被改變。
對於CHAR
和VARCHAR
列,你可以索引列的前綴。這更快並且比索引整個列需要較少的磁碟空間。在CREATE
TABLE
語句中索引列前綴的語法看起來像這樣:
KEY index_name (col_name(length))
下面的例子為name
列的頭10個字符創建一個索引:
mysql> CREATE TABLE test ( name CHAR(200) NOT NULL, KEY index_name (name(10)));
對於BLOB
和TEXT
列,你必須索引列的前綴,你不能索引列的全部。
MySQL能在多個列上創建索引。一個索引可以由最多15個列組成。(在CHAR
和VARCHAR
列上,你也可以使用列的前綴作為一個索引的部分)。
一個多重列索引可以認為是包含通過合並(concatenate)索引列值創建的值的一個排序數組。
當你為在一個WHERE
子句索引的第一列指定已知的數量時,MySQL以這種方式使用多重列索引使得查詢非常快速,即使你不為其他列指定值。
假定一張表使用下列說明創建:
mysql> CREATE TABLE test ( id INT NOT NULL, last_name CHAR(30) NOT NULL, first_name CHAR(30) NOT NULL, PRIMARY KEY (id), INDEX name (last_name,first_name));
那麼索引name
是一個在last_name
和first_name
上的索引,這個索引將被用於在last_name
或last_name
和first_name
的一個已知範圍內指定值的查詢,因此,name
索引將使用在下列查詢中:
mysql> SELECT * FROM test WHERE last_name="Widenius"; mysql> SELECT * FROM test WHERE last_name="Widenius" AND first_name="Michael"; mysql> SELECT * FROM test WHERE last_name="Widenius" AND (first_name="Michael" OR first_name="Monty"); mysql> SELECT * FROM test WHERE last_name="Widenius" AND first_name >="M" AND first_name < "N";
然而,name
索引將不用在下列詢問中:
mysql> SELECT * FROM test WHERE first_name="Michael"; mysql> SELECT * FROM test WHERE last_name="Widenius" OR first_name="Michael";
關於MySQL使用索引改進性能的方式的更多的資訊,見10.4 使用MySQL索引。
為了跟容易地使用為其他供應商的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類型報告表結構。
SELECT
和WHERE
子句中的函數在一個SQL語句中的select_expression
或where_definition
可由使用下面描述的函數的任何表達式組成。
包含NULL
的一個表達式總是產生一個NULL
值,否則除非表達式所包含的操作符和函數在文檔中說明。
注意:在一個函數名和跟隨它的括號之間不許沒有空格。這幫助MySQL分析器區分函數調用和具有相同名字的對表或列的引用,盡管允許在參數周圍有空格。
為了簡潔,例子以縮寫形式顯示從mysql
程式輸出。因此:
mysql> select MOD(29,9); 1 rows in set (0.00 sec) +-----------+ | mod(29,9) | +-----------+ | 2 | +-----------+
被顯示為這樣:
mysql> select MOD(29,9); -> 2
( ... )
mysql> select 1+2*3; -> 7 mysql> select (1+2)*3; -> 9
一般的算術操作符是可用的。注意在-
、+
和*
情況下,如果兩個參數是整數,結果用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
/
mysql> select 3/5; -> 0.60
被零除產生一個NULL
結果:
mysql> select 102/(1-1); -> NULL
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
所有的邏輯函數返回1
(TRUE)或0
(FALSE)。
NOT
!
0
,返回1
,否則返回0
。例外:
NOT NULL
返回NULL
。 mysql> select NOT 1; -> 0 mysql> select NOT NULL; -> NULL mysql> select ! (1+1); -> 0 mysql> select ! 1+1; -> 1
最後的例子返回1
,因為表達式作為(!1)+1
計算。
OR
||
0
並且不NULL
,返回1
。
mysql> select 1 || 0; -> 1 mysql> select 0 || 0; -> 0 mysql> select 1 || NULL; -> 1
AND
&&
0
或NULL
,返回0
,否則返回1
。
mysql> select 1 && NULL; -> 0 mysql> select 1 && 0; -> 0
比較操作得出值1
(TRUE)、0
(FALSE)或NULL
等結果。這些函數工作運用在數字和字符串上。當需要時,字符串自動地被變換到數字且數字到字符串(如在Perl)。
MySQL使用下列規則執行比較:
NULL
,比較的結果是NULL
,除了<=>
操作符。
TIMESTAMP
或DATETIME
列而其他參數是一個常數,在比較執行前,常數被轉換為一個時間標記。這樣做是為了對ODBC更友好。
內定地,字符串使用當前的字符集以大小寫敏感的方式進行(內定為ISO-8859-1 Latin1,它對英語運用得很出色)。
下面的例子演示了對於比較操作字符串到數字的轉換:
mysql> SELECT 1 > '6x'; -> 0 mysql> SELECT 7 > '6x'; -> 1 mysql> SELECT 0 > 'x6'; -> 0 mysql> SELECT 0 = 'x6'; -> 1
=
mysql> select 1 = 0; -> 0 mysql> select '0' = 0; -> 1 mysql> select '0.0' = 0; -> 1 mysql> select '0.01' = 0; -> 0 mysql> select '.01' = 0.01; -> 1
<>
!=
mysql> select '.01' <> '0.01'; -> 1 mysql> select .01 <> '0.01'; -> 0 mysql> select 'zapp' <> 'zappp'; -> 1
<=
mysql> select 0.1 <= 2; -> 1
<
mysql> select 2 <= 2; -> 1
>=
mysql> select 2 >= 2; -> 1
>
mysql> select 2 > 2; -> 0
<=>
mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1 1 0
IS NULL
IS NOT NULL
NULL
mysql> select 1 IS NULL, 0 IS NULL, NULL IS NULL: -> 0 0 1 mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
expr BETWEEN min AND max
expr
對大於或等於min
且expr
是小於或等於max
,BETWEEN
返回1
,否則它返回0
。如果所有的參數類型是一樣得,這等價於表達式(min
<= expr AND expr <= max)
。第一個參數(expr
)決定比較如何被執行。如果expr
是一個大小寫不敏感的字符串表達式,進行一個大小寫不敏感的字符串比較。如果expr
是一個大小寫敏感的字符串表達式,進行一個大小寫敏感的字符串比較。如果expr
是一個整數表達式,進行整數比較。否則,進行一個浮點(實數)比較。
mysql> select 1 BETWEEN 2 AND 3; -> 0 mysql> select 'b' BETWEEN 'a' AND 'c'; -> 1 mysql> select 2 BETWEEN 2 AND '3'; -> 1 mysql> select 2 BETWEEN 2 AND 'x-3'; -> 0
expr IN (value,...)
expr
是在IN
表中的任何值,返回1
,否則返回0
。如果所有的值是常數,那麼所有的值根據expr
類型被計算和排序,然後項目的搜索是用二進制的搜索完成。這意味著如果IN
值表全部由常數組成,IN
是很快的。如果expr
是一個大小寫敏感的字符串表達式,字符串比較以大小寫敏感方式執行。
mysql> select 2 IN (0,3,5,'wefwf'); -> 0 mysql> select 'wefwf' IN (0,3,5,'wefwf'); -> 1
expr NOT IN (value,...)
NOT (expr IN (value,...))
相同。 ISNULL(expr)
expr
是NULL
,ISNULL()
返回1
,否則它返回0
。
mysql> select ISNULL(1+1); -> 0 mysql> select ISNULL(1/0); -> 1
COALESCE(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
通常,如果在字符串比較中的任何表達式是區分大小寫的,比較以大小寫敏感的方式執行。
expr LIKE pat [ESCAPE 'escape-char']
1
(TRUE)或0
(FALSE)。用LIKE
,你可以在模式中使用下列2個通配符字符:
% |
匹配任何數目的字符,甚至零個字符 |
_ |
精確匹配一個字符 |
mysql> select 'David!' LIKE 'David_'; -> 1 mysql> select 'David!' LIKE '%D%v%'; -> 1
為了測試一個通配符的文字實例,用轉義字符的加在字符前面。如果你不指定ESCAPE
字符,假定為“\”:
\% |
匹配一% 字符 |
\_ |
匹配一_ 字符 |
mysql> select 'David!' LIKE 'David\_';
-> 0
mysql> select 'David_' LIKE 'David\_';
-> 1
為了指定一個不同的轉義字符,使用ESCAPE
子句:
mysql> select 'David_' LIKE 'David|_' ESCAPE '|'; -> 1
LIKE
允許用在數字的表達式上!(這是MySQL對ANSI
SQL LIKE
的一個擴充。)
mysql> select 10 LIKE '1%'; -> 1
注意:因為MySQL在字符串中使用C轉義語法(例如,“\n”),你必須在你的LIKE
字符串中重複任何“\”。例如,為了查找“\n”,指定它為“
\\n”,為了查找“\”,指定它為“\\\\”(反斜線被分析器剝去一次,另一次是在模式匹配完成時,留下一條單獨的反斜線被匹配)。
expr NOT LIKE pat [ESCAPE 'escape-char']
NOT (expr LIKE pat [ESCAPE 'escape-char'])
相同。
expr REGEXP pat
expr RLIKE pat
expr
對一個模式pat
的模式匹配。模式可以是一個擴充的正則表達式。見MySQL 正則表達式句法的 H 描述.如果expr
匹配pat
,返回1
,否則返回0
。RLIKE
是REGEXP
的一個同義詞,提供了與mSQL
的兼容性。注意:因為MySQL在字符串中使用C轉義語法(例如,“\n”),
你必須在你的REGEXP
字符串重複任何“\”。在MySQL
3.23.4中,REGEXP
對於正常的(不是二進制)字符串是忽略大小寫。
mysql> select 'Monty!' REGEXP 'm%y%%'; -> 0 mysql> select 'Monty!' REGEXP '.*'; -> 1 mysql> select 'new*\n*line' REGEXP 'new\\*.\\*line'; -> 1 mysql> select "a" REGEXP "A", "a" REGEXP BINARY "A"; -> 1 0
REGEXP
和RLIKE
使用當前的字符集(內定為ISO-8859-1
Latin1)。 expr NOT REGEXP pat
expr NOT RLIKE pat
NOT (expr REGEXP pat)
相同。 STRCMP(expr1,expr2)
STRCMP()
回來0
,如果第一參數根據當前的排序次序小於第二個,返回-1
,否則返回1
。
mysql> select STRCMP('text', 'text2'); -> -1 mysql> select STRCMP('text2', 'text'); -> 1 mysql> select STRCMP('text', 'text'); -> 0
BINARY
BINARY
操作符強制跟隨它後面的字符串為一個二進制字符串。即使列沒被定義為BINARY
或BLOB
,這是一個強制列比較區分大小寫的簡易方法。
mysql> select "a" = "A"; -> 1 mysql> select BINARY "a" = "A"; -> 0
BINARY
在MySQL 3.23.0中被引入。
IFNULL(expr1,expr2)
expr1
不是NULL
,IFNULL()
返回expr1
,否則它返回expr2
。IFNULL()
返回一個數字或字符串值,取決於它被使用的上下文環境。
mysql> select IFNULL(1,0); -> 1 mysql> select IFNULL(0,10); -> 0 mysql> select IFNULL(1/0,10); -> 10 mysql> select IFNULL(1/0,'yes'); -> 'yes'
IF(expr1,expr2,expr3)
expr1
是TRUE(expr1<>0
且expr1<>NULL
),那麼IF()
返回expr2
,否則它返回expr3
。IF()
返回一個數字或字符串值,取決於它被使用的上下文。
mysql> select IF(1>2,2,3); -> 3 mysql> select IF(1<2,'yes','no'); -> 'yes' mysql> select IF(strcmp('test','test1'),'yes','no'); -> 'no'
expr1
作為整數值被計算,它意味著如果你正在測試浮點或字符串值,你應該使用一個比較操作來做。
mysql> select IF(0.1,1,0); -> 0 mysql> select IF(0.1<>0,1,0); -> 1
在上面的第一種情況中,IF(0.1)
返回0
,因為0.1
被變換到整數值,
導致測試IF(0)
。這可能不是你期望的。在第二種情況中,比較測試原來的浮點值看它是否是非零,比較的結果被用作一個整數。
CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...]
[ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result]
END
result
,其中value=compare-value
。第二個版本中如果第一個條件為真,返回result。如果沒有匹配的result值,那麼結果在ELSE
後的result被返回。如果沒有ELSE
部分,那麼NULL
被返回。
mysql> SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END; -> "one" mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END; -> "true" mysql> SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END; -> NULL
所有的數學函數在一個出錯的情況下返回NULL
。
-
mysql> select - 2;
注意,如果這個操作符與一個BIGINT
使用,返回值是一個BIGINT
!這意味著你應該避免在整數上使用-
,那可能有值-2^63
!
ABS(X)
X
的絕對值。 mysql> select ABS(2); -> 2 mysql> select ABS(-32); -> 32
SIGN(X)
-1
、0
或1
,取決於X
是否是負數、零或正數。
mysql> select SIGN(-32); -> -1 mysql> select SIGN(0); -> 0 mysql> select SIGN(234); -> 1
MOD(N,M)
%
%
操作符)。返回N
被M
除的餘數。
mysql> select MOD(234, 10); -> 4 mysql> select 253 % 7; -> 1 mysql> select MOD(29,9); -> 2
這個函數可安全用於BIGINT
值。
FLOOR(X)
X
的最大整數值。 mysql> select FLOOR(1.23); -> 1 mysql> select FLOOR(-1.23); -> -2
注意返回值被變換為一個BIGINT
!
CEILING(X)
X
的最小整數值。 mysql> select CEILING(1.23); -> 2 mysql> select CEILING(-1.23); -> -1
ROUND(X)
X
的四捨五入的一個整數。 mysql> select ROUND(-1.23); -> -1 mysql> select ROUND(-1.58); -> -2 mysql> select ROUND(1.58); -> 2
ROUND(X,D)
X
的四捨五入的有D
為小數的一個數字。如果D
為0
,結果將沒有小數點或小數部分。
mysql> select ROUND(1.298, 1); -> 1.3 mysql> select ROUND(1.298, 0); -> 1
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
LOG10(X)
X
的以10為底的對數。 mysql> select LOG10(2); -> 0.301030 mysql> select LOG10(100); -> 2.000000 mysql> select LOG10(-100); -> NULL
POW(X,Y)
POWER(X,Y)
X
的Y
次冪。 mysql> select POW(2,2); -> 4.000000 mysql> select POW(2,-2); -> 0.250000
SQRT(X)
X
的平方根。 mysql> select SQRT(4); -> 2.000000 mysql> select SQRT(20); -> 4.472136
PI()
mysql> select PI(); -> 3.141593
COS(X)
X
的餘弦, 在這裡X
以弧度給出。 mysql> select COS(PI()); -> -1.000000
SIN(X)
X
的正弦值,在此X
以弧度給出。 mysql> select SIN(PI()); -> 0.000000
TAN(X)
X
的正切值,在此X
以弧度給出。 mysql> select TAN(PI()+1); -> 1.557408
ACOS(X)
X
反餘弦,即其餘弦值是X
。如果X
不在-1
到1
的範圍,返回NULL
。
mysql> select ACOS(1); -> 0.000000 mysql> select ACOS(1.0001); -> NULL mysql> select ACOS(0); -> 1.570796
ASIN(X)
X
反正弦值,即其正弦值是X
。L
如果X
不在-1
到1
的範圍,返回NULL
。
mysql> select ASIN(0.2); -> 0.201358 mysql> select ASIN('foo'); -> 0.000000
ATAN(X)
X
的反正切值,即其正切值是X
。 mysql> select ATAN(2); -> 1.107149 mysql> select ATAN(-2); -> -1.107149
ATAN2(X,Y)
X
和Y
的反正切。它類似於計算Y/X
的反正切,除了兩個參數的符號被用來決定結果的像限。
mysql> select ATAN(-2,2); -> -0.785398 mysql> select ATAN(PI(),0); -> 1.570796
COT(X)
X
的餘切。 mysql> select COT(12); -> -1.57267341 mysql> select COT(0); -> NULL
RAND()
RAND(N)
0
到1.0
內的隨機浮點值。如果一個整數參數N
被指定,它被用作種子值。
mysql> select RAND(); -> 0.5925 mysql> select RAND(20); -> 0.1811 mysql> select RAND(20); -> 0.1811 mysql> select RAND(); -> 0.2079 mysql> select RAND(); -> 0.7888
你不能在一個ORDER BY
子句用RAND()
值使用列,因為ORDER
BY
將重複計算列多次。然而在MySQL3.23中,你可以做:
SELECT * FROM table_name ORDER BY RAND()
,這是有利於得到一個來自SELECT
* FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000
的集合的隨機樣本。注意在一個WHERE
子句裡的一個RAND()
將在每次WHERE
被執行時重新評估。
LEAST(X,Y,...)
INTEGER
上下文,或所有的參數都是整數值,他們作為整數比較。
REAL
上下文,或所有的參數是實數值,他們作為實數比較。
mysql> select LEAST(2,0); -> 0 mysql> select LEAST(34.0,3.0,5.0,767.0); -> 3.0 mysql> select LEAST("B","A","C"); -> "A"
GREATEST(X,Y,...)
LEAST
一樣的規則進行比較。
mysql> select GREATEST(2,0); -> 2 mysql> select GREATEST(34.0,3.0,5.0,767.0); -> 767.0 mysql> select GREATEST("B","A","C"); -> "C"
在MySQL在 3.22.5 以前的版本, 你能使用MAX()
而不是GREATEST
.
DEGREES(X)
X
,從弧度變換為角度。 mysql> select DEGREES(PI()); -> 180.000000
RADIANS(X)
X
,從角度變換為弧度。 mysql> select RADIANS(90); -> 1.570796
TRUNCATE(X,D)
X
,截斷為D
位小數。如果D
為0
,結果將沒有小數點或小數部分。
mysql> select TRUNCATE(1.223,1); -> 1.2 mysql> select TRUNCATE(1.999,1); -> 1.9 mysql> select TRUNCATE(1.999,0); -> 1
如果結果的長度大於伺服器參數max_allowed_packet
,字符串值函數返回NULL
。見10.2.3 調節伺服器參數。
對於針對字符串位置的操作,第一個位置被標記為1。
ASCII(str)
str
的最左面字符的ASCII代碼值。如果str
是空字符串,返回0
。如果str
是NULL
,返回NULL
。
mysql> select ASCII('2'); -> 50 mysql> select ASCII(2); -> 50 mysql> select ASCII('dx'); -> 100
ORD(str)
((first
byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code...]
返回字符的ASCII代碼值來返回多字節字符代碼。如果最左面的字符不是一個多字節字符。返回與ASCII()
函數返回的相同值。mysql> select ORD('2'); -> 50
CONV(N,from_base,to_base)
N
的字符串數字,從from_base
基變換為to_base
基,如果任何參數是NULL
,返回NULL
。參數N
解釋為一個整數,但是可以指定為一個整數或一個字符串。最小基是2
且最大的基是36
。如果to_base
是一個負數,N
被認為是一個有符號數,否則,N
被當作無符號數。
CONV
以64位點精度工作。 mysql> select CONV("a",16,2); -> '1010' mysql> select CONV("6E",18,8); -> '172' mysql> select CONV(-17,10,-18); -> '-H' mysql> select CONV(10+"10"+'10'+0xa,10,10); -> '40'
BIN(N)
N
的一個字符串表示,在此N
是一個長整數(BIGINT
)數字,這等價於CONV(N,10,2)
。如果N
是NULL
,返回NULL
。
mysql> select BIN(12); -> '1100'
OCT(N)
N
的一個字符串的表示,在此N
是一個長整型數字,這等價於CONV(N,10,8)
。如果N
是NULL,返回NULL
。
mysql> select OCT(12); -> '14'
HEX(N)
N
一個字符串的表示,在此N
是一個長整型(BIGINT
)數字,這等價於CONV(N,10,16)
。如果N
是NULL
,返回NULL
。
mysql> select HEX(255); -> 'FF'
CHAR(N,...)
CHAR()
將參數解釋為整數並且返回由這些整數的ASCII代碼字符組成的一個字符串。NULL
值被跳過。
mysql> select CHAR(77,121,83,81,'76'); -> 'MySQL' mysql> select CHAR(77,77.3,'77.3'); -> 'MMM'
CONCAT(str1,str2,...)
NULL
,返回NULL
。可以有超過2個的參數。一個數字參數被變換為等價的字符串形式。
mysql> select CONCAT('My', 'S', 'QL'); -> 'MySQL' mysql> select CONCAT('My', NULL, 'QL'); -> NULL mysql> select CONCAT(14.3); -> '14.3'
LENGTH(str)
OCTET_LENGTH(str)
CHAR_LENGTH(str)
CHARACTER_LENGTH(str)
str
的長度。 mysql> select LENGTH('text'); -> 4 mysql> select OCTET_LENGTH('text'); -> 4
LOCATE(substr,str)
POSITION(substr IN str)
substr
在字符串str
第一個出現的位置,如果substr
不是在str
裡面,返回0
.
mysql> select LOCATE('bar', 'foobarbar'); -> 4 mysql> select LOCATE('xbar', 'foobar'); -> 0
該函數是多字節可靠的。
LOCATE(substr,str,pos)
substr
在字符串str
第一個出現的位置,從位置pos
開始。如果substr
不是在str
裡面,返回0
。mysql> select LOCATE('bar', 'foobarbar',5); -> 7
INSTR(str,substr)
substr
在字符串str
中的第一個出現的位置。這與有2個參數形式的LOCATE()
相同,除了參數被顛倒。
mysql> select INSTR('foobarbar', 'bar'); -> 4 mysql> select INSTR('xbar', 'foobar'); -> 0
LPAD(str,len,padstr)
str
,左面用字符串padstr
填補直到str
是len
個字符長。
mysql> select LPAD('hi',4,'??'); -> '??hi'
RPAD(str,len,padstr)
str
,右面用字符串padstr
填補直到str
是len
個字符長。
mysql> select RPAD('hi',5,'?'); -> 'hi???'
LEFT(str,len)
str
的最左面len
個字符。mysql> select LEFT('foobarbar', 5); -> 'fooba'
RIGHT(str,len)
str
的最右面len
個字符。
mysql> select RIGHT('foobarbar', 4); -> 'rbar'
SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
MID(str,pos,len)
str
返回一個len
個字符的子串,從位置pos
開始。使用FROM
的變種形式是ANSI
SQL92語法。 mysql> select SUBSTRING('Quadratically',5,6); -> 'ratica'
SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
str
的起始位置pos
返回一個子串。 mysql> select SUBSTRING('Quadratically',5); -> 'ratically' mysql> select SUBSTRING('foobarbar' FROM 4); -> 'barbar'
SUBSTRING_INDEX(str,delim,count)
str
的第count
個出現的
分隔符delim
之後的子串。如果count
是正數,返回最後的分隔符到左邊(從左邊數)
的所有字符。如果count
是負數,返回最後的分隔符到右邊的所有字符(從右邊數)。
mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2); -> 'www.mysql' mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2); -> 'mysql.com'
LTRIM(str)
str
。 mysql> select LTRIM(' barbar'); -> 'barbar'
RTRIM(str)
str
。 mysql> select RTRIM('barbar '); -> 'barbar'
該函數對多字節是可靠的。
TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
str
,其所有remstr
前綴或後綴被刪除了。如果沒有修飾符BOTH
、LEADING
或TRAILING
給出,BOTH
被假定。如果remstr
沒被指定,空格被刪除。
mysql> select TRIM(' bar '); -> 'bar' mysql> select TRIM(LEADING 'x' FROM 'xxxbarxxx'); -> 'barxxx' mysql> select TRIM(BOTH 'x' FROM 'xxxbarxxx'); -> 'bar' mysql> select TRIM(TRAILING 'xyz' FROM 'barxxyz'); -> 'barx'
SOUNDEX(str)
str
的一個同音字符串。聽起來“大致相同”的2個字符串應該有相同的同音字符串。一個“標準”的同音字符串長是4個字符,但是SOUNDEX()
函數返回一個任意長的字符串。你可以在結果上使用SUBSTRING()
得到一個“標準”的
同音串。所有非數字字母字符在給定的字符串中被忽略。所有在A-Z之外的字符國際字母被當作元音。
mysql> select SOUNDEX('Hello'); -> 'H400' mysql> select SOUNDEX('Quadratically'); -> 'Q36324'
SPACE(N)
N
個空格字符組成的一個字符串。 mysql> select SPACE(6); -> ' '
REPLACE(str,from_str,to_str)
str
,其字符串from_str
的所有出現由字符串to_str
代替。
mysql> select REPLACE('www.mysql.com', 'w', 'Ww'); -> 'WwWwWw.mysql.com'
REPEAT(str,count)
count
Times次的字符串str
組成的一個字符串。如果count
<= 0
,返回一個空字符串。如果str
或count
是NULL
,返回NULL
。
mysql> select REPEAT('MySQL', 3); -> 'MySQLMySQLMySQL'
REVERSE(str)
str
。 mysql> select REVERSE('abc'); -> 'cba'
INSERT(str,pos,len,newstr)
str
,在位置pos
起始的子串且len
個字符長得子串由字符串newstr
代替。
mysql> select INSERT('Quadratic', 3, 4, 'What'); -> 'QuWhattic'
ELT(N,str1,str2,str3,...)
N
= 1
,返回str1
,如果N
= 2
,返回str2
,等等。如果N
小於1
或大於參數個數,返回NULL
。ELT()
是FIELD()
反運算。
mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo'); -> 'ej' mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo'); -> 'foo'
FIELD(str,str1,str2,str3,...)
str
在str1
, str2
, str3
, ...
清單的索引。如果str
沒找到,返回0
。FIELD()
是ELT()
反運算。
mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 2 mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 0
FIND_IN_SET(str,strlist)
str
在由N
子串組成的表strlist
之中,返回一個1
到N
的值。一個字符串表是被“,”分隔的子串組成的一個字符串。如果第一個參數是一個常數字符串並且第二個參數是一種類型為SET
的列,FIND_IN_SET()
函數被最佳化而使用位運算!如果str
不是在strlist
裡面或如果strlist
是空字符串,返回0
。如果任何一個參數是NULL
,返回NULL
。如果第一個參數包含一個“,”,該函數將工作不正常。
mysql> SELECT FIND_IN_SET('b','a,b,c,d'); -> 2
MAKE_SET(bits,str1,str2,...)
bits
集合中的的字符串組成。str1
對應於位0,str2
對應位1,等等。在str1
,
str2
, ...
中的NULL
串不添加到結果中。 mysql> SELECT MAKE_SET(1,'a','b','c'); -> 'a' mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world'); -> 'hello,world' mysql> SELECT MAKE_SET(0,'a','b','c'); -> ''
EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
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)
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.3.6 日期和時間類型。
這裡是一個使用日期函數的例子。下面的查詢選擇了所有記錄,其date_col
的值是在最後30天以內:
mysql> SELECT something FROM table WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
DAYOFWEEK(date)
date
的星期索引(1
=星期天,2
=星期一,
……7
=星期六)。這些索引值對應於ODBC標準。 mysql> select DAYOFWEEK('1998-02-03'); -> 3
WEEKDAY(date)
date
的星期索引(0
=星期一,1
=星期二,
……6
= 星期天)。 mysql> select WEEKDAY('1997-10-04 22:23:00'); -> 5 mysql> select WEEKDAY('1997-11-05'); -> 2
DAYOFMONTH(date)
date
的月份中日期,在1
到31
範圍內。
mysql> select DAYOFMONTH('1998-02-03'); -> 3
DAYOFYEAR(date)
date
在一年中的日數, 在1
到366
範圍內。
mysql> select DAYOFYEAR('1998-02-03'); -> 34
MONTH(date)
date
的月份,範圍1
到12
。 mysql> select MONTH('1998-02-03'); -> 2
DAYNAME(date)
date
的星期名字。 mysql> select DAYNAME("1998-02-05"); -> 'Thursday'
MONTHNAME(date)
date
的月份名字。 mysql> select MONTHNAME("1998-02-05"); -> 'February'
QUARTER(date)
date
一年中的季度,範圍1
到4
。 mysql> select QUARTER('98-04-01'); -> 2
WEEK(date)
WEEK(date,first)
date
的周數,範圍在0
到52
。2個參數形式WEEK()
允許你指定星期是否開始於星期天或星期一。如果第二個參數是0
,星期從星期天開始,如果第二個參數是1
,從星期一開始。
mysql> select WEEK('1998-02-20'); -> 7 mysql> select WEEK('1998-02-20',0); -> 7 mysql> select WEEK('1998-02-20',1); -> 8
YEAR(date)
date
的年份,範圍在1000
到9999
。mysql> select YEAR('98-02-03'); -> 1998
HOUR(time)
time
的小時,範圍是0
到23
。mysql> select HOUR('10:05:03'); -> 10
MINUTE(time)
time
的分鐘,範圍是0
到59
。mysql> select MINUTE('98-02-03 10:05:03'); -> 5
SECOND(time)
time
的秒數,範圍是0
到59
。mysql> select SECOND('10:05:03'); -> 3
PERIOD_ADD(P,N)
N
個月到階段P
(以格式YYMM
或YYYYMM
)。以格式YYYYMM
返回值。注意階段參數P
不是日期值。
mysql> select PERIOD_ADD(9801,2); -> 199803
PERIOD_DIFF(P1,P2)
P1
和P2
之間月數,P1
和P2
應該以格式YYMM
或YYYYMM
。注意,時期參數P1
和P2
不是日期值。
mysql> select PERIOD_DIFF(9802,199703); -> 11
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
ADDDATE()
和SUBDATE()
是DATE_ADD()
和DATE_SUB()
的同義詞。在MySQL
3.23中,你可以使用+
和-
而不是DATE_ADD()
和DATE_SUB()
。(見例子)date
是一個指定開始日期的DATETIME
或DATE
值,expr
是指定加到開始日期或從開始日期減去的間隔值一個表達式,expr
是一個字符串﹔它可以以一個“-”開始表示負間隔。type
是一個關鍵詞,指明表達式應該如何被解釋。EXTRACT(type
FROM date)
函數從日期中返回“type”間隔。下表顯示了type
和expr
參數怎樣被關聯:
type 值 |
含義 | 期望的expr 格式 |
SECOND |
秒 | SECONDS |
MINUTE |
分鐘 | MINUTES |
HOUR |
時間 | HOURS |
DAY |
天 | DAYS |
MONTH |
月 | MONTHS |
YEAR |
年 | YEARS |
MINUTE_SECOND |
分鐘和秒 | "MINUTES:SECONDS" |
HOUR_MINUTE |
小時和分鐘 | "HOURS:MINUTES" |
DAY_HOUR |
天和小時 | "DAYS HOURS" |
YEAR_MONTH |
年和月 | "YEARS-MONTHS" |
HOUR_SECOND |
小時, 分鐘, | "HOURS:MINUTES:SECONDS" |
DAY_MINUTE |
天, 小時, 分鐘 | "DAYS HOURS:MINUTES" |
DAY_SECOND |
天, 小時, 分鐘, 秒 | "DAYS HOURS:MINUTES:SECONDS" |
MySQL在expr
格式中允許任何標點分隔符。表示顯示的是建議的分隔符。如果date
參數是一個DATE
值並且你的計算僅僅包含YEAR
、MONTH
和DAY
部分(即,沒有時間部分),結果是一個DATE
值。否則結果是一個DATETIME
值。
mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; -> 1998-01-01 00:00:00 mysql> SELECT INTERVAL 1 DAY + "1997-12-31"; -> 1998-01-01 mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND; -> 1997-12-31 23:59:59 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 SECOND); -> 1998-01-01 00:00:00 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 DAY); -> 1998-01-01 23:59:59 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL "1:1" MINUTE_SECOND); -> 1998-01-01 00:01:00 mysql> SELECT DATE_SUB("1998-01-01 00:00:00", INTERVAL "1 1:1:1" DAY_SECOND); -> 1997-12-30 22:58:59 mysql> SELECT DATE_ADD("1998-01-01 00:00:00", INTERVAL "-1 10" DAY_HOUR); -> 1997-12-30 14:00:00 mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY); -> 1997-12-02 mysql> SELECT EXTRACT(YEAR FROM "1999-07-02"); -> 1999 mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03"); -> 199907 mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03"); -> 20102
如果你指定太短的間隔值(不包括type
關鍵詞期望的間隔部分),MySQL假設你省掉了間隔值的最左面部分。例如,如果你指定一個type
是DAY_SECOND
,值expr
被希望有天、小時、分鐘和秒部分。如果你像"1:10"
這樣指定值,MySQL假設日子和小時部分是丟失的並且值代表分鐘和秒。換句話說,"1:10"
DAY_SECOND
以它等價於"1:10" MINUTE_SECOND
的方式解釋,這對那MySQL解釋TIME
值表示經過的時間而非作為一天的時間的方式有二義性。如果你使用確實不正確的日期,結果是NULL
。如果你增加MONTH
、YEAR_MONTH
或YEAR
並且結果日期大於新月份的最大值天數,日子在新月用最大的天調整。
mysql> select DATE_ADD('1998-01-30', Interval 1 month); -> 1998-02-28
注意,從前面的例子中詞INTERVAL
和type
關鍵詞不是區分大小寫的。
TO_DAYS(date)
date
,返回一個天數(從0年的天數)。 mysql> select TO_DAYS(950501); -> 728779 mysql> select TO_DAYS('1997-10-07'); -> 729669
FROM_DAYS(N)
N
,返回一個DATE
值。 mysql> select FROM_DAYS(729669); -> '1997-10-07'
DATE_FORMAT(date,format)
format
字符串格式化date
值。下列修飾符可以被用在format
字符串中:
%M |
月名字(January ……December ) |
%W |
星期名字(Sunday ……Saturday ) |
%D |
有英語前綴的月份的日期(1st , 2nd , 3rd ,
等等。) |
%Y |
年, 數字, 4 位 |
%y |
年, 數字, 2 位 |
%a |
縮寫的星期名字(Sun ……Sat ) |
%d |
月份中的天數, 數字(00 ……31 ) |
%e |
月份中的天數, 數字(0 ……31 ) |
%m |
月, 數字(01 ……12 ) |
%c |
月, 數字(1 ……12 ) |
%b |
縮寫的月份名字(Jan ……Dec ) |
%j |
一年中的天數(001 ……366 ) |
%H |
小時(00 ……23 ) |
%k |
小時(0 ……23 ) |
%h |
小時(01 ……12 ) |
%I |
小時(01 ……12 ) |
%l |
小時(1 ……12 ) |
%i |
分鐘, 數字(00 ……59 ) |
%r |
時間,12 小時(hh:mm:ss [AP]M ) |
%T |
時間,24 小時(hh:mm:ss ) |
%S |
秒(00 ……59 ) |
%s |
秒(00 ……59 ) |
%p |
AM 或PM |
%w |
一個星期中的天數(0 =Sunday ……6 =Saturday ) |
%U |
星期(0 ……52 ), 這裡星期天是星期的第一天 |
%u |
星期(0 ……52 ), 這裡星期一是星期的第一天 |
%% |
一個文字“%”。 |
所有的其他字符不做解釋被複製到結果中。
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); -> 'Saturday October 1997' mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j'); -> '4th 97 Sat 04 10 Oct 277' mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6'
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)
'1970-01-01 00:00:00'
GMT開始的秒數)。如果UNIX_TIMESTAMP()
用一個date
參數被調用,它返回從'1970-01-01
00:00:00'
GMT開始的秒數值。date
可以是一個DATE
字符串、一個DATETIME
字符串、一個TIMESTAMP
或以YYMMDD
或YYYYMMDD
格式的本地時間的一個數字。
mysql> select UNIX_TIMESTAMP(); -> 882226357 mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00'); -> 875996580
當UNIX_TIMESTAMP
被用於一個TIMESTAMP
列,函數將直接接受值,沒有隱含的“string-to-unix-timestamp”變換。
FROM_UNIXTIME(unix_timestamp)
'YYYY-MM-DD HH:MM:SS'
或YYYYMMDDHHMMSS
格式返回unix_timestamp
參數所表示的值,取決於函數是在一個字符串還是或數字上下文中被使用。
mysql> select FROM_UNIXTIME(875996580); -> '1997-10-04 22:23:00' mysql> select FROM_UNIXTIME(875996580) + 0; -> 19971004222300
FROM_UNIXTIME(unix_timestamp,format)
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
DATABASE()
mysql> select DATABASE(); -> 'test'
USER()
SYSTEM_USER()
SESSION_USER()
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])
crypt()
系統調用加密str
。salt
參數應該是一個有2個字符的字符串。(MySQL
3.22.16中,salt
可以長於2個字符。)mysql> select ENCRYPT("hello"); -> 'VxuFAJXVARROc'
如果crypt()
在你的系統上不可用,ENCRYPT()
總是返回NULL
。ENCRYPT()
只保留str
起始8個字符而忽略所有其他,至少在某些系統上是這樣。這將由底層的crypt()
系統調用的行為決定。
ENCODE(str,pass_str)
pass_str
作為密碼加密str
。為了解密結果,使用DECODE()
。結果是一個二進制字符串,如果你想要在列中保存它,使用一個BLOB
列類型。
DECODE(crypt_str,pass_str)
pass_str
作為密碼解密加密的字符串crypt_str
。crypt_str
應該是一個由ENCODE()
返回的字符串。
MD5(string)
mysql> select MD5("testing") -> 'ae2b1fca515949e5d54fb22b8ed95575'
LAST_INSERT_ID([expr])
AUTO_INCREMENT
列的最後一個自動產生的值。見20.4.29 mysql_insert_id()
。 mysql> select LAST_INSERT_ID(); -> 195
產生的最後ID以每個連接為基礎在伺服器被維護,它不會被其他客戶改變。如果你更新另外一個有非魔術值(即,不是NULL
和不是0
的一個值)的AUTO_INCREMENT
列,它甚至不會被改變。如果expr
作為一個參數在一個UPDATE
子句的LAST_INSERT_ID()
裡面給出,那麼參數值作為一個LAST_INSERT_ID()
值被返回。這可以用來模仿順序:首先創建表:
mysql> create table sequence (id int not null); mysql> insert into sequence values (0);
然後表能被用來產生順序號,像這樣:
mysql> update sequence set id=LAST_INSERT_ID(id+1);
你可以不調用LAST_INSERT_ID()
而產生順序,但是這樣使用函數的實用程式在伺服器上自動維護ID值作為最後自動產生的值。你可以檢索新的ID值,就像你能讀入正常MySQL中的任何正常的AUTO_INCREMENT
值一樣。例如,LAST_INSERT_ID()
(沒有一個參數
)將返回新ID。C API函數mysql_insert_id()
也可被用來得到值。
FORMAT(X,D)
X
為類似於格式'#,###,###.##'
,四捨五入到D
為小數。如果D
為0
,結果將沒有小數點和小數部分。
mysql> select FORMAT(12332.123456, 4); -> '12,332.1235' mysql> select FORMAT(12332.1,4); -> '12,332.1000' mysql> select FORMAT(12332.2,0); -> '12,332'
VERSION()
mysql> 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()
函數重複count
Times次執行表達式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()
若干次可能是明智的,並且注意伺服器機器的負載有多重來解釋結果。
GROUP
BY
子句一起使用的函數如果你在不包含GROUP BY
子句的一個語句中使用聚合函數,它等價於聚合所有行。
COUNT(expr)
SELECT
語句檢索出來的行的非NULL
值的數目。
mysql> select student.student_name,COUNT(*) from student,course where student.student_id=course.student_id GROUP BY student_name;
COUNT(*)
在它返回的檢索出來的行數目上有些不同,不管他們是否包含NULL
值。如果SELECT
從一個表檢索,或沒有檢索出其他列並且沒有WHERE
子句,COUNT(*)
被最佳化以便快速地返回。例如:
mysql> select COUNT(*) from student;
COUNT(DISTINCT expr,[expr...])
mysql> select COUNT(DISTINCT results) from student;
在MySQL中,你可以通過給出一個表達式列表以得到不同的表達式組合的數目。在
ANSI SQL中,你可能必須在CODE(DISTINCT ..)
內進行所有表達式的連接。
AVG(expr)
expr
的平均值。 mysql> select student_name, AVG(test_score) from student GROUP BY student_name;
MIN(expr)
MAX(expr)
expr
的最小或最大值。MIN()
和MAX()
可以有一個字符串參數﹔在這種的情況下,他們返回最小或最大的字符串值。
mysql> select student_name, MIN(test_score), MAX(test_score) from student GROUP BY student_name;
SUM(expr)
expr
的和。注意,如果返回的集合沒有行,它返回NULL!
STD(expr)
STDDEV(expr)
expr
標準差(deviation)。這是對 ANSI SQL
的擴展。該函數的形式STDDEV()
是提供與Oracle的兼容性。 BIT_OR(expr)
expr
裡所有位的位或。計算用 64 位(BIGINT
)精度進行。
BIT_AND(expr)
expr
裡所有位的位與。計算用 64 位(BIGINT
)精度進行。
MySQL擴展了GROUP BY
的用法。你可以不出現在的GROUP
BY
部分的SELECT
表達式中使用列或計算,這表示這個組的任何可能值。你可以使用它是性能更好,避免在不必要的項目上排序和分組。例如,你在下列查詢中不需要在customer.name
上聚合:
mysql> select order.custid,customer.name,max(payments) from order,customer where order.custid = customer.custid GROUP BY order.custid;
在 ANSI SQL中,你將必須將customer.name
加到GROUP BY
子句。在MySQL中,名字是冗餘的。
如果你從GROUP BY
部分省略的列在組中不是唯一的,不要使用這個功能。
在某些情況下,你可以使用MIN()
和MAX()
獲得一個特定的列值,即使它不是唯一的。下例給出從包含sort
列中最小值的行的column
值:
substr(MIN(concat(sort,space(6-length(sort)),column),7,length(column)))
注意,如果你正在使用MySQL
3.22(或更早)或如果你正在試圖遵從ANSI SQL,你不能在GROUP BY
或ORDER
BY
子句中使用表達式。你可以通過使用表達式的一個別名解決此限制:
mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name GROUP BY id,val ORDER BY val;
在MySQL
3.23中,你可以這樣做:
mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
CREATE
DATABASE
句法CREATE DATABASE db_name
CREATE DATABASE
用給定的名字創建一個資料庫。允許的資料庫名字規則在7.1.5
資料庫、桌子、索引、列和別名命名中給出。如果資料庫已經存在,發生一個錯誤。
在MySQL中的資料庫實現成包含對應資料庫中表的文件的目錄。因為資料庫在初始創建時沒有任何表,CREATE
DATABASE
語句只是在MySQL數據目錄下面創建一個目錄。
你也可以用mysqladmin
創建資料庫。見12.1 不同的MySQL程式的概述。
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 程式的概述。
CREATE TABLE
句法CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [select_statement] create_definition: col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [PRIMARY KEY] [reference_definition] or PRIMARY KEY (index_col_name,...) or KEY [index_name] (index_col_name,...) or INDEX [index_name] (index_col_name,...) or UNIQUE [INDEX] [index_name] (index_col_name,...) or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...) [reference_definition] or CHECK (expr) type: TINYINT[(length)] [UNSIGNED] [ZEROFILL] or SMALLINT[(length)] [UNSIGNED] [ZEROFILL] or MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL] or INT[(length)] [UNSIGNED] [ZEROFILL] or INTEGER[(length)] [UNSIGNED] [ZEROFILL] or BIGINT[(length)] [UNSIGNED] [ZEROFILL] or REAL[(length,decimals)] [UNSIGNED] [ZEROFILL] or DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL] or FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL] or DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL] or NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL] or CHAR(length) [BINARY] or VARCHAR(length) [BINARY] or DATE or TIME or TIMESTAMP or DATETIME or TINYBLOB or BLOB or MEDIUMBLOB or LONGBLOB or TINYTEXT or TEXT or MEDIUMTEXT or LONGTEXT or ENUM(value1,value2,value3,...) or SET(value1,value2,value3,...) index_col_name: col_name [(length)] reference_definition: REFERENCES tbl_name [(index_col_name,...)] [MATCH FULL | MATCH PARTIAL] [ON DELETE reference_option] [ON UPDATE reference_option] reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT table_options: TYPE = {ISAM | MYISAM | HEAP} or AUTO_INCREMENT = # or AVG_ROW_LENGTH = # or CHECKSUM = {0 | 1} or COMMENT = "string" or MAX_ROWS = # or MIN_ROWS = # or PACK_KEYS = {0 | 1} or PASSWORD = "string" or DELAY_KEY_WRITE = {0 | 1} or ROW_FORMAT= { default | dynamic | static | compressed } select_statement: [IGNORE | REPLACE] SELECT ... (Some legal select statement)
CREATE TABLE
在當前資料庫刈谻給出的名字創建一個資料庫表。允許的表名的規則在7.1.5
資料庫,桌子,索引,列和別名命名中給出。如果當前資料庫不存在或如果表已經存在,出現一個錯誤。
在MySQL3.22或以後版本中,表名可以被指定為db_name.tbl_name
,不管有沒有當前的資料庫都可以。
在MySQL3.23中,當你創建一張表時,你可以使用TEMPORARY
關鍵詞。如果一個連接死掉,臨時表將自動被刪除,並且其名字是按連接命名。這意味著,2個不同的連接能使用相同的暫時表的名字而不會彼此衝突或與相同名字的現有資料庫表衝突。(現有的表被隱蔽直到臨時表被刪除)。
在MySQL3.23或以後版本中,你可以使用關鍵詞IF NOT
EXISTS
以便如果表已經存在不發生一個錯誤。注意,無法証實表結構是相同的。
每張表tbl_name
由在資料庫目錄的一些文件表示。在MyISAM類型的表的情況下,你將得到:
文件 | 目的 |
tbl_name.frm |
表定義(表格)文件 |
tbl_name.MYD |
數據文件 |
tbl_name.MYI |
索引文件 |
對於各種列類型的性質的更多資訊,見7.3 列類型。
NULL
也不指定NOT NULL
,列被視為指定了NULL
。
AUTO_INCREMENT
。當你插入NULL
值(推薦)或0
到一個AUTO_INCREMENT
列中時,列被設置為value+1
,在此value
是當前表中的列的最大值。AUTO_INCREMENT
順序從1
開始。見20.4.29 mysql_insert_id()
。如果你刪除了包含一個AUTO_INCREMENT
列的最大值的行,值將被重新使用。如果你刪除表中所有的行,順序重新開始。注意:每個表只能有一個AUTO_INCREMENT
列,並且它必須被索引。為了使做MySQL兼容一些
ODBC 應用程式,用下列查詢你可以找出最後插入的行: SELECT * FROM tbl_name WHERE auto_col IS NULL
NULL
值對於TIMESTAMP
列的處理不同於其他列類型。你不能在一個TIMESTAMP
列中儲存一個文字NULL
﹔設置列為NULL
將把它設成當前的日期和時間。因為TIMESTAMP
列表現就這樣,NULL
和NOT
NULL
屬性不以一般方式運用並且如果你指定它們,將被忽略。在另一方面,為了使它MySQL客戶更容易地使用TIMESTAMP
列,伺服器報告這樣的列可以被賦值NULL
(
它是對的),盡管TIMESTAMP
實際上絕不包含一個NULL
值。當你使用DESCRIBE
tbl_name
得到有關你的表的描述時,你就會明白。注意,設置一個TIMESTAMP
列為0
不同於將它設置為NULL
,因為0
是一個有效的TIMESTAMP
值。
DEFAULT
值,MySQL自動地分配一個。如果列可以取NULL
作為值,內定值是NULL
。如果列被聲明為NOT
NULL
,內定值取決於列類型: AUTO_INCREMENT
屬性的數字類型,內定值是0
。對於一個AUTO_INCREMENT
列,內定值是在順序中的下一個值。
TIMESTAMP
的日期和時間類型,內定值是該類型適當的“零”值。對於表中第一個TIMESTAMP
列,內定值是當前的日期和時間。見7.3.6 日期和時間類型。 ENUM
的字符串類型,內定是空字符串。對於ENUM
,內定值是第一個枚舉值。
KEY
是INDEX
的一個同義詞。 UNIQUE
鍵只能有不同的值。如果你試圖用匹配現有行的鍵來增加新行,發生一個錯誤。
PRIMARY KEY
是一個唯一KEY
,它有額外的限制,即所有的關鍵列必須被定義為NOT
NULL
。在MySQL中,鍵被命名為PRIMARY
。一張表只能有一個PRIMARY
KEY
。如果在表中你沒有一個PRIMARY KEY
並且一些應用程式要求PRIMARY
KEY
,MySQL將返回第一個UNIQUE
鍵,它沒有任何NULL
列,作為PRIMARY
KEY
。 PRIMARY KEY
可以是一個多列索引。然而,你不能在一個列說明中使用PRIMARY
KEY
的關鍵字屬性創建一個多列索引。這樣做將僅僅標記單個列作為主鍵。你必須使用PRIMARY
KEY(index_col_name, ...)
語法。 index_col_name
相同的名字,用一個可選的suffix(_2
,
_3
, ...
)使它唯一。你能使用SHOW INDEX FROM
tbl_name
看到一張表的索引名字。見7.21
SHOW
句法(得到表、列等的資訊)。 MyISAM
表類型支援可以有NULL
值的列上的索引。在其他情況下,你必須聲明這樣的列為NOT
NULL
,否則導致一個錯。 col_name(length)
語法,你可以指定僅使用部分的CHAR
或VARCHAR
列的一個索引。這能使索引文件變得更小。見7.3.9 列索引。 MyISAM
表類型支援BLOB
和TEXT
列的索引。當在一個BLOB
或TEXT
列上放置索引時,你必須總是指定索引的長度:
CREATE TABLE test (blob_col BLOB, index(blob_col(10)));
TEXT
或BLOB
列一起使用ORDER BY
或GROUP
BY
時,只使用頭max_sort_length
個字節。見7.3.7.2 BLOB
和TEXT
類型。
FOREIGN KEY
、CHECK
和REFERENCES
子句實際上不做任何事情,其語法僅僅提供兼容性,使得它更容易從其他的SQL伺服器移植代碼並運行借助引用創建表的應用。見5.4 MySQL缺少的功能。 NULL
列占據額外一位,取舍到最接近的字節。 row length = 1 + (sum of column lengths) + (number of NULL columns + 7)/8 + (number of variable-length columns)
table_options
和SELECT
選項只在MySQL 3.23和以後版本中被實現。不同的表類型是:
ISAM | 原來的表處理器 |
MyISAM | 全新二進制可移植的表處理器 |
HEAP | 用於該表的數據僅僅儲存在內存中 |
見9.4 MySQL 表類型。其他表選項被用來最佳化表的行為。在大多數情況下,你不必指定他們任何一個。選項對所有表都適用,如果不是則說明。
AUTO_INCREMENT |
你想要為你的表設定的下一個 auto_increment 值 ( MyISAM ) |
AVG_ROW_LENGTH |
你的表的平均行長度的近似值。你只需要為有變長記錄的表設置它。 |
CHECKSUM |
如果你想要MySQL對每行維持一個校驗和(使表變得更慢以更新但是使它更容易找出損壞的表)設置它為1 ( MyISAM ) |
COMMENT |
對於你的表的一篇60個字符的注釋 |
MAX_ROWS |
你計劃在表中儲存的行的最大數目 |
MIN_ROWS |
你計劃在表中儲存的行的最小數目 |
PACK_KEYS |
如果你想要有更小的索引,將它設為1。這通常使的更新更慢並且讀取更快(MyISAM,ISAM)。 |
PASSWORD |
用一個密碼加密.frm 文件。該選項在標準MySQL版本中不做任何事情。
|
DELAY_KEY_WRITE |
如果想要推遲關鍵表的更新直到表被關閉(MyISAM),將它設置為1。 |
ROW_FORMAT |
定義行應該如何被儲存(為了將來)。 |
當你使用一個MyISAM
表時,MySQL使用max_rows
* avg_row_length
的乘積決定最終的表將有多大。如果你不指定上面的任何選項,對一個表的最大尺寸將是4G(或2G,如果你的作業系統僅支援2G的表)。
CREATE
語句後指定一個SELECT
,MySQL將為在SELECT
中所有的單元創鍵新字段。例如:
mysql> CREATE TABLE test (a int not null auto_increment, primary key (a), key(b)) TYPE=HEAP SELECT b,c from test2;
這將創建一個有3個列的HEAP
表。注意如果在拷貝數據進表時發生任何錯誤,表將自動被刪除。
在某些情況下,MySQL隱含地改變在一個CREATE TABLE
語句給出的一個列說明。(這也可能在ALTER
TABLE
。)
VARCHAR
被改變為CHAR
。 VARCHAR
、TEXT
或BLOB
),所有大於3個字符的CHAR
列被改變為VARCHAR
列。這在任何方面都不影響你如何使用列﹔在MySQL中,VARCHAR
只是儲存字符的一個不同方法。MySQL實施這種改變,是因為它節省空間並且使表操作更快捷。見10.6 選擇一種表格類型。 TIMESTAMP
的顯示尺寸必須是偶數且在2 ∼ 14的範圍內。如果你指定0顯示尺寸或比14大,尺寸被強制為14。從1∼13範圍內的奇數值尺寸被強制為下一個更大的偶數。
TIMESTAMP
列裡面儲存一個文字NULL
﹔將它設為NULL
將設置為當前的日期和時間。因為TIMESTAMP
列表現就是這樣,NULL
和NOT
NULL
屬性不以一般的方式運用並且如果你指定他們,將被忽略。DESCRIBE
tbl_name
總是報告該TIMESTAMP
列可能賦予了NULL
值。
如果你想要知道MySQL是否使用了除你指定的以外的一種列類型,在創建或改變你的表之後,發出一個DESCRIBE
tbl_name
語句即可。
如果你使用myisampack
壓縮一個表,可能會發生改變某些其他的列類型。見10.6.3 壓縮表的特徵。
ALTER TABLE
句法ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...] alter_specification: ADD [COLUMN] create_definition [FIRST | AFTER column_name ] or ADD INDEX [index_name] (index_col_name,...) or ADD PRIMARY KEY (index_col_name,...) or ADD UNIQUE [index_name] (index_col_name,...) or ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT} or CHANGE [COLUMN] old_col_name create_definition or MODIFY [COLUMN] create_definition or DROP [COLUMN] col_name or DROP PRIMARY KEY or DROP INDEX index_name or RENAME [AS] new_tbl_name or table_options
ALTER TABLE
允許你修改一個現有表的結構。例如,你可以增加或刪除列、創造或消去索引、改變現有列的類型、或重新命名列或表本身。你也能改變表的注釋和表的類型。見7.7 CREATE TABLE
句法。
如果你使用ALTER TABLE
修改一個列說明但是DESCRIBE
tbl_name
顯示你的列並沒有被修改,這可能是MySQL因為在7.7.1 隱含的列說明改變中描述的原因之一而忽略了你的修改。例如,如果你試圖將一個VARCHAR
改為CHAR
,MySQL將仍然使用VARCHAR
,如果表包含其他變長的列。
ALTER TABLE
通過制作原來表的一個臨時副本來工作。修改在副本上施行,然後原來的表被刪除並且重新命名一個新的。這樣做使得所有的修改自動地轉向到新表,沒有任何失敗的修改。當ALTER
TABLE
正在執行時,原來的桌可被其他客戶讀取。更新和寫入表被延遲到新表準備好了為止。
ALTER TABLE
,你需要在表上的select、insert、delete、update、create和drop的權限。
IGNORE
是MySQL對ANSI SQL92
的一個擴充,如果在新表中的唯一鍵上有重複,它控制ALTER TABLE
如何工作。如果IGNORE
沒被指定,副本被放棄並且恢復原狀。如果IGNORE
被指定,那麼對唯一鍵有重複的行,只有使用第一行﹔其餘被刪除。
ALTER TABLE
語句中發出多個ADD
、ALTER
、DROP
和CHANGE
子句。這是MySQL對ANSI
SQL92的一個擴充,SQL92在每個ALTER TABLE
語句刈荿允許一個子句。
CHANGE col_name
、DROP col_name
和DROP INDEX
是MySQL對
ANSI SQL92 的擴充。 MODIFY
是 Oracle 對ALTER TABLE
的擴充。 COLUMN
是一個純粹的噪音且可以省略。 ALTER TABLE tbl_name RENAME AS new_name
而沒有任何其他選項,MySQL簡單地重命名對應於表tbl_name
的文件。沒有必要創建臨時表。
create_definition
子句使用CREATE TABLE
相同的ADD
和CHANGE
語法。注意語法包括列名字,不只列類型。見7.7 CREATE TABLE
句法。 CHANGE old_col_name create_definition
子句重命名一個列。為了這樣做,指定舊的和新的列名字和列當前有的類型。例如,重命名一個INTEGER
列,從a
到b
,你可以這樣做:
mysql> ALTER TABLE t1 CHANGE a b INTEGER;
如果你想要改變列的類型而非名字,就算他們是一樣的,CHANGE
語法仍然需要2個列名。例如:
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
然而,在MySQL3.22.16a,你也可以使用MODIFY
來改變列的類型而不是重命名它:
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
CHANGE
或MODIFY
縮短一個列,一個索引存在於該列的部分(例如,如果你有一個VARCHAR
列的頭10個字符的索引),你不能使列短於被索引的字符數目。
CHANGE
或MODIFY
改變一個列類型時,MySQL盡可能試圖很好地變換數據到新類型。
FIRST
或ADD ...
AFTER col_name
在一個表的行內在一個特定的位置增加列。內定是增加到最後一列。
ALTER COLUMN
為列指定新的內定值或刪除老的內定值。如果老的內定值被刪除且列可以是NULL
,新內定值是NULL
。如果列不能是NULL
,MySQL賦予一個內定值。內定值賦值在7.7 CREATE TABLE
句法中描述。
DROP INDEX
刪除一個索引。這是MySQL對 ANSI SQL92
的一個擴充。 DROP PRIMARY KEY
丟棄主索引。如果這樣的索引不存在,它丟棄表中第一個UNIQUE
索引。(如果沒有明確地指定PRIMARY
KEY
,MySQL標記第一個UNIQUE
鍵為PRIMARY
KEY
。)mysql_info()
,你能找出多少記錄被拷貝,
和(當使用IGNORE
時)由於唯一鍵值的重複多少記錄被刪除。 FOREIGN KEY
、CHECK
和REFERENCES
子句實際上不做任何事情,他們的句法僅僅提供兼容性,使得更容易地從其他SQL伺服器移植代碼並且運行借助引用來創建表的應用程式。見5.4 MySQL缺少的功能。 這裡是一個例子,顯示了一些ALTER TABLE
用法。我們以一個如下創建的表t1
開始:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
重命名表,從t1
到t2
:
mysql> ALTER TABLE t1 RENAME t2;
為了改變列a
,從INTEGER
改為TINYINT NOT NULL
(名字一樣),並且改變列b
,從CHAR(10)
改為CHAR(20)
,同時重命名它,從b
改為c
:
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
增加一個新TIMESTAMP
列,名為d
:
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
在列d
上增加一個索引,並且使列a
為主鍵:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);
刪出列c
:
mysql> ALTER TABLE t2 DROP COLUMN c;
增加一個新的AUTO_INCREMENT
整數列,命名為c
:
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD INDEX (c);
注意,我們索引了c
,因為AUTO_INCREMENT
柱必須被索引,並且另外我們聲明c
為NOT
NULL
,因為索引了的列不能是NULL
。
當你增加一個AUTO_INCREMENT
列時,自動地用順序數字填入列值。
OPTIMIZE
TABLE
句法OPTIMIZE TABLE tbl_name
如果你刪除了一個表的大部分或如果你用變長的行對一個表(有VARCHAR
、BLOB
或TEXT
列的表)做了改變,應該使用OPTIMZE
TABLE
。刪除的記錄以一個鏈接表維持並且隨後的INSERT
操作再次使用老記錄的位置。你可以使用OPTIMIZE
TABLE
回收閑置的空間。
OPTIMIZE TABLE
通過制作原來的表的一個臨時副本來工作。老的表子被拷貝到新表中(沒有閑置的行),然後原來的表被刪除並且重命名一個新的。這樣做使得所有更新自動轉向新的表,沒有任何失敗的更新。當時OPTIMIZE
TABLE
正在執行時,原來的表可被另外的客戶讀取。對表的更新和寫入延遲到新表是準備好為止。
DROP TABLE
句法DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...]
DROP TABLE
刪除一個或多個資料庫表。所有表中的數據和表定義均被刪除,故小心使用這個命令!
在MySQL 3.22或以後版本,你可以使用關鍵詞IF EXISTS
類避免不存在表的一個錯誤發生。
DELETE
句法DELETE [LOW_PRIORITY] FROM tbl_name [WHERE where_definition] [LIMIT rows]
DELETE
從tbl_name
表中刪除滿足由where_definition
給出的條件的行,並且返回刪除記錄的個數。
如果你發出一個沒有WHERE
子句的DELETE
,所有行都被刪除。MySQL通過創建一個空表來完成,它比刪除每行要快。在這種情況下,DELETE
返回零作為受影響記錄的數目。(MySQL不能返回實際上被刪除的行數,因為進行再創建而不是打開數據文件。只要表定義文件“tbl_name.frm”是有效的,表才能這樣被再創建,即使數據或索引文件破壞了)。
如果你確實想要知道在你正在刪除所有行時究竟有對少記錄被刪除,並且願意承受速度上的懲罰,你可以這種形式的一個ELETE
語句:
mysql> DELETE FROM tbl_name WHERE 1>0;
注意這比沒有WHERE
子句的DELETE FROM tbl_name
慢的多了,因為它一次刪除一行。
如果你指定關鍵詞LOW_PRIORITY
,DELETE
的執行被推遲到沒有其他客戶讀取表後。
刪除的記錄以一個鏈接表維持並且隨後的INSERT
操作再次使用老的記錄位置。為了回收閑置的空間並減小文件大小,使用OPTIMIZE
TABLE
語句或myisamchk
實用程式重新組織表。OPTIMIZE
TABLE
較容易,但是myisamchk
更快。見7.9 OPTIMIZE TABLE
句法和13.4.3 表最佳化。
MySQL對DELETE
特定的LIMIT rows
選項告訴伺服器在控制被返回到客戶之前,將要刪除的最大行數,這可以用來保証一個特定DELETE
命令不會花太多的時間。你可以簡單地重複DELETE
命令直到受影響的行數小於LIMIT
值。
SELECT
句法SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [HIGH_PRIORITY] [DISTINCT | DISTINCTROW | ALL] select_expression,... [INTO {OUTFILE | DUMPFILE} 'file_name' export_options] [FROM table_references [WHERE where_definition] [GROUP BY col_name,...] [HAVING where_definition] [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] ,...] [LIMIT [offset,] rows] [PROCEDURE procedure_name] ]
SELECT
被用來檢索從一個或多個表中選取的行。select_expression
指出你想要檢索的列。SELECT
也可以用來檢索不引用任何表的計算行。例如:
mysql> SELECT 1 + 1; -> 2
所有使用的關鍵詞必須精確地以上面的順序給出。例如,一個HAVING
子句必須跟在GROUP
BY
子句之後和ORDER BY
子句之前。
SELECT
表達式可以用一個AS
給定一個別名,別名被用作表達式的列名並且能使用在ORDER
BY
或HAVING
子句中。例如: mysql> select concat(last_name,', ',first_name) AS full_name from mytable ORDER BY full_name;
FROM table_references
子句指出從哪個表中檢索行。如果你命名多個表,你正在執行一個聯結(join)。對於聯結的句法資訊,見7.13 JOIN
句法。 col_name
、tbl_name.col_name
或db_name.tbl_name.col_name
,你不必在一個SELECT
語句中指定一個tbl_name
或db_name.tbl_name
是一個列引用的前綴,除非引用有二義性。見7.1.5
資料庫、表、索引、列和別名命名。對於二義性的例子要求更加顯式的列引用格式。
tbl_name [AS]
alias_name
起一個別名。 mysql> select t1.name, t2.salary from employee AS t1, info AS t2 where t1.name = t2.name; mysql> select t1.name, t2.salary from employee t1, info t2 where t1.name = t2.name;
ORDER BY
和GROUP
BY
子句引用,列位置從1開始。 mysql> select college, region, seed from tournament ORDER BY region, seed; mysql> select college, region AS r, seed AS s from tournament ORDER BY r, s; mysql> select college, region, seed from tournament ORDER BY 2, 3;
為了以降序排列,把DESC
(下降 )關鍵詞加到ORDER BY
子句中你要排序的列名前。內定是升序﹔這也可以用ASC
關鍵詞明確指定。
HAVING
子句能引用任何列或在select_expression
中命名的別名,它最後運用,就在項目被送到客戶之前,沒有最佳化。不要對因該在WHERE
子句中的項目使用HAVING
。例如,不能寫成這樣:
mysql> select col_name from tbl_name HAVING col_name > 0;
相反寫成這樣:
mysql> select col_name from tbl_name WHERE col_name > 0;
在MySQL 3.22.5或以後,你也能這樣寫查詢:
mysql> select user,max(salary) from users group by user HAVING max(salary)>10;
在裡面更老的MySQL版本中,你能這樣寫:
mysql> select user,max(salary) AS sum from users group by user HAVING sum>10;
SQL_SMALL_RESULT
、SQL_BIG_RESULT
、STRAIGHT_JOIN
和HIGH_PRIORITY
是MySQL對ANSI
SQL92的擴展。 STRAIGHT_JOIN
強制最佳化器以其列在FROM
子句的次序聯結(join)桌子。如果最佳化器以非最佳次序聯結表,你能使用它加速查詢。見7.22 EXPLAIN
句法(得到關於SELECT
的資訊)。
SQL_SMALL_RESULT
能與GROUP BY
或DISTINCT
一起使用告訴最佳化器結果集將很小。在這種情況下,MySQL將使用快速臨時表儲存最終的表而不是使用排序。
SQL_SMALL_RESULT
是一個MySQL擴展。 SQL_BIG_RESULT
能與GROUP BY
或DISTINCT
一起使用以告訴最佳化器結果集合將有很多行。在這種情況下,如果需要,MySQL將直接使用基於磁碟的臨時表。
MySQL
在這種情況下將選擇用GROUP BY
單元上的鍵值進行排序而不是做一個臨時表。
HIGH_PRIORITY
將賦予SELECT
比一個更新表的語句更高的優先級,你應該僅對非常快的並且必須一次完成的查詢使用它。
如果表為讀而鎖定或甚至有一個等待表釋放的更新語句,一個SELECT
HIGH_PRIORITY
將運行。 LIMIT
子句可以被用來限制SELECT
語句返回的行數。LIMIT
取1個或2個數字參數,如果給定2個參數,第一個指定要返回的第一行的偏移量,第二個指定返回行的最大數目。初始行的偏移量是0(不是1)。
mysql> select * from table LIMIT 5,10; # Retrieve rows 6-15
如果給定一個參數,它指出返回行的最大數目。
mysql> select * from table LIMIT 5; # Retrieve first 5 rows
換句話說,LIMIT n
等價於LIMIT 0,n
。
SELECT ... INTO OUTFILE 'file_name'
格式的SELECT
語句將選擇的行寫入一個文件。文件在伺服器主機上被創建,並且不能是已經存在的(不管別的,這可阻止資料庫表和文件例如“/etc/passwd”被破壞)。在伺服器主機上你必須有file權限以使用這種SELECT
。SELECT
... INTO OUTFILE
是LOAD DATA INFILE
逆操作﹔語句的export_options
部分的語法與用在LOAD
DATA INFILE
語句中的FIELDS
和LINES
子句的相同。見7.16 LOAD DATA INFILE
句法。在最終的文本文件中,只有下列字符由ESCAPED
BY
字符轉義: ESCAPED BY
字符FIELDS TERMINATED BY
中的第一個字符LINES TERMINATED BY
中的第一個字符另外,ASCII 0
被變換到ESCAPED BY
後跟0(ASCII 48
)。上述的原因是你必須轉義任何FIELDS
TERMINATED BY
、ESCAPED BY
或LINES TERMINATED BY
字符以便能可靠地能讀回文件。ASCII
0
被轉義使它更容易用分頁器觀看。因為最終的文件不必須遵循SQL句法,沒有別的東西需要轉義。
如果你使用INTO DUMPFILE
而不是INTO
OUTFILE
,MySQL將只寫一行到文件中,沒有任何列或行結束並且沒有任何轉義。如果你想要在一個文件儲存一個blob,這是很有用的。
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兼容而存在的。
tbl_name AS alias_name
或tbl_name
alias_name
的起的別名。 mysql> select t1.name, t2.salary from employee AS t1, info AS t2 where t1.name = t2.name;
INNER JOIN
和,
(逗號)在語義上是等價的,都是進行一個在使用的表之間的全聯結。通常,你指定表應該如何用WHERE
條件聯結起來。
ON
條件是可以用在一個WHERE
子句形式的任何條件。
LEFT JOIN
中沒有右表的匹配記錄,一個所有列設置為NULL
的行被用於右表。你可以使用這個事實指出表中在另一個表中沒有對應記錄的記錄:
mysql> select table1.* from table1 LEFT JOIN table2 ON table1.id=table2.id where table2.id is NULL;
這個例子找出在table1
中所有的行,其id
值在table2
中不存在(即,所有table1
中的在table2
中沒有對應行的行)。當然這假定table2.id
被聲明為NOT
NULL
。
USING
(column_list)
子句命名一系列必須存在於兩個表中的列。
例如一個USING
子句: A LEFT JOIN B USING (C1,C2,C3,...)
被定義成在語義上等同一個這樣的ON
表達式:
A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
NATURAL LEFT JOIN
被定義為在語義上等同於一個有USING
子句命名在兩表中存在的所有列的一個LEFT
JOIN
。 STRAIGHT_JOIN
等同於JOIN
,除了左表在右表之前被讀入,這能用於這些情況,聯結最佳化器將表的順序放錯了。
一些例子:
mysql> select * from table1,table2 where table1.id=table2.id; mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id; mysql> select * from table1 LEFT JOIN table2 USING (id); mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id;
INSERT
句法INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] VALUES (expression,...),(...),... 或 INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] SELECT ... 或 INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name SET col_name=expression, col_name=expression, ...
INSERT
把新行插入到一個存在的表中,INSERT ... VALUES
形式的語句基於明確指定的值插入行,INSERT
... SELECT
形式插入從其他表選擇的行,有多個值表的INSERT ...
VALUES
的形式在MySQL 3.22.5或以後版本中支援,col_name=expression
語法在MySQL
3.22.10或以後版本中支援。
tbl_name
是行應該被插入其中的表。列名表或SET
子句指出語句為那一列指定值。
INSERT ... VALUES
或INSERT ... SELECT
不指定列表,所有列的值必須在VALUES()
表或由SELECT
提供。如果你不知道表中列的順序,使用DESCRIBE
tbl_name
來找出。 CREATE TABLE
句法中描述。
expression
可以引用在一個值表先前設置的任何列。例如,你能這樣:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
但不能這樣:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
LOW_PRIORITY
,INSERT
的執行被推遲到沒有其他客戶正在讀取表。在這種情況下,客戶必須等到插入語句完成後,如果表頻繁使用,它可能花很長時間。這與INSERT
DELAYED
讓客馬上繼續正好相反。 INSERT
中指定關鍵詞IGNORE
,表刈酚何複製一個現有PRIMARY
或UNIQUE
鍵的行被忽略並且不被插入。如果你不指定IGNORE
,插入如果有任何複製現有關鍵值的行被放棄。你可用C
API函數mysql_info()
檢查多少行被插入到表中。 DONT_USE_DEFAULT_FIELDS
選項配置,INSERT
語句產生一個錯誤,除非你明確對需要一個非NULL
值的所有列指定值。見4.7.3 典型configure
選項。
INSERT INTO ... SELECT
語句滿足下列條件: ORDER BY
子句。 INSERT
語句的目的表不能出現在SELECT
查詢部分的FROM
子句,因為這在ANSI
SQL中被禁止讓從你正在插入的表中SELECT
。(問題是SELECT
將可能發現在同一個運行期間內先前被插入的記錄。當使用子選擇子句時,情況能很容易混淆)AUTO_INCREMENT
列像往常一樣工作。 如果你使用INSERT ... SELECT
或INSERT ...
VALUES
語句有多個值列表,你可以使用C API函數mysql_info()
得到查詢的資訊。資訊字符串的格式如下:
Records: 100 Duplicates: 0 Warnings: 0
Duplicates
指出不能被插入的行的數量,因為他們與現有的唯一的索引值重複。Warnings
指出在出現某些問題時嘗試插入列值的次數。在下列任何條件下都可能發生錯誤:
NULL
到被聲明了NOT NULL
的列,列被設置為它的內定值。
'10.34 a'
的值,拖尾的垃圾被剝去並仍然是數字部分被插入。如果值根本不是一個數字,列被設置到0
。
CHAR
、VARCHAR
、TEXT
或BLOB
列中。值被截斷為列的最大長度。
對於INSERT
語句的DELAYED
選項是MySQL專屬的選項-如果你客戶有不能等到INSERT
完成,它是很有用的。當你為日記登錄使用MySQL時,而且你也周期性地運行花很長時間完成的SELECT
語句,這是一個常見的問題。DELAYED
在面MySQL
3.22.15中被引入,它是MySQL對 ANSI SQL92 的一個擴展。
當你使用INSERT DELAYED
時,客戶將馬上準備好,並且當表不被任何其他的執行緒使用時,行將被插入。
另一個使用INSERT DELAYED
的主要好處是從很多客戶插入被捆綁在一起並且寫進一個塊。這比做很多單獨的插入要來的快。
注意,當前排隊的行只是儲存在內存中,直到他們被插入到表中。這意味著,如果你硬要殺死mysqld
(kill
-9
)或如果mysqld
出人意料地死掉,沒被寫進磁碟的任何排隊的行被丟失!
下列詳細描述當你為INSERT
或REPLACE
使用DELAYED
選項時,發生什麼。在這個描述中,“執行緒”是收到一個INSERT
DELAYED
命令的執行緒並且“處理器”是處理所有對於一個特定表的INSERT
DELAYED
語句。
DELAYED
語句時,如果不存在這樣的處理程式,一個處理器執行緒被創建以處理對於該表的所有DELAYED
語句。
DELAYED
鎖﹔如果沒有,它告訴處理程式去獲得。即使其他的執行緒有在表上的一個READ
或WRITE
鎖,也能獲得DELAYED
鎖。然而,處理程式將等待所有ALTER
TABLE
鎖或FLUSH TABLES
以保証表結構是最新的。 INSERT
語句,但不是將行寫入表,它把最後一行的副本放進被處理器執行緒管理的一個隊列。任何語法錯誤都能被執行緒發覺並報告給客戶程式。
AUTO_INCREMENT
值﹔它不能從伺服器獲得它們,因為INSERT
在插入操作完成前返回。如果你使用C
API,同樣原因,mysql_info()
函數不返回任何有意義的東西。 delayed_insert_limit
行後,處理器檢查是否任何SELECT
語句仍然是未完成,如果這樣,在繼續之前允許執行這些語句。
delayed_insert_timeout
秒內沒有收到新的INSERT
DELAYED
命令,處理器終止。 delayed_queue_size
行在一個特定的處理器隊列刈袧解決,執行緒等待直到隊列有空間。這有助於保証mysqld
伺服器對延遲的內存隊列不使用所有內存。
Command
列的MySQL進程表中顯示delayed_insert
。如果你執行一個FLUSH
TABLES
命令或以KILL thread_id
殺死它,它將被殺死,然而,它在退出前首先將所有排隊的行存進表中。在這期間,這次它將不從其他執行緒接受任何新的INSERT
命令。如果你在它之後執行一個INSERT
DELAYED
,將創建一個新的處理器執行緒。 INSERT DELAYED
處理器已經運行,INSERT
DELAYED
命令有比正常INSERT
更高的優先級!其他更新命令將必須等到INSERT
DELAY
排隊變空、殺死處理器執行緒(用KILL thread_id
)或執行FLUSH
TABLES
。 INSERT DELAYED
命令的資訊: Delayed_insert_threads |
處理器執行緒數量 |
Delayed_writes |
用INSERT DELAYED 被寫入的行的數量 |
Not_flushed_delayed_rows |
等待被寫入的行數字 |
你能通過發出一個SHOW STATUS
語句或通過執行一個mysqladmin
extended-status
命令察看這些變數。
注意如果桌子不在使用,INSERT DELAYED
比一個正常的INSERT
慢。對伺服器也有額外開銷來處理你對它使用INSERT
DELAYED
的每個表的一個單獨執行緒。這意味著,你應該只在你確實肯定需要它的時候才使用INSERT
DELAYED
!
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
句法。
LOAD DATA INFILE
句法LOAD DATA [LOW_PRIORITY] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE tbl_name [FIELDS [TERMINATED BY '\t'] [OPTIONALLY] ENCLOSED BY ''] [ESCAPED BY '\\' ]] [LINES TERMINATED BY '\n'] [IGNORE number LINES] [(col_name,...)]
LOAD DATA INFILE
語句從一個文本文件刈脛很高的速度讀入一個表中。如果指定LOCAL
關鍵詞,從客戶主機讀文件。如果LOCAL
沒指定,文件必須位於伺服器上。(LOCAL
在MySQL3.22.6或以後版本刈莃用。)
為了安全原因,當讀取位於伺服器上的文本文件時,文件必須處於資料庫目錄或可被所有人讀取。另外,為了對伺服器上文件使用LOAD
DATA INFILE
,在伺服器主機上你必須有file的權限。見6.5 由MySQL提供的權限。
如果你指定關鍵詞LOW_PRIORITY
,LOAD DATA
語句的執行被推遲到沒有其他客戶讀取表後。
使用LOCAL
將比讓伺服器直接存取文件慢些,因為文件的內容必須從客戶主機傳送到伺服器主機。在另一方面,你不需要file權限裝載本地文件。
你也可以使用mysqlimport
實用程式裝載數據文件﹔它由發送一個LOAD
DATA INFILE
命令到伺服器來運作。 --local
選項使得mysqlimport
從客戶主機上讀取數據。如果客戶和伺服器支援壓縮協議,你能指定--compress
在較慢的網路上獲得更好的性能。
當在伺服器主機上尋找文件時,伺服器使用下列規則:
注意這些規則意味著一個像“./myfile.txt”給出的文件是從伺服器的數據目錄讀取,而作為“myfile.txt”給出的一個文件是從當前資料庫的資料庫目錄下讀取。也要注意,對於下列哪些語句,對db1
文件從資料庫目錄讀取,而不是db2
:
mysql> USE db1; mysql> LOAD DATA INFILE "./data.txt" INTO TABLE db2.my_table;
REPLACE
和IGNORE
關鍵詞控制對現有的唯一鍵記錄的重複的處理。如果你指定REPLACE
,新行將代替有相同的唯一鍵值的現有行。如果你指定IGNORE
,跳過有唯一鍵的現有行的重複行的輸入。如果你不指定任何一個選項,當找到重複鍵鍵時,出現一個錯誤,並且文本文件的餘下部分被忽略時。
如果你使用LOCAL
關鍵詞從一個本地文件裝載數據,伺服器沒有辦法在操作的當中停止文件的傳輸,因此內定的行為好像IGNORE
被指定一樣。
LOAD DATA INFILE
是SELECT ... INTO OUTFILE
的逆操作,見7.12 SELECT
句法。為了將一個資料庫的數據寫入一個文件,使用SELECT
... INTO OUTFILE
,為了將文件讀回資料庫,使用LOAD DATA INFILE
。兩個命令的FIELDS
和LINES
子句的語法是相同的。兩個子句是可選的,但是如果指定兩個,FIELDS
必須在LINES
之前。
如果你指定一個FIELDS
子句,它的每一個子句(TERMINATED
BY
, [OPTIONALLY] ENCLOSED BY
和ESCAPED BY
)也是可選的,除了你必須至少指定他們之一。
如果你不指定一個FIELDS
子句,內定值與如果你這樣寫的相同:
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
如果你不指定一個LINES
子句,內定值與如果你這樣寫的相同:
LINES TERMINATED BY '\n'
換句話說,內定值導致讀取輸入時,LOAD DATA INFILE
表現如下:
相反,內定值導致在寫入輸出時,SELECT ... INTO OUTFILE
表現如下:
注意,為了寫入FIELDS ESCAPED BY '\\'
,對作為一條單個的反斜線被讀取的值,你必須指定2條反斜線值。
IGNORE number LINES
選項可被用來忽略在文件開始的一個列名字的頭:
mysql> LOAD DATA INFILE "/tmp/file_name" into table test IGNORE 1 LINES;
當你與LOAD DATA INFILE
一起使用SELECT ... INTO OUTFILE
將一個資料庫的數據寫進一個文件並且隨後馬上將文件讀回資料庫時,兩個命令的字段和處理選項必須匹配,否則,LOAD
DATA INFILE
將不能正確解釋文件的內容。假定你使用SELECT ...
INTO OUTFILE
將由逗號分隔的字段寫入一個文件:
mysql> SELECT * FROM table1 INTO OUTFILE 'data.txt' FIELDS TERMINATED BY ',' FROM ...
為了將由逗號分隔的文件讀回來,正確的語句將是:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY ',';
相反,如果你試圖用下面顯示的語句讀取文件,它不會工作,因為它命令LOAD
DATA INFILE
在字段之間尋找定位符:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY '\t';
可能的結果是每個輸入行將被解釋為單個的字段。
LOAD DATA INFILE
能被用來讀取從外部來源獲得的文件。例如,以dBASE格式的文件將有由逗號分隔並用雙引號包圍的字段。如果文件中的行由換行符終止,下面顯示的命令說明你將用來裝載文件的字段和行處理選項:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';
任何字段或行處理選項可以指定一個空字符串(''
)。如果不是空,FIELDS
[OPTIONALLY] ENCLOSED BY
和FIELDS ESCAPED BY
值必須是一個單個字符。FIELDS
TERMINATED BY
和LINES TERMINATED BY
值可以是超過一個字符。例如,寫入由回車換行符對(CR+LF)終止的行,或讀取包含這樣行的一個文件,指定一個LINES
TERMINATED BY '\r\n'
子句。
FIELDS [OPTIONALLY] ENCLOSED BY
控制字段的包圍字符。對於輸出(SELECT
... INTO OUTFILE
),如果你省略OPTIONALLY
,所有的字段由ENCLOSED
BY
字符包圍。對於這樣的輸出的一個例子(使用一個逗號作為字段分隔符)顯示在下面:
"1","a string","100.20" "2","a string containing a , comma","102.20" "3","a string containing a \" quote","102.20" "4","a string containing a \", quote and comma","102.20"
如果你指定OPTIONALLY
,ENCLOSED BY
字符僅被用於包圍CHAR
和VARCHAR
字段:
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a \" quote",102.20 4,"a string containing a \", quote and comma",102.20
注意,一個字段值中的ENCLOSED BY
字符的出現通過用ESCAPED
BY
字符作為其前綴來轉義。也要注意,如果你指定一個空ESCAPED
BY
值,可能產生不能被LOAD DATA INFILE
正確讀出的輸出。例如,如果轉義字符為空,上面顯示的輸出顯示如下。注意到在第四行的第二個字段包含跟隨引號的一個逗號,它(錯誤地)好像要終止字段:
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a " quote",102.20 4,"a string containing a ", quote and comma",102.20
對於輸入,ENCLOSED BY
字符如果存在,它從字段值的尾部被剝去。(不管是否指定OPTIONALLY
都是這樣﹔OPTIONALLY
對於輸入解釋不起作用)由ENCLOSED
BY
字符領先的ESCAPED BY
字符出現被解釋為當前字段值的一部分。另外,出現在字段中重複的ENCLOSED
BY
被解釋為單個ENCLOSED BY
字符,如果字段本身以該字符開始。例如,如果ENCLOSED
BY '"'
被指定,引號如下處理:
"The ""BIG"" boss" -> The "BIG" boss The "BIG" boss -> The "BIG" boss The ""BIG"" boss -> The ""BIG"" boss
FIELDS ESCAPED BY
控制如何寫入或讀出特殊字符。如果FIELDS
ESCAPED BY
字符不是空的,它被用於前綴在輸出上的下列字符:
FIELDS ESCAPED BY
字符FIELDS [OPTIONALLY] ENCLOSED BY
字符FIELDS TERMINATED BY
和LINES TERMINATED BY
值的第一個字符 0
(實際上將後續轉義字符寫成 ASCII'0'
,而不是一個零值字節)如果FIELDS ESCAPED BY
字符是空的,沒有字符被轉義。指定一個空轉義字符可能不是一個好主意,特別是如果在你數據中的字段值包含剛才給出的表中的任何字符。
對於輸入,如果FIELDS ESCAPED BY
字符不是空的,該字符的出現被剝去並且後續字符在字面上作為字段值的一個部分。例外是一個轉義的“0”或“N”(即,\0
或\N
,如果轉義字符是“\”)。這些序列被解釋為ASCII
0
(一個零值字節)和NULL
。見下面關於NULL
處理的規則。
對於更多關於“\”- 轉義句法的資訊,見7.1 文字:怎樣寫字符串和數字。
在某些情況下,字段和行處理選項相互作用:
LINES TERMINATED BY
是一個空字符串並且FIELDS TERMINATED
BY
是非空的,行也用FIELDS TERMINATED BY
終止。 FIELDS TERMINATED BY
和FIELDS ENCLOSED BY
值都是空的(''
),一個固定行(非限定的)格式被使用。用固定行格式,在字段之間不使用分隔符。相反,列值只用列的“顯示”寬度被寫入和讀出。例如,如果列被聲明為INT(7)
,列的值使用7個字符的字段被寫入。對於輸入,列值通過讀取7個字符獲得。固定行格式也影響NULL
值的處理﹔見下面。注意如果你正在使用一個多字節字符集,固定長度格式將不工作。
NULL
值的處理有多種,取決於你使用的FIELDS
和LINES
選項:
FIELDS
和LINES
值,對輸出,NULL
被寫成\N
,對輸入,\N
被作為NULL
讀入(假定ESCAPED
BY
字符是“\”)。 FIELDS ENCLOSED BY
不是空的,包含以文字詞的NULL
作為它的值的字段作為一個NULL
值被讀入(這不同於包圍在FIELDS
ENCLOSED BY
字符中的字NULL
,它作為字符串'NULL'
讀入)。
FIELDS ESCAPED BY
是空的,NULL
作為字NULL
被寫入。
FIELDS TERMINATED BY
和FIELDS ENCLOSED
BY
都是空的時候),NULL
作為一個空字符串被寫入。注意,在寫入文件時,這導致NULL
和空字符串在表中不能區分,因為他們都作為空字符串被寫入。如果在讀回文件時需要能區分這兩者,你應該不使用固定行格式。
一些不被LOAD DATA INFILE
支援的情況:
FIELDS TERMINATED BY
和FIELDS ENCLOSED BY
都為空)和BLOB
或TEXT
列。
LOAD
DATA INFILE
不能正確地解釋輸入。例如,下列FIELDS
子句將導致問題:
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
FIELDS ESCAPED BY
是空的,一個包含跟隨FIELDS
TERMINATED BY
值之後的FIELDS ENCLOSED BY
或LINES TERMINATED
BY
的字段值將使得LOAD DATA INFILE
過早地終止讀取一個字段或行。這是因為LOAD
DATA INFILE
不能正確地決定字段或行值在哪兒結束。 下列例子裝載所有persondata
表的行:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
沒有指定字段表,所以LOAD DATA INFILE
期望輸入行對每個表列包含一個字段。使用內定FIELDS
和LINES
值。
如果你希望僅僅裝載一張表的某些列,指定一個字段表:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);
如果在輸入文件中的字段順序不同於表中列的順序,你也必須指定一個字段表。否則,MySQL不能知道如何匹配輸入字段和表中的列。
如果一個行有很少的字段,對於不存在輸入字段的列被設置為內定值。內定值賦值在7.7 CREATE TABLE
句法中描述。
如果字段值內定,空字段值有不同的解釋:
0
。 如果列有一個NULL
,或(只對第一個TIMESTAMP
列)在指定一個字段表時,如果TIMESTAMP
列從字段表省掉,TIMESTAMP
列只被設置為當前的日期和時間。
如果輸入行有太多的字段,多餘的字段被忽略並且警告數字加1。
LOAD DATA INFILE
認為所有的輸入是字符串,因此你不能像你能用INSERT
語句的ENUM
或SET
列的方式使用數字值。所有的ENUM
和SET
值必須作為字符串被指定!
如果你正在使用C API,當LOAD DATA INFILE
查詢完成時,你可通過調用API函數mysql_info()
得到有關查詢的資訊。資訊字符串的格式顯示在下面:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
當值通過INSERT
語句插入時,在某些情況下出現警告(見7.14 INSERT
句法),除了在輸入行中有太少或太多的字段時,LOAD
DATA INFILE
也產生警告。警告沒被儲存在任何地方﹔警告數字僅能用於表明一切是否順利。如果你得到警告並且想要確切知道你為什麼得到他們,一個方法是使用SELECT
... INTO OUTFILE
到另外一個文件並且把它與你的原版輸入文件比較。
對於有關INSERT
相對LOAD DATA INFILE
的效率和加快LOAD
DATA INFILE
的更多資訊,見10.5.6
加速INSERT
查詢。
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 #
來保証只有一個給定數量的行被改變。
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的兼容性。
FLUSH
句法(清除緩存)FLUSH flush_option [,flush_option]
如果你想要清除一些MySQL使用內部緩存,你應該使用FLUSH
命令。為了執行FLUSH
,你必須有reload權限。
flush_option
可以是下列任何東西:
HOSTS |
清空主機緩存表。如果你的某些主機改變IP數字,或如果你得到錯誤消息Host
... is blocked ,你應該清空主機表。當在連接MySQL伺服器時,對一台給定的主機有多於max_connect_errors 個錯誤連續不斷地發生,MySQL認定某些東西錯了並且阻止主機進一步的連接請求。清空主機表允許主機再嘗試連接。見18.2.3 Host '...' is blocked 錯誤)。你可用-O
max_connection_errors=999999999 啟動mysqld 來避免這條錯誤消息。
|
LOGS |
關閉並且再打開標準和更新記錄文件。如果你指定了一個沒有擴展名的更新記錄文件,新的更新記錄文件的擴展數字將相對先前的文件加1。 |
PRIVILEGES |
從mysql 資料庫授權表中重新裝載權限。 |
TABLES |
關閉所有打開的表。 |
STATUS |
重置大多數狀態變數到0。 |
你也可以用mysqladmin
實用程式,使用flush-hosts
, flush-logs
,
reload
或flush-tables
命令來訪問上述的每一個命令。
KILL
句法KILL thread_id
每個對mysqld
的連接以一個單獨的執行緒運行。你可以用看SHOW
PROCESSLIST
命令察看哪個執行緒正在運行,並且用KILL thread_id
命令殺死一個執行緒。
如果你有process權限,你能看到並且殺死所有執行緒。否則,你只能看到並且殺死你自己的執行緒。
你也可以使用mysqladmin processlist
和mysqladmin kill
命令檢查並殺死執行緒。
SHOW
句法 (得到表,列等的資訊)SHOW DATABASES [LIKE wild] or SHOW TABLES [FROM db_name] [LIKE wild] or SHOW COLUMNS FROM tbl_name [FROM db_name] [LIKE wild] or SHOW INDEX FROM tbl_name [FROM db_name] or SHOW STATUS or SHOW VARIABLES [LIKE wild] or SHOW [FULL] PROCESSLIST or SHOW TABLE STATUS [FROM db_name] [LIKE wild] or SHOW GRANTS FOR user
SHOW
提供關於資料庫、桌子、列或伺服器的資訊。如果使用LIKE
wild
部分,wild
字符串可以是一個使用SQL的“%”和“_”通配符的字符串。
你能使用db_name.tbl_name
作為tbl_name FROM db_name
句法的另一種選擇。這兩個語句是相等的:
mysql> SHOW INDEX FROM mytable FROM mydb; mysql> SHOW INDEX FROM mydb.mytable;
SHOW DATABASES
列出在MySQL伺服器主機上的資料庫。你也可以用mysqlshow
命令得到這張表。
SHOW TABLES
列出在一個給定的資料庫中的表。你也可以用mysqlshow
db_name
命令得到這張表。
注意:如果一個用戶沒有一個表的任何權限,表將不在SHOW
TABLES
或mysqlshow db_name
中的輸出中顯示。
SHOW COLUMNS
列出在一個給定表中的列。如果列類型不同於你期望的是基於CREATE
TABLE
語句的那樣,注意,MySQL有時改變列類型。見7.7.1 隱含的列說明變化。
DESCRIBE
語句提供了類似SHOW COLUMNS
的資訊。見7.23 DESCRIBE
句法 (得到列的資訊)。
SHOW TABLE STATUS
(在版本3.23引入)運行類似SHOW STATUS
,但是提供每個表的更多資訊。你也可以使用mysqlshow
--status db_name
命令得到這張表。下面的列被返回:
列 | 含義 |
Name |
表名 |
Type |
表的類型 (ISAM,MyISAM或HEAP) |
Row_format |
行儲存格式 (固定, 動態, 或壓縮) |
Rows |
行數量 |
Avg_row_length |
平均行長度 |
Data_length |
數據文件的長度 |
Max_data_length |
數據文件的最大長度 |
Index_length |
索引文件的長度 |
Data_free |
已分配但未使用了字節數 |
Auto_increment |
下一個 autoincrement(自動加1)值 |
Create_time |
表被創造的時間 |
Update_time |
數據文件最後更新的時間 |
Check_time |
最後對表運行一個檢查的時間 |
Create_options |
與CREATE TABLE 一起使用的額外選項 |
Comment |
當創造表時,使用的注釋 (或為什麼MySQL不能存取表資訊的一些資訊)。 |
SHOW FIELDS
是SHOW COLUMNS
一個同義詞,SHOW KEYS
是SHOW
INDEX
一個同義詞。你也可以用mysqlshow db_name tbl_name
或mysqlshow
-k db_name tbl_name
列出一張表的列或索引。
SHOW INDEX
以非常相似於ODBC的SQLStatistics
調用的格式返回索引資訊。下面的列被返回:
列 | 含義 |
Table |
表名 |
Non_unique |
0,如果索引不能包含重複。 |
Key_name |
索引名 |
Seq_in_index |
索引中的列順序號, 從 1 開始。 |
Column_name |
列名。 |
Collation |
列怎樣在索引中被排序。在MySQL中,這可以有值A (升序)
或NULL (不排序)。 |
Cardinality |
索引中唯一值的數量。這可通過運行isamchk -a 更改. |
Sub_part |
如果列只是部分被索引,索引字符的數量。NULL ,如果整個鍵被索引。
|
SHOW STATUS
提供伺服器的狀態資訊(像mysqladmin
extended-status
一樣)。輸出類似於下面的顯示,盡管格式和數字可以有點不同:
+--------------------------+--------+ | Variable_name | Value | +--------------------------+--------+ | Aborted_clients | 0 | | Aborted_connects | 0 | | Connections | 17 | | Created_tmp_tables | 0 | | Delayed_insert_threads | 0 | | Delayed_writes | 0 | | Delayed_errors | 0 | | Flush_commands | 2 | | Handler_delete | 2 | | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_next | 0 | | Handler_read_rnd | 35 | | Handler_update | 0 | | Handler_write | 2 | | Key_blocks_used | 0 | | Key_read_requests | 0 | | Key_reads | 0 | | Key_write_requests | 0 | | Key_writes | 0 | | Max_used_connections | 1 | | Not_flushed_key_blocks | 0 | | Not_flushed_delayed_rows | 0 | | Open_tables | 1 | | Open_files | 2 | | Open_streams | 0 | | Opened_tables | 11 | | Questions | 14 | | Slow_queries | 0 | | Threads_connected | 1 | | Threads_running | 1 | | Uptime | 149111 | +--------------------------+--------+
上面列出的狀態變數有下列含義:
Aborted_clients |
由於客戶沒有正確關閉連接已經死掉,已經放棄的連接數量。 |
Aborted_connects |
嘗試已經失敗的MySQL伺服器的連接的次數。 |
Connections |
試圖連接MySQL伺服器的次數。 |
Created_tmp_tables |
當執行語句時,已經被創造了的隱含臨時表的數量。 |
Delayed_insert_threads |
正在使用的延遲插入處理器執行緒的數量。 |
Delayed_writes |
用INSERT DELAYED 寫入的行數。 |
Delayed_errors |
用INSERT DELAYED 寫入的發生某些錯誤(可能重複鍵值 )的行數。
|
Flush_commands |
執行FLUSH 命令的次數。 |
Handler_delete |
請求從一張表中刪除行的次數。 |
Handler_read_first |
請求讀入表中第一行的次數。 |
Handler_read_key |
請求數字基於鍵讀行。 |
Handler_read_next |
請求讀入基於一個鍵的一行的次數。 |
Handler_read_rnd |
請求讀入基於一個固定位置的一行的次數。 |
Handler_update |
請求更新表中一行的次數。 |
Handler_write |
請求向表中插入一行的次數。 |
Key_blocks_used |
用於關鍵字緩存的塊的數量。 |
Key_read_requests |
請求從緩存讀入一個鍵值的次數。 |
Key_reads |
從磁碟物理讀入一個鍵值的次數。 |
Key_write_requests |
請求將一個關鍵字塊寫入緩存次數。 |
Key_writes |
將一個鍵值塊物理寫入磁碟的次數。 |
Max_used_connections |
同時使用的連接的最大數目。 |
Not_flushed_key_blocks |
在鍵緩存中已經改變但是還沒被清空到磁碟上的鍵塊。 |
Not_flushed_delayed_rows |
在INSERT DELAY 隊列中等待寫入的行的數量。 |
Open_tables |
打開表的數量。 |
Open_files |
打開文件的數量。 |
Open_streams |
打開流的數量(主要用於日誌記載) |
Opened_tables |
已經打開的表的數量。 |
Questions |
發往伺服器的查詢的數量。 |
Slow_queries |
要花超過long_query_time 時間的查詢數量。 |
Threads_connected |
當前打開的連接的數量。 |
Threads_running |
不在睡眠的執行緒數量。 |
Uptime |
伺服器工作了多少秒。 |
關於上面的一些注釋:
Opened_tables
太大,那麼你的table_cache
變數可能太小。
key_reads
太大,那麼你的key_cache
可能太小。緩存命中率可以用key_reads
/key_read_requests
計算。
Handler_read_rnd
太大,那麼你很可能有大量的查詢需要MySQL掃描整個表或你有沒正確使用鍵值的聯結(join)。
SHOW VARIABLES
顯示出一些MySQL系統變數的值,你也能使用mysqladmin
variables
命令得到這個資訊。如果內定值不合適,你能在mysqld
啟動時使用命令行選項來設置這些變數的大多數。輸出類似於下面的顯示,盡管格式和數字可以有點不同:
+------------------------+--------------------------+ | Variable_name | Value | +------------------------+--------------------------+ | back_log | 5 | | connect_timeout | 5 | | basedir | /my/monty/ | | datadir | /my/monty/data/ | | delayed_insert_limit | 100 | | delayed_insert_timeout | 300 | | delayed_queue_size | 1000 | | join_buffer_size | 131072 | | flush_time | 0 | | interactive_timeout | 28800 | | key_buffer_size | 1048540 | | language | /my/monty/share/english/ | | log | OFF | | log_update | OFF | | long_query_time | 10 | | low_priority_updates | OFF | | max_allowed_packet | 1048576 | | max_connections | 100 | | max_connect_errors | 10 | | max_delayed_threads | 20 | | max_heap_table_size | 16777216 | | max_join_size | 4294967295 | | max_sort_length | 1024 | | max_tmp_tables | 32 | | net_buffer_length | 16384 | | port | 3306 | | protocol-version | 10 | | record_buffer | 131072 | | skip_locking | ON | | socket | /tmp/mysql.sock | | sort_buffer | 2097116 | | table_cache | 64 | | thread_stack | 131072 | | tmp_table_size | 1048576 | | tmpdir | /machine/tmp/ | | version | 3.23.0-alpha-debug | | wait_timeout | 28800 | +------------------------+--------------------------+
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 | +---------------------------------------------------------------------+
EXPLAIN
句法(得到關於SELECT
的資訊)EXPLAIN tbl_name or EXPLAIN SELECT select_options
EXPLAIN tbl_name
是DESCRIBE tbl_name
或SHOW COLUMNS
FROM tbl_name
的一個同義詞。
當你在一條SELECT
語句前放上關鍵詞EXPLAIN
,MySQL解釋它將如何處理SELECT
,提供有關表如何聯結和以什麼次序聯結的資訊。
借助於EXPLAIN
,你可以知道你什麼時候必須為表加入索引以得到一個使用索引找到記錄的更快的SELECT
。你也能知道最佳化器是否以一個最佳次序聯結表。為了強制最佳化器對一個SELECT
語句使用一個特定聯結次序,增加一個STRAIGHT_JOIN
子句。
對於非簡單的聯結,EXPLAIN
為用於SELECT
語句中的每個表返回一行資訊。表以他們將被讀入的順序被列出。MySQL用一邊掃描多次聯結的方式解決所有聯結,這意味著MySQL從第一個表中讀一行,然後找到在第二個表中的一個匹配行,然後在第3個表中等等。當所有的表被處理完,它輸出選擇的列並且回溯表列表直到找到一個表有更多的匹配行,從該表讀入下一行並繼續處理下一個表。
從EXPLAIN
的輸出包括下面列:
table
type
possible_keys
possible_keys
列指出MySQL能使用哪個索引在該表中找到行。注意,該列完全獨立於表的次序。這意味著在possible_keys中的某些鍵實際上不能以產生的表次序使用。如果該列是空的,沒有相關的索引。在這種情況下,你也許能通過檢驗WHERE
子句看是否它引用某些列或列不是適合索引來提高你的查詢性能。如果是這樣,創造一個適當的索引並且在用EXPLAIN
檢查查詢。見7.8 ALTER TABLE
句法。為了看清一張表有什麼索引,使用SHOW
INDEX FROM tbl_name
。 key
key
列顯示MySQL實際決定使用的鍵。如果沒有索引被選擇,鍵是NULL
。
key_len
key_len
列顯示MySQL決定使用的鍵長度。如果鍵是NULL
,長度是NULL
。注意這告訴我們MySQL將實際使用一個多部鍵值的幾個部分。
ref
ref
列顯示哪個列或常數與key
一起用於從表中選擇行。
rows
rows
列顯示MySQL相信它必須檢驗以執行查詢的行數。
Extra
Extra
列包括文字Only index
,這意味著資訊只用索引樹中的資訊檢索出的。通常,這比掃描整個表要快。如果Extra
列包括文字where
used
,它意味著一個WHERE
子句將被用來限制哪些行與下一個表匹配或發向客戶。
不同的聯結類型列在下面,以最好到最差類型的次序:
system
const
聯結類型的一個特例。 const
const
表很快,因為它們只讀取一次! eq_ref
const
類型。它用在一個索引的所有部分被聯結使用並且索引是UNIQUE
或PRIMARY
KEY
。 ref
UNIQUE
或PRIMARY
KEY
(換句話說,如果聯結不能基於鍵值選擇單個行的話),使用ref
。如果被使用的鍵僅僅匹配一些行,該聯結類型是不錯的。
range
ref
列顯示哪個索引被使用。
index
ALL
相同,除了只有索引樹被掃描。這通常比ALL
快,因為索引文件通常比數據文件小。
ALL
const
的表,這通常不好,並且通常在所有的其他情況下很差。你通常可以通過增加更多的索引來避免ALL
,使得行能從早先的表中基於常數值或列值被檢索出。
通過相乘EXPLAIN
輸出的rows
行的所有值,你能得到一個關於一個聯結要多好的提示。這應該粗略地告訴你MySQL必須檢驗多少行以執行查詢。當你使用max_join_size
變數限制查詢時,也用這個數字。見10.2.3 調節伺服器參數。
下列例子顯示出一個JOIN
如何能使用EXPLAIN
提供的資訊逐步被最佳化。
假定你有顯示在下面的SELECT
語句,你使用EXPLAIN
檢驗:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC = et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
對於這個例子,假定:
表 | 列 | 列類型 |
tt |
ActualPC |
CHAR(10) |
tt |
AssignedPC |
CHAR(10) |
tt |
ClientID |
CHAR(10) |
et |
EMPLOYID |
CHAR(15) |
do |
CUSTNMBR |
CHAR(15) |
表 | 索引 |
tt |
ActualPC |
tt |
AssignedPC |
tt |
ClientID |
et |
EMPLOYID (主鍵) |
do |
CUSTNMBR (主鍵) |
tt.ActualPC
值不是均勻分布的。 開始,在任何最佳化被施行前,EXPLAIN
語句產生下列資訊:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 range checked for each record (key map: 35)
因為type
對每張表是ALL
,這個輸出顯示MySQL正在對所有表進行一個完整聯結!這將花相當長的時間,因為必須檢驗每張表的行數的乘積次數!對於一個實例,這是74
* 2135 * 74 * 3872 = 45,268,558,720
行。如果表更大,你只能想像它將花多長時間……
如果列聲明不同,這裡的一個問題是MySQL(還)不能高效地在列上使用索引。在本文中,VARCHAR
和CHAR
是相同的,除非他們聲明為不同的長度。因為tt.ActualPC
被聲明為CHAR(10)
並且et.EMPLOYID
被聲明為CHAR(15)
,有一個長度失配。
為了修正在列長度上的不同,使用ALTER TABLE
將ActualPC
的長度從10個字符變為15個字符:
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
現在tt.ActualPC
和et.EMPLOYID
都是VARCHAR(15)
,再執行EXPLAIN
語句產生這個結果:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used do ALL PRIMARY NULL NULL NULL 2135 range checked for each record (key map: 1) et_1 ALL PRIMARY NULL NULL NULL 74 range checked for each record (key map: 1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
這不是完美的,但是是好一些了(rows
值的乘積少了一個74一個因子),這個版本在幾秒內執行。
第2種改變能消除tt.AssignedPC = et_1.EMPLOYID
和tt.ClientID =
do.CUSTNMBR
比較的列的長度失配:
mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15), MODIFY ClientID VARCHAR(15);
現在EXPLAIN
產生的輸出顯示在下面:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
這“幾乎”像它能得到的一樣好。
剩下的問題是,內定地,MySQL假設在tt.ActualPC
列的值是均勻分布的,並且對tt
表不是這樣。幸好,很容易告訴MySQL關於這些:
shell> myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt shell> mysqladmin refresh
現在聯結是“完美”的了,而且EXPLAIN
產生這個結果:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
注意在從EXPLAIN
輸出的rows
列是一個來自MySQL聯結最佳化器的“教育猜測”﹔為了最佳化查詢,你應該檢查數字是否接近事實。如果不是,你可以通過在你的SELECT
語句裡面使用STRAIGHT_JOIN
並且試著在在FROM
子句以不同的次序列出表,可能得到更好的性能。
DESCRIBE
句法 (得到列的資訊){DESCRIBE | DESC} tbl_name {col_name | wild}
DESCRIBE
提供關於一張表的列的資訊。col_name
可以是一個列名字或包含SQL的“%”和“_”通配符的一個字符串。
如果列類型不同於你期望的是基於一個CREATE TABLE
語句,注意MySQL有時改變列類型。見7.7.1 隱含的列說明變化。
SHOW
語句提供類似的資訊。見7.21
SHOW
句法(得到表,列的資訊)。
LOCK TABLES/UNLOCK
TABLES
句法LOCK TABLES tbl_name [AS alias] {READ | [LOW_PRIORITY] WRITE} [, tbl_name {READ | [LOW_PRIORITY] WRITE} ...] ... UNLOCK TABLES
LOCK TABLES
為當前執行緒鎖定表。UNLOCK TABLES
釋放被當前執行緒持有的任何鎖。當執行緒發出另外一個LOCK
TABLES
時,或當伺服器的連接被關閉時,當前執行緒鎖定的所有表自動被解鎖。
如果一個執行緒獲得在一個表上的一個READ
鎖,該執行緒(和所有其他執行緒)只能從表中讀。如果一個執行緒獲得一個表上的一個WRITE
鎖,那麼只有持鎖的執行緒READ
或WRITE
表,其他執行緒被阻止。
每個執行緒等待(沒有超時)直到它獲得它請求的所有鎖。
WRITE
鎖通常比READ
鎖有更高的優先級,以確保更改盡快被處理。這意味著,如果一個執行緒獲得READ
鎖,並且然後另外一個執行緒請求一個WRITE
鎖,
隨後的READ
鎖請求將等待直到WRITE
執行緒得到了鎖並且釋放了它。當執行緒正在等待WRITE
鎖時,你可以使用LOW_PRIORITY
WRITE
允許其他執行緒獲得READ
鎖。如果你肯定終於有個時刻沒有執行緒將有一個READ
鎖,你應該只使用LOW_PRIORITY
WRITE
。
當你使用LOCK TABLES
時,你必須鎖定你將使用的所有表!如果你正在一個查詢中多次使用一張表(用別名),你必須對每個別名得到一把鎖!這條政策保証表鎖定不會死鎖。
注意你應該不鎖定任何你正在用INSERT DELAYED
使用的表,這是因為在這種情況下,INSERT
被一個不同的執行緒執行。
通常,你不必鎖定表,因為所有單個UPDATE
語句是原語﹔沒有其他執行緒能防礙任何其它正在執行SQL語句的執行緒。當你想鎖定表,有一些情況:
READ
鎖定的表並且沒有其他執行緒能讀一個WRITE
-鎖定的表。
SELECT
和一個UPDATE
之間沒有其他執行緒到來,你必須使用LOCK
TABLES
。下面顯示的例子要求LOCK TABLES
以便安全地執行:
mysql> LOCK TABLES trans READ, customer WRITE; mysql> select sum(value) from trans where customer_id= some_id; mysql> update customer set total_value=sum_from_previous_statement where customer_id=some_id; mysql> UNLOCK TABLES;
沒有LOCK TABLES
,另外一個執行緒可能有一個機會在執行SELECT
和UPDATE
語句之間往trans
表中插入一個新行。
通過使用漸增更改(UPDATE customer SET value=value+new_value
)或LAST_INSERT_ID()
函數,在很多情況下你能使用LOCK
TABLES
來避免。
你也可以使用用戶級鎖定函數GET_LOCK()
和RELEASE_LOCK()
解決一些情況,這些鎖保存在伺服器的一張哈希表中並且用pthread_mutex_lock()
和pthread_mutex_unlock()
實現以獲得高速度。見7.4.12 其他函數。
有關鎖定政策的更多資訊,見10.2.8 MySQL 怎樣鎖定表。
SET OPTION
句法SET [OPTION] SQL_VALUE_OPTION= value, ...
SET OPTION
設置影響伺服器或你的客戶操作的各種選項。你設置的任何選擇保持有效直到當前會話結束,或直到你設置選項為不同的值。
CHARACTER SET character_set_name | DEFAULT
character_set_name
當前唯一的選項是
cp1251_koi8
,但是你能容易通過編輯在MySQL原始碼版本的“sql/convert.cc”文件增加新的映射。內定映射能用character_set_name
的DEFAULT
值恢復。注意設置CHARACTER
SET
選項的語法不同於設置其他選項目的語法。 PASSWORD = PASSWORD('some password')
PASSWORD FOR user = PASSWORD('some password')
mysql
資料庫的用戶可以這樣做。用戶應該以user@hostname
格式給出,這裡user
和hostname
完全與他們列在mysql.user
表條目的User
和Host
列一樣。例如,如果你有一個條目其User
和Host
字段是'bob'
和'%.loc.gov'
,你將寫成:
mysql> SET PASSWORD FOR bob@"%.loc.gov" = PASSWORD("newpass"); 或 mysql> UPDATE mysql.user SET password=PASSWORD("newpass") where user="bob' and host="%.loc.gov";
SQL_AUTO_IS_NULL = 0 | 1
1
(內定 ),那麼對於一個具有一個自動加1的行的表,用下列構件能找出最後插入的行:WHERE
auto_increment_column IS NULL
。這被一些 ODBC 程式入Access使用。 SQL_BIG_TABLES = 0 | 1
1
,所有臨時表存在在磁碟上而非內存中。這將更慢一些,但是對需要大的臨時表的大SELECT
操作,你將不會得到The
table tbl_name is full
的錯誤。對於一個新連接的內定值是0
(即,使用內存中的臨時表)。
SQL_BIG_SELECTS = 0 | 1
0
,如果一個SELECT
嘗試可能花很長的時間,MySQL將放棄。這在一個不妥當的WHERE
語句發出時是有用的。一個大的查詢被定義為一個將可能必須檢驗多於max_join_size
行的SELECT
。對一個新連接的內定值是1
(它將允許所有SELECT
語句)。
SQL_LOW_PRIORITY_UPDATES = 0 | 1
1
,所有INSERT
、UPDATE
、DELETE
和LOCK
TABLE WRITE
語句等待,直到在受影響的表上沒有未解決的SELECT
或LOCK
TABLE READ
。 SQL_SELECT_LIMIT = value | DEFAULT
SELECT
語句返回的記錄的最大數量。如果一個SELECT
有一個LIMIT
子句,LIMIT
優先與SQL_SELECT_LIMIT
值。對一個新連接的內定值是“無限”的。如果你改變了限制,內定值能用SQL_SELECT_LIMIT
的一個DEFAULT
值恢復。
SQL_LOG_OFF = 0 | 1
1
,如果客戶有process權限,對該客戶沒有日誌記載到標準的日誌文件中。這不影響更新日誌記錄!
SQL_LOG_UPDATE = 0 | 1
0
, 如果客戶有process權限,對該客戶沒有日誌記載到更新日誌中。這不影響標準日誌文件!
TIMESTAMP = timestamp_value | DEFAULT
LAST_INSERT_ID = #
LAST_INSERT_ID()
返回的值。當你在更新一個表的命令中使用LAST_INSERT_ID()
時,它儲存在更新日誌中。
INSERT_ID = #
AUTO_INCREMENT
值時,由INSERT
命令使用的值。這主要與更新日誌一起使用。
GRANT
和REVOKE
句法GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...] ON {tbl_name | * | *.* | db_name.*} TO user_name [IDENTIFIED BY 'password'] [, user_name [IDENTIFIED BY 'password'] ...] [WITH GRANT OPTION] REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...] ON {tbl_name | * | *.* | db_name.*} FROM user_name [, user_name ...]
GRANT
在MySQL 3.22.11或以後版本中實現。對於更早MySQL版本,GRANT
語句不做任何事情。
GRANT
和REVOKE
命令允許系統主管在4個權限級別上授權和撤回賦予MySQL用戶的權利:
mysql.user
表中。
mysql.db
和mysql.host
表中。
mysql.tables_priv
表中。
mysql.columns_priv
表中。
對於GRANT
如何工作的例子,見6.11 為MySQL增加新的用戶權限。
對於GRANT
和REVOKE
語句,priv_type
可以指定下列的任何一個:
ALL PRIVILEGES FILE RELOAD ALTER INDEX SELECT CREATE INSERT SHUTDOWN DELETE PROCESS UPDATE DROP REFERENCES USAGE
ALL
是ALL PRIVILEGES
的一個同義詞,REFERENCES
還沒被實現,USAGE
當前是“沒有權限”的一個同義詞。它能用在你想要創建一個沒有權限用戶的時候。
為了從一個用戶撤回grant的權限,使用GRANT OPTION
的一個priv_type
值:
REVOKE GRANT OPTION ON ... FROM ...;
對於表,你能指定的唯一priv_type
值是SELECT
、INSERT
、UPDATE
、DELETE
、CREATE
、DROP
、GRANT
、INDEX
和ALTER
。
對於列,你能指定的唯一priv_type
值是(即,當你使用一個column_list
子句時)是SELECT
、INSERT
和UPDATE
。
你能通過使用ON *.*
語法設置全局權限,你能通過使用ON
db_name.*
語法設置資料庫權限。如果你指定ON *
並且你有一個當前資料庫,你將為該資料庫設置權限。(警告:如果你指定ON
*
而你沒有一個當前資料庫,你將影響全局權限!)
為了容納對任意主機的用戶授予的權利,MySQL支援以user@host
格式指定user_name
值。如果你想要指定一個特殊字符的一個user
字符串(例如“-”),或一個包含特殊字符或通配符的host
字符串(例如“%”),你可以用括號括起能用戶或主機名字
(例如,'test-user'@'test-hostname'
)。
你能在主機名中指定通配符。例如,user@"%.loc.gov"
適用於在loc.gov
域刈酚何主機的user
,並且user@"144.155.166.%"
適用於在144.155.166
類
C 子網刈酚何主機的user
。
簡單形式的user
是user@"%"
的一個同義詞。注意:如果你允許匿名用戶連接MySQL伺服器(它是內定的),你也應該增加所有本地用戶如user@localhost
,因為否則,當用戶試圖從本地機器上登錄到MySQL伺服器時,對於mysql.user
表中的本地主機的匿名用戶條目將被使用!匿名用戶通過插入有User=''
的條目到mysql.user
表中來定義。通過執行這個查詢,你可以檢驗它是否作用於你:
mysql> SELECT Host,User FROM mysql.user WHERE User='';
目前,GRANT
僅支援最長60個字符的主機、表、資料庫和列名。一個用戶名字能最多到16個字符。
對與一個表或列的權限是由4個權限級別的邏輯或形成的。例如,如果mysql.user
表指定一個用戶有一個全局select權限,它不能被資料庫、表或列的一個條目否認。
對於一個列的權限能如下計算:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
在大多數情況下,你只授予用戶一個權限級別上的權限,因此現實通常不像上面所說的那樣複雜。:) 權限檢查程序的細節在6 MySQL 存取權限系統中給出。
如果你為一個在mysql.user
表中不存在的用戶/主機名組合授權,一個條目被增加並且保留直到用一個DELETE
命令刪除。換句話說,GRANT
可以創建user
表的條目,但是REVOKE
將不刪除﹔你必須明確地使用DELETE
刪除.
在MySQL 3.22.12或以後,如果創建一個新用戶或如果你有全局授予權限,用戶的密碼將被設置為由IDENTIFIED
BY
子句指定的密碼,如果給出一個。如果用戶已經有了一個密碼,它被一個新的代替。
警告:如果你創造一個新用戶但是不指定一個IDENTIFIED
BY
子句,用戶沒有密碼。這是不安全的。
密碼也能用SET PASSWORD
命令設置。見7.25 SET OPTION
句法。
如果你為一個資料庫授權,如果需要在mysql.db
表中創建一個條目。當所有為資料庫的授權用REVOKE
刪除時,這個條目被刪除。
如果一個用戶沒有在一個表上的任何權限,當用戶請求一系列表時,表不被顯示(例如,用一個SHOW
TABLES
語句)。
WITH GRANT OPTION
子句給與用戶有授予其他用戶在指定的權限水平上的任何權限的能力。你應該謹慎對待你授予他grant權限的用戶,因為具有不同權限的兩個用戶也許能合並權限!
你不能授予其他用戶你自己不具備的權限﹔ agree權限允許你放棄你僅僅擁有的那些權限。
要知道,當你將一個特定權限級別上的grant授予其他用戶,用戶已經擁有(或在未來被授予!)的在該級別上的任何權限也可由該用戶授權。假定你授權一個用戶在一個資料庫上的insert權限,那麼如果你授權在資料庫上select權限並且指定WITH
GRANT OPTION
,用戶能不僅放棄select權限,還有insert。如果你授權用戶在資料庫上的update權限,用戶能放棄insert、select和update。
你不應該將alter權限授予一個一般用戶。如果你這樣做,用戶可以通過重命名表試圖顛覆權限系統!
注意,如果你正在使用即使一個用戶的表或列的權限,伺服器要檢查所有用戶的表和列權限並且這將使MySQL慢下來一點。
當mysqld
啟動時,所有的權限被讀入儲存器。資料庫、表和列權限馬上生效,而用戶級權限在下一次用戶連接時生效。你用GRANT
或REVOKE
對受權表執行的更改立即被伺服器知曉。如果你手工修改授權表(使用INSERT
、UPDATE等等),你應該執行一個FLUSH
PRIVILEGES
語句或運行mysqladmin flush-privileges
告訴伺服器再次裝載授權表。見6.9 權限變化何時生效。
ANSI SQL版本的GRANT
與MySQL版本之間的最大差別:
REVOKE
命令或操作MySQL授權表拋棄。
CREATE INDEX
句法CREATE [UNIQUE] INDEX index_name ON tbl_name (col_name[(length)],... )
CREATE INDEX
語句在MySQL版本 3.22
以前不做任何事情。在 3.22 或以後版本中,CREATE INDEX
被映射到一個ALTER
TABLE
語句來創建索引。見7.8
ALTER TABLE
句法。
通常,你在用CREATE TABLE
創建表本身時創建表的所有索引。見7.7 CREATE TABLE
句法。CREATE
INDEX
允許你把索引加到現有表中。
一個(col1,col2,...)
形式的列表創造一個多列索引。索引值有給定列的值串聯而成。
對於CHAR
和VARCHAR
列,索引可以只用一個列的部分來創建,使用col_name(length)
句法。(在BLOB
和TEXT
列上需要長度)。下面顯示的語句使用name
列的頭10個字符創建一個索引:
mysql> CREATE INDEX part_of_name ON customer (name(10));
因為大多數名字通常在頭10個字符不同,這個索引應該不比從整個name
列的創建的索引慢多少。另外,在索引使用部分的列能使這個索引成為更小的文件大部分, 它能保存很多磁碟空格並且可能也加快INSERT
操作!
注意,如果你正在使用MySQL版本 3.23.2
或更新並且正在使用MyISAM
桌子類型,你只能在可以有NULL
值的列或一個BLOB
/TEXT
列上增加一個索引,
關於MySQL如何使用索引的更多資訊,見10.4 MySQL索引的使用。
DROP INDEX
句法DROP INDEX index_name ON tbl_name
DROP INDEX
從tbl_name
表拋棄名為index_name
的索引。DROP
INDEX
在MySQL 3.22 以前的版本中不做任何事情。在 3.22
或以後,DROP INDEX
被映射到一個ALTER TABLE
語句來拋棄索引。見7.8 ALTER TABLE
句法。
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>
變為'>
或">
。
當你交互式運行mysql
時和當你把命令放在一個文件中並用mysql
< some-file
告訴mysql
從那個文件讀它的輸入時,這些限制都適用。
MySQL不支援‘--’的ANSI SQL注釋風格。見5.4.7 ‘--’作為一篇注釋的開始。
CREATE
FUNCTION/DROP FUNCTION
句法CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER} SONAME shared_library_name DROP FUNCTION function_name
一個用戶可定義函數(UDF)是用一個像MySQL的原生(內置)函數如ABS()
和CONCAT()
的新函數來擴展MySQL的方法。
AGGREGATE
是MySQL 3.23的一個新選項。一個AGGREGATE
函數功能就像一個原生MySQL
GROUP
函數如SUM
或COUNT()
。
CREATE FUNCTION
在mysql.func
系統表中保存函數名、類型和共享庫名。你必須對mysql
資料庫有insert和delete權限以創建和拋棄函數。
所有活躍的函數在每次伺服器啟動時被重新裝載,除非你使用--skip-grant-tables
選項啟動mysqld
,在這種情況下,UDF初始化被跳過並且UDF是無法獲得的。(一個活躍函數是一個已經用CREATE
FUNCTION
裝載並且沒用DROP FUNCTION
刪除的函數。)
關於編寫用戶可定義函數的指令,見14 為MySQL增加新函數。對於UDF的工作機制,函數必須用
C 或 C++
編寫,你的作業系統必須支援動態裝載並且你必須動態編譯了mysqld
(不是靜態)。
一個常見的問題源自於試圖使用MySQL內置的數據類型或函數名同名的列來創建資料庫表,例如TIMESTAMP
或GROUP
。你允許這樣做(例如,ABS
是一個允許的列名),但是當使用其名字也是列名的函數時,在一個函數名和“
( ”之間不允許白空。
下列詞明確地在MySQL中被保留。他們的大多數被 ANSI
SQL92 禁止作為列或表名(例如,group
)。一些被保留因為MySQL需要他們並且正在(當前)使用一個yacc
分析器:
action |
add |
aggregate |
all |
alter |
after |
and |
as |
asc |
avg |
avg_row_length |
auto_increment |
between |
bigint |
bit |
binary |
blob |
bool |
both |
by |
cascade |
case |
char |
character |
change |
check |
checksum |
column |
columns |
comment |
constraint |
create |
cross |
current_date |
current_time |
current_timestamp |
data |
database |
databases |
date |
datetime |
day |
day_hour |
day_minute |
day_second |
dayofmonth |
dayofweek |
dayofyear |
dec |
decimal |
default |
delayed |
delay_key_write |
delete |
desc |
describe |
distinct |
distinctrow |
double |
drop |
end |
else |
escape |
escaped |
enclosed |
enum |
explain |
exists |
fields |
file |
first |
float |
float4 |
float8 |
flush |
foreign |
from |
for |
full |
function |
global |
grant |
grants |
group |
having |
heap |
high_priority |
hour |
hour_minute |
hour_second |
hosts |
identified |
ignore |
in |
index |
infile |
inner |
insert |
insert_id |
int |
integer |
interval |
int1 |
int2 |
int3 |
int4 |
int8 |
into |
if |
is |
isam |
join |
key |
keys |
kill |
last_insert_id |
leading |
left |
length |
like |
lines |
limit |
load |
local |
lock |
logs |
long |
longblob |
longtext |
low_priority |
max |
max_rows |
match |
mediumblob |
mediumtext |
mediumint |
middleint |
min_rows |
minute |
minute_second |
modify |
month |
monthname |
myisam |
natural |
numeric |
no |
not |
null |
on |
optimize |
option |
optionally |
or |
order |
outer |
outfile |
pack_keys |
partial |
password |
precision |
primary |
procedure |
process |
processlist |
privileges |
read |
real |
references |
reload |
regexp |
rename |
replace |
restrict |
returns |
revoke |
rlike |
row |
rows |
second |
select |
set |
show |
shutdown |
smallint |
soname |
sql_big_tables |
sql_big_selects |
sql_low_priority_updates |
sql_log_off |
sql_log_update |
sql_select_limit |
sql_small_result |
sql_big_result |
sql_warnings |
straight_join |
starting |
status |
string |
table |
tables |
temporary |
terminated |
text |
then |
time |
timestamp |
tinyblob |
tinytext |
tinyint |
trailing |
to |
type |
use |
using |
unique |
unlock |
unsigned |
update |
usage |
values |
varchar |
variables |
varying |
varbinary |
with |
write |
when |
where |
year |
year_month |
zerofill |
下列符號(來自上表)被ANSI SQL禁止但是被MySQL允許作為列/表名。這是因為這些名字的一些是很自然的名字並且很多人已經使用了他們。
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP