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