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