13. SQL語句語法

13.1. 數據定義語句

13.1.1. ALTER DATABASE語法

ALTER {DATABASE | SCHEMA} [db_name]
    alter_specification [, alter_specification] ...

alter_specification:
    [DEFAULT] CHARACTER SET charset_name
  | [DEFAULT] COLLATE collation_name

ALTER DATABASE用於更改數據庫的全局特性。這些特性儲存在數據庫目錄中的db.opt文件中。要使用ALTER DATABASE,您需要獲得數據庫ALTER權限。

CHARACTER SET子句用於更改默認的數據庫字符集。COLLATE子句用於更改默認的數據庫整序。在第10章字符集支持中對字符集和整序名稱進行了討論。

數據庫名稱可以忽略,此時,語句對應於默認數據庫。也可以使用ALTER SCHEMA

13.1.2. ALTER TABLE語法

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

alter_specification:
    ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
  | ADD [COLUMN] (column_definition,...)
  | ADD INDEX [index_name] [index_type] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        PRIMARY KEY [index_type] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        UNIQUE [index_name] [index_type] (index_col_name,...)
  | ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        FOREIGN KEY [index_name] (index_col_name,...)
        [reference_definition]
  | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  | CHANGE [COLUMN] old_col_name column_definition
        [FIRST|AFTER col_name]
  | MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
  | DROP [COLUMN] col_name
  | DROP PRIMARY KEY
  | DROP INDEX index_name
  | DROP FOREIGN KEY fk_symbol
  | DISABLE KEYS
  | ENABLE KEYS
  | RENAME [TO] new_tbl_name
  | ORDER BY col_name
  | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
  | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
  | DISCARD TABLESPACE
  | IMPORT TABLESPACE
  | table_options
  | partition_options
  | ADD PARTITION partition_definition
  | DROP PARTITION partition_names
  | COALESCE PARTITION number
  | REORGANIZE PARTITION partition_names INTO (partition_definitions)
  | ANALYZE PARTITION partition_names
  | CHECK PARTITION partition_names
  | OPTIMIZE PARTITION partition_names
  | REBUILD PARTITION partition_names
  | REPAIR PARTITION partition_names

ALTER TABLE用於更改原有表的結構。例如,您可以增加或刪減列,創建或取消索引,更改原有列的類型,或重新命名列或表。您還可以更改表的評註和表的類型。

允許進行的變更中,許多子句的語法與CREATE TABLE中的子句的語法相近。其中包括table_options修改,選項有ENGINE, AUTO_INCREMENTAVG_ROW_LENGTH等。請見13.1.5節,“CREATE TABLE語法”

存儲引擎不支持有些操作,如果進行這些操作,會出現警告。使用SHOW WARNINGS可以顯示出這些警告。請參見13.5.4.22節,“SHOW WARNINGS語法”

如果您使用ALTER TABLE更改列規約,但是DESCRIBE tbl_name提示您列規約並沒有改變,則可能是因爲MySQL忽略了您所做的更改。忽略更改的原因見13.1.5.1節,“沉寂的列規格變更”。例如,如果您試圖把VARCHAR列更改爲CHAR列,此時,如果表包含其它長度可變的列,則MySQL仍會使用VARCHAR

ALTER TABLE運行時會對原表進行臨時複製,在副本上進行更改,然後刪除原表,再對新表進行重命名。在執行ALTER TABLE時,其它用戶可以閱讀原表,但是對錶的更新和修改的操作將被延遲,直到新表生成爲止。新表生成後,這些更新和修改信息會自動轉移到新表上。

注意,如果您在執行ALTER TABLE時使用除了RENAME以外的選項,則MySQL會創建一個臨時表。即使數據並不需要進行復制(例如當您更改列的名稱時),MySQL也會這麼操作。對於MyISAM表,您可以通過把myisam_sort_buffer_size系統變量設置到一個較高的值,來加快重新創建索引(該操作是變更過程中速度最慢的一部分)的速度。

·         要使用ALTER TABLE,您需要獲得表的ALTER, INSERTCREATE權限。

·         IGNOREMySQL相對於標準SQL的擴展。如果在新表中有重複關鍵字,或者當STRICT模式啓動後出現警告,則使用IGNORE控制ALTER TABLE的運行。如果沒有指定IGNORE,當重複關鍵字錯誤發生時,複製操作被放棄,返回前一步驟。如果指定了IGNORE,則對於有重複關鍵字的行,只使用第一行,其它有衝突的行被刪除。並且,對錯誤值進行修正,使之儘量接近正確值。

·         您可以在一個ALTER TABLE語句裏寫入多個ADD, ALTER, DROPCHANGE子句,中間用逗號分開。這是MySQL相對於標準SQL的擴展。在標準SQL中,每個ALTER TABLE語句中每個子句只允許使用一次。例如,在一個語句中取消多個列:

·                mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;

·         CHANGE col_name, DROP col_nameDROP INDEXMySQL相對於標準SQL的擴展。

·         MODIFYOracleALTER TABLE的擴展。

·         COLUMN只是自選項目,可以忽略。

·         如果您使用ALTER TABLE tbl_name RENAME TO new_tbl_name並且沒有其它選項,則MySQL只對與table tbl_name相對應的文件進行重命名。不需要創建一個臨時表。(您也可以使用RENAME TABLE語句對錶進行重命名。請參見13.1.9節,“RENAME TABLE語法”。)

·         column_definition子句使用與CREATE TABLE中的ADDCHANGE子句相同的語法。注意,此語法包括列名稱,而不只是列類型。請參見13.1.5節,“CREATE TABLE語法”

·         您可以使用CHANGE old_col_name column_definition子句對列進行重命名。重命名時,需給定舊的和新的列名稱和列當前的類型。例如:要把一個INTEGER列的名稱從a變更到b,您需要如下操作:

·                mysql> ALTER TABLE t1 CHANGE a b INTEGER;

如果您想要更改列的類型而不是名稱, CHANGE語法仍然要求舊的和新的列名稱,即使舊的和新的列名稱是一樣的。例如:

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

您也可以使用MODIFY來改變列的類型,此時不需要重命名:

mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

·         如果您使用CHANGEMODITY縮短列長時,列中存在有索引,並且縮短後的列長小於索引長度,則MySQL會自動縮短索引的長度。

·         當您使用CHANGEMODIFY更改列的類型時,MySQL會盡量把原有的列值轉化爲新的類型。

·         您可以使用FIRSTAFTER col_name在一個錶行中的某個特定位置添加列。默認把列添加到最後。您也可以在CHANGEMODIFY語句中使用FIRSTAFTER

·         AFTER COLUMN用於指定列的新默認值,或刪除舊的默認值。如果舊的默認值被刪除同時列值爲NULL,則新的默認值爲NULL。如果列值不能爲NULLMySQL會指定一個默認值,請參見13.1.5節,“CREATE TABLE語法”

·         DROP INDEX用於取消索引。這是MySQL相對於標準SQL的擴展。請參見13.1.7節,“DROP INDEX語法”

·         如果列從表中被取消了,則這些列也從相應的索引中被取消。如果組成一個索引的所有列均被取消,則該索引也被取消。

·         如果一個表只包含一列,則此列不能被取消。如果您想要取消表,應使用DROP TABLE

·         DROP PRIMAY DEY用於取消主索引。註釋:在MySQL較早的版本中,如果沒有主索引,則DROP PRIMARY KEY會取消表中的第一個UNIQUE索引。在MySQL 5.1中不會出現這種情況。如果在MySQL 5.1中對沒有主鍵的表使用DROP PRIMARY KEY,則會出現錯誤信息。

如果您向表中添加UNIQUE KEYPRIMARY KEY,則UNIQUE KEYPRIMARY KEY會被儲存在非唯一索引之前,這樣MySQL就可以儘早地檢查出重複關鍵字。

·         ORDER BY用於在創建新表時,讓各行按一定的順序排列。注意,在插入和刪除後,表不會仍保持此順序。當您知道多數情況下您會按照特定的順序查詢各行時,可以使用這個選項;在對錶進行了大的改動後,通過使用此選項,您可以提高查詢效率。在有些情況下,如果表按列排序,對於MySQL來說,排序可能會更簡單。

·         如果您對一個MyISAM表使用ALTER TABLE,則所有非唯一索引會被創建到一個單獨的批裏(和REPAIR TABLE相同)。當您有許多索引時,這樣做可以使ALTER TABLE的速度更快。

這項功能可以明確激活。ALTER TABLE...DISABLE KEYSMySQL停止更新MyISAM表中的非唯一索引。然後使用ALTER TABLE ... ENABLE KEYS重新創建丟失的索引。進行此操作時,MySQL採用一種特殊的算法,比一個接一個地插入關鍵字要快很多。因此,在進行成批插入操作前先使關鍵字禁用可以大大地加快速度。使用ALTER TABLE ... DISABLE KEYS除了需要獲得以前提到的權限以外,還需要獲得INDEX權限。

·         Innodb存儲引擎支持FOREIGN KEYREFERENCES子句。Innodb存儲引擎執行ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...)。請參見15.2.6.4節,“FOREIGN KEY約束”。對於其它存儲引擎,這些子句會被分析,但是會被忽略。對於所有的存儲引擎,CHECK子句會被分析,但是會被忽略。請參見13.1.5節,“CREATE TABLE語法”。接受這些子句但又忽略子句的原因是爲了提高兼容性,以便更容易地從其它SQL服務器中導入代碼,並運行應用程序,創建帶參考數據的表。請參見1.8.5節,“MySQL與標準SQL的差別”

·         InnoDB支持使用ALTER TABLE來取消外鍵:

·                ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;

要了解更多信息,請參見15.2.6.4節,“FOREIGN KEY約束”

·         ALTER TABLE忽略DATA DIRECTORYINDEX DIRECTORY表選項。

·         如果您想要把表默認的字符集和所有字符列(CHAR, VARCHAR, TEXT)改爲新的字符集,應使用如下語句:

·                ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;

警告:前面的操作轉換了字符集之間的列類型。如果您有一列使用一種字符集(如latin1),但是存儲的值實際上使用了其它的字符集(如utf8),這種情況不是您想要的。此時,您必須對這樣的列進行以下操作。

ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

這種方法能夠實現此功能的原因是,當您轉換到BLOB列或從BLOB列轉換過來時,並沒有發生轉換。

如果您指定CONVERT TO CHARACTER SET爲二進制,則TEXT列被轉換到相應的二進制字符串類型(BINARY, VARBINARY, BLOB)。這意味着這些列將不再有字符集,接下來的CONVERT TO操作也將不適用於這些列。

要僅僅改變一個表的默認字符集,應使用此語句:

ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;

詞語DEFAULT爲自選項。如果您在向表中添加一個新列時(例如,使用ALTER TABLE...ADD column)沒有指定字符集,則此時使用的字符集爲默認字符集。

警告:ALTER TABLE...DEFAULT CHARACTER SETALTER TABLE...CHARACTER SET是等價的,只用於更改默認的表字符集。

·         如果InnoDB表在創建時,使用了.ibd文件中的自己的表空間,則這樣的文件可以被刪除和導入。使用此語句刪除.ibd文件:

·                ALTER TABLE tbl_name DISCARD TABLESPACE;

此語句用於刪除當前的.ibd文件,所以應首先確認您有一個備份。如果在表空間被刪除後嘗試打開表格,則會出現錯誤。

要把備份的.ibd文件還原到表中,需把此文件複製到數據庫目錄中,然後書寫此語句:

ALTER TABLE tbl_name IMPORT TABLESPACE;

15.2.6.6節,“使用按表的表空間”

·         使用mysql_info() C API函數,您可以瞭解有多少記錄已被複制,以及(當使用IGNORE時)有多少記錄由於重複關鍵字的原因已被刪除。請參見25.2.3.34節,“mysql_info()”

·         ALTER TABLE也可以用於對帶分區的表進行重新分區,功能包括添加、取消、合併和拆分各分區,還可以用於進行分區維護。

對帶分區的表使用partition_options子句和ALTER TABLE可以對錶進行重新分區,使用時依據partition_options定義的分區方法。本子句以PARTITION BY爲開頭,然後使用與用於CREATE TABLEpartition_options子句一樣的語法和規則(要了解詳細信息,請參見13.1.5節,“CREATE TABLE語法”)。註釋:MySQL 5.1服務器目前接受此語法,但是不實際執行;等MySQL 5.1開發出來後,將執行此語法。

用於ALTER TABLE ADD PARTITIONpartition_definition子句支持用於CREATE TABLE語句的partition_definition子句的同樣名稱的選項。(要了解語法和介紹,請參見13.1.5節,“CREATE TABLE語法”。)例如,假設您有一個按照以下方式創建的帶分區的表:

CREATE TABLE t1 (
    id INT,
    year_col INT
)
PARTITION BY RANGE (year_col) (
    PARTITION p0 VALUES LESS THAN (1991),
    PARTITION p1 VALUES LESS THAN (1995),
    PARTITION p2 VALUES LESS THAN (1999)
);    

您可以在表中增加一個新的分區p3,該分區用於儲存小於2002的值。添加方法如下:

ALTER TABLE t1 ADD PARTITION p3 VALUES LESS THAN (2002);

註釋:您不能使用ALTER TABLE向一個沒有進行分區的表添加分區。

DROP PARTITION用於取消一個或多個RANGELIST分區。此命令不能用於HASHKEY 分區;用於這兩個分區時,應使用COALESCE PARTITION(見後)。如果被取消的分區其名稱列於partition_names清單中,則儲存在此分區中的數據也被取消。例如,如果以前已定義的表t1,您可以採用如下方法取消名稱爲p0p1的分區:

ALTER TABLE DROP PARTITION p0, p1;

ADD PARTITIONDROP PARTITION目前不支持IF [NOT] EXISTS。也不可能對一個分區或一個已分區的表進行重命名。如果您希望對一個分區進行重命名,您必須取消分區,再重新建立;如果您希望對一個已分區的表進行重新命名,您必須取消所有分區,然後對錶進行重命名,再添加被取消的分區。

COALESCE PARTITION可以用於使用HASHKEY進行分區的表,以便使用number來減少分區的數目。例如,假設您使用下列方法創建了表t2

CREATE TABLE t2 (
    name VARCHAR (30),
    started DATE
)
PARTITION BY HASH(YEAR(started))
PARTITIONS (6);

您可以使用以下命令,把t2使用的分區的數目由6個減少到4個:

ALTER TABLE t2 COALESCE PARTITION 2;

包含在最後一個number分區中的數據將被合併到其餘的分區中。在此情況下,分區4和分區5將被合併到前4個分區中(編號爲0123的分區)。

如果要更改部分分區,但不更改所有的分區,您可以使用REORGANIZE PARTITION。這個命令有多種使用方法:

o        把多個分區合併爲一個分區。通過把多個分區的名稱列入partition_names清單,併爲partition_definition提供一個單一的定義,可以實現這個功能。

o        把一個原有的分區拆分爲多個分區。通過爲partition_names命名一個分區,並提供多個partition_definitions,可以實現這個功能。

o        更改使用VALUES LESS THAN定義的分區子集的範圍或更改使用VALUES IN定義的分區子集的值清單。

註釋:對於沒有明確命名的分區,MySQL會自動提供默認名稱p0, p1, p2等。

要了解有關ALTER TALBE...REORANIZE PARTITION命令的詳細信息,請參見18.3節,“分區管理”

·         多個附加子句用於提供分區維護和修補功能。這些功能與用於非分區表的功能類似。這些功能由CHECK TABLEREPAIR TABLE等命令(這些命令不支持用於分區表)執行。這些子句包括ANALYZE PARTITION, CHECK PARTITION, OPTIMIZE PARTITION, REBUILD PARTITIONREPAIR PARTITION.每個選項均爲一個partition_names子句,包括一個或多個分區名稱。需要更改的表中必須已存在這些分區。多個分區名稱用逗號分隔。要了解更多信息,或要了解舉例說明,請參見18.3.3節,“分區維護”

以下例子展示了ALTER TABLE的使用。首先展示表t1。表t1採用如下方法創建:

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

把表t1重新命名爲t2

mysql> ALTER TABLE t1 RENAME t2;

把列aINTERGER更改爲TINYINT NOT NULL(名稱保持不變),並把列bCHAR(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 INDEX (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 PRIMARY KEY (c);

注意我們爲c編制了索引(作爲PRIMARY KEY),因爲AUTO_INCREMENT列必須編制索引。同時我們定義cNOT NULL,因爲主鍵列不能爲NULL

當您添加一個AUTO_INCREMENT列時,列值被自動地按序號填入。對於MyISAM表,您可以在ALTER TABLE之前執行SET INSERT_ID=value來設置第一個序號,也可以使用AUTO_INCREMENT=value表選項來設置。請參見13.5.3節,“SET語法”

如果值大於AUTO_INCREMENT列中的最大值,則您可以使用用於InnoDB表的ALTER TALBE...AUTO_INCREMENT=value表選項,來爲新行設置序號。如果值小於列中當前的最大值,不會出現錯誤信息,當前的序列值也不改變。

使用MyISAM表時,如果您不更改AUTO_INCREMENT列,則序列號不受影響。如果您取消一個AUTO_INCREMENT列,然後添加另一個AUTO_INCREMENT列,則序號重新排列,從1開始。

A.7.1節,“與ALTER TABLE有關的問題”

13.1.3. CREATE DATABASE語法

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
    [create_specification [, create_specification] ...]
 
create_specification:
    [DEFAULT] CHARACTER SET charset_name
  | [DEFAULT] COLLATE collation_name

CREATE DATABASE用於創建數據庫,並進行命名。如果要使用CREATE DATABASE,您需要獲得數據庫CREATE權限。

有關合法數據庫名稱的規定列於9.2節,“數據庫、表、索引、列和別名”。如果存在數據庫,並且您沒有指定IF NOT EXISTS,則會出現錯誤。

create_specification選項用於指定數據庫的特性。數據庫特性儲存在數據庫目錄中的db.opt文件中。CHARACTER SET子句用於指定默認的數據庫字符集。COLLATE子句用於指定默認的數據庫整序。字符集和整序名稱在第10章字符集支持中討論。

有些目錄包含文件,這些文件與數據庫中的表對應。MySQL中的數據庫的執行方法與這些目錄的執行方法相同。因爲當數據庫剛剛被創建時,在數據庫中沒有表,所以CREATE DATABASE只創建一個目錄。這個目錄位於MySQL數據目錄和db.opt文件之下。

如果您手動在數據目錄之下創建一個目錄(例如,使用mkdir),則服務器會認爲這是一個數據庫目錄,並在SHOW DATABASES的輸出中顯示出來。

也可以使用CREATE SCHEMA

您還可以使用mysqladmin程序創建數據庫。請參見8.5節,“mysqladmin:用於管理MySQL服務器的客戶端”

13.1.4. CREATE INDEX語法

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [USING index_type]
    ON tbl_name (index_col_name,...)
 
index_col_name:
    col_name [(length)] [ASC | DESC]

CREATE INDEX被映射到一個ALTER TABLE語句上,用於創建索引。請參見13.1.2節,“ALTER TABLE語法”

通常,當使用CREATE TABLE創建表時,也同時在表中創建了所有的索引。請參見13.1.5節,“CREATE TABLE語法”CREATE INDEX允許您向已有的表中添加索引。

格式爲(col1, col2,...)的一個列清單創建出一個多列索引。通過串接給定列中的值,確定索引值的格式。

對於CHARVARCHAR列,只用一列的一部分就可創建索引。創建索引時,使用col_name(length)語法,對前綴編制索引。前綴包括每列值的前length字符。BLOBTEXT列也可以編制索引,但是必須給出前綴長度。

此處展示的語句用於創建一個索引,索引使用列名稱的前10個字符。

CREATE INDEX part_of_name ON customer (name(10));

因爲多數名稱的前10個字符通常不同,所以此索引不會比使用列的全名創建的索引速度慢很多。另外,使用列的一部分創建索引可以使索引文件大大減小,從而節省了大量的磁盤空間,有可能提高INSERT操作的速度。

前綴最長爲255字節。對於MyISAMInnoDB表,前綴最長爲1000字節。注意前綴的限長以字節計,而CREATE INDEX語句中的前綴長度指的是字符的數目。對於使用多字節字符集的列,在指定列的前綴長度時,要考慮這一點。

MySQL 5.1中:

·         只有當您正在使用MyISAM, InnoDBBDB表類型時,您可以向有NULL值的列中添加索引。

·         只有當您正在使用MyISAM, BDBInnoDB表類型時,您可以向BLOBTEXT列中添加索引。

一個index_col_name規約可以以ASCDESC爲結尾。這些關鍵詞將來可以擴展,用於指定遞增或遞減索引值存儲。目前,這些關鍵詞被分析,但是被忽略;索引值均以遞增順序存儲。

部分儲存引擎允許在創建索引時指定索引類型。index_type指定語句的語法是USING type_name。不同的儲存引擎所支持的type_name值已顯示在下表中。如果列有多個索引類型,當沒有指定index_type時,第一個類型是默認值

存儲引擎

允許的索引類型

MyISAM

BTREE

InnoDB

BTREE

MEMORY/HEAP

HASH, BTREE

示例:

CREATE TABLE lookup (id INT) ENGINE = MEMORY;
CREATE INDEX id_index USING BTREE ON lookup (id);

TYPE type_name可以作爲USING type_name的同義詞,用於指定索引類型。但是,USING是首選的格式。另外,在索引規約語法中,位於索引類型前面的索引名稱不能使用TYPE。這是因爲,與USING不同,TYPE不是保留詞,因此會被認爲是一個索引名稱。

如果您指定的索引類型在給定的儲存引擎中不合法,但是有其它的索引類型適合引擎使用,並且不會影響查詢功能,則引擎應使用此類型。

要了解更多有關MySQL如何使用索引的信息,請參見7.4.5節,“MySQL如何使用索引”

FULLTEXT索引只能對CHAR, VARCHARTEXT列編制索引,並且只能在MyISAM表中編制。請參見12.7節,“全文搜索功能”

SPATIAL索引只能對空間列編制索引,並且只能在MyISAM表中編制。空間列類型在第19章:MySQL中的空間擴展中進行了描述。

13.1.5. CREATE TABLE語法

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

或:

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(] LIKE old_tbl_name [)];
 
create_definition:
    column_definition
  | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
  | KEY [index_name] [index_type] (index_col_name,...)
  | INDEX [index_name] [index_type] (index_col_name,...)
  | [CONSTRAINT [symbol]] UNIQUE [INDEX]
        [index_name] [index_type] (index_col_name,...)
  | [FULLTEXT|SPATIAL] [INDEX] [index_name] (index_col_name,...)
  | [CONSTRAINT [symbol]] FOREIGN KEY
        [index_name] (index_col_name,...) [reference_definition]
  | CHECK (expr)
 
column_definition:
    col_name type [NOT NULL | NULL] [DEFAULT default_value]
        [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
        [COMMENT 'string'] [reference_definition]
 
type:
    TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  | INT[(length)] [UNSIGNED] [ZEROFILL]
  | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  | DATE
  | TIME
  | TIMESTAMP
  | DATETIME
  | CHAR(length) [BINARY | ASCII | UNICODE]
  | VARCHAR(length) [BINARY]
  | TINYBLOB
  | BLOB
  | MEDIUMBLOB
  | LONGBLOB
  | TINYTEXT [BINARY]
  | TEXT [BINARY]
  | MEDIUMTEXT [BINARY]
  | LONGTEXT [BINARY]
  | ENUM(value1,value2,value3,...)
  | SET(value1,value2,value3,...)
  | spatial_type
 
index_col_name:
    col_name [(length)] [ASC | DESC]
 
reference_definition:
    REFERENCES tbl_name [(index_col_name,...)]
               [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
               [ON DELETE reference_option]
               [ON UPDATE reference_option]
 
reference_option:
    RESTRICT | CASCADE | SET NULL | NO ACTION
 
table_options: table_option [table_option] ...
 
table_option:
    {ENGINE|TYPE} = engine_name
  | AUTO_INCREMENT = value
  | AVG_ROW_LENGTH = value
  | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
  | CHECKSUM = {0 | 1}
  | COMMENT = 'string'
  | CONNECTION = 'connect_string'
  | MAX_ROWS = value
  | MIN_ROWS = value
  | PACK_KEYS = {0 | 1 | DEFAULT}
  | PASSWORD = 'string'
  | DELAY_KEY_WRITE = {0 | 1}
  | ROW_FORMAT = {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
  | UNION = (tbl_name[,tbl_name]...)
  | INSERT_METHOD = { NO | FIRST | LAST }
  | DATA DIRECTORY = 'absolute path to directory'
  | INDEX DIRECTORY = 'absolute path to directory'
 
partition_options:
    PARTITION BY
           [LINEAR] HASH(expr)
        |  [LINEAR] KEY(column_list)
        |  RANGE(expr)
        |  LIST(column_list)
    [PARTITIONS num]
    [  SUBPARTITION BY
           [LINEAR] HASH(expr)
         | [LINEAR] KEY(column_list)
      [SUBPARTITIONS(num)]  
    ]
    [(partition_definition), [(partition_definition)], ...]
 
partition_definition:
    PARTITION partition_name
        [VALUES { 
                  LESS THAN (expr) | MAXVALUE 
                | IN (value_list) }]
        [[STORAGE] ENGINE [=] engine-name]
        [COMMENT [=] 'comment_text' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] (tablespace_name)]
        [NODEGROUP [=] node_group_id]
        [(subpartition_definition), [(subpartition_definition)], ...]
 
subpartition_definition:
    SUBPARTITION logical_name
        [[STORAGE] ENGINE [=] engine-name]
        [COMMENT [=] 'comment_text' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] (tablespace_name)]
        [NODEGROUP [=] node_group_id]
 
select_statement:
    [IGNORE | REPLACE] [AS] SELECT ...   (Some legal select statement)

CREATE TABLE用於創建帶給定名稱的表。您必須擁有表CREATE權限。

允許的表名稱的規則列於9.2節,“數據庫、表、索引、列和別名”中。默認的情況是,表被創建到當前的數據庫中。如果表已存在,或者如果沒有當前數據庫,或者如果數據庫不存在,則會出現錯誤。

表名稱被指定爲db_name.tbl_name,以便在特定的數據庫中創建表。不論是否有當前數據庫,都可以通過這種方式創建表。如果您使用加引號的識別名,則應對數據庫和表名稱分別加引號。例如,`mydb`.`mytbl`是合法的,但是`mydb.mytbl`不合法。

在創建表格時,您可以使用TEMPORARY關鍵詞。只有在當前連接情況下,TEMPORARY表纔是可見的。當連接關閉時,TEMPORARY表被自動取消。這意味着兩個不同的連接可以使用相同的臨時表名稱,同時兩個臨時表不會互相沖突,也不與原有的同名的非臨時表衝突。(原有的表被隱藏,直到臨時表被取消時爲止。)您必須擁有CREATE TEMPORARY TABLES權限,才能創建臨時表。

如果表已存在,則使用關鍵詞IF NOT EXISTS可以防止發生錯誤。注意,原有表的結構與CREATE TABLE語句中表示的表的結構是否相同,這一點沒有驗證。註釋:如果您在CREATE TABLE...SELECT語句中使用IF NOT EXISTS,則不論表是否已存在,由SELECT部分選擇的記錄都會被插入。

MySQL通過數據庫目錄中的.frm表格式(定義)文件表示每個表。表的存儲引擎也可能會創建其它文件。對於MyISAM表,存儲引擎可以創建數據和索引文件。因此,對於每個MyISAMtbl_name,有三個磁盤文件:

文件

作用

tbl_name.frm

表格式(定義)文件

tbl_name.MYD

數據文件

tbl_name.MYI

索引文件

用於表示表的由存儲引擎創建的文件在第15章:存儲引擎和表類型中描述。

要了解有關各種列類型的性質的一般說明,請參見第11章:列類型。要了解有關空間列類型的說明,請參見第19章:MySQL中的空間擴展

·         如果沒有指定是NULL或是NOT NULL,則列在創建時假定指定爲NULL

·         一個整數列可以擁有一個附加屬性AUTO_INCREMENT。當您向一個已編入索引的AUTO_INCREMENT列中插入一個NULL值(建議)或0時,此列被設置爲下一個序列的值。通常情況下爲value+1,此處value是當前在表中的列的最大值。AUTO_INCREMENT序列從1開始。這樣的列必須被定義爲一種整數類型,請參見11.1.1節,“數值類型概述”中的敘述。(值1.0不是整數)。請參見25.2.3.36節,“mysql_insert_id()”

--sql-mode服務器選項或sql_mode系統變量指定NO_AUTO_VALUE_ON_ZERO特徵位,這樣可以把0存儲到AUTO_INCREMENT列中,同時不生成一個新的序列值。請參見5.3.1節,“mysqld命令行選項”

註釋:有時候,每個表只有一個AUTO_INCREMENT列,此列必須編制索引,不能有DEFAULT值。一個AUTO_INCREMENT列只有在只包含正數的情況下,才能運行正常。插入一個負數會被認爲是插入了一個非常大的正數。這樣做是爲了避免當數字由正數轉爲負數時出現精度問題,同時也爲了確保AUTO_INCREMENT列中不會包含0

對於MyISAMBDB表,您可以在一個多列關鍵字中指定一個AUTO_INCREMENT次級列。請參見3.6.9節,“使用AUTO_INCREMENT”

爲了讓MySQL與部分ODBC應用軟件相兼容,您可以使用以下查詢方法找到最後一個插入行的AUTO_INCREMENT值:

SELECT * FROM tbl_name WHERE auto_col IS NULL

·         字符列的定義可以包括一個CHARACTER SET屬性,用來指定字符集,也可以指定列的整序。要了解詳細情況,請參見第10章:字符集支持CHARSETCHARACTER SET的同義詞。

·                CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);

MySQL 5.1理解,在字符列定義中的長度規約以字符爲單位。(有些早期版本以字節爲單位。)

·         DEFAULT子句用於爲列指定一個默認值。默認值必須爲一個常數,不能爲一個函數或一個表達式,有一種情況例外。例如,一個日期列的默認值不能被設置爲一個函數,如NOW()CURRENT_DATE。不過,有一種例外,您可以對TIMESTAMP列指定CURRENT_TIMESTAMP爲默認值。請參見11.3.1.1節,“MySQL 4.1中的TIMESTAMP屬性”

BLOBTEXT列不能被賦予默認值。

如果在列定義中沒有明確的DEFAULT值,則MySQL按照如下規則確定默認值:

如果列可以使用NULL作爲值,則使用DEFAULT NULL子句對列進行定義。(在MySQL的早期版本中也如此。)

如果列不能使用NULL作爲值,則MySQL對列進行定義時不使用DEFAULT子句。輸入數據時,如果INSERTREPLACE語句不包括列的值,則MySQL依據當時的有效的SQL模式操作列:

o        如果嚴格模式沒有被啓用,則MySQL會根據列數據類型,把列設置爲明確的默認值。

o        如果嚴格模式已被啓用,則事務表會出現錯誤,語句被回滾。對於非事務表,會出現錯誤,不過,如果錯誤出現在一個多行語句中的第二行或後續行,則以前的各行將被插入。

假設表t按下面的方法進行定義:

CREATE TABLE t (i INT NOT NULL);

在這種情況下,i沒有明確的默認值,所以在嚴格模式中,每個後續語句都會產生一個錯誤,並且沒有行被插入。當未使用嚴格模式時,只有第三個語句產生錯誤;明確的默認值被插入到前兩個語句中,但是第三個語句會出現錯誤,因爲DEFAULT(i)不會產生一個值:

INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));

5.3.2節,“SQL服務器模式”

對於一個給定的表,您可以使用SHOW CREATE TABLE語句來查看那些列有明確的DEFAULT子句。

·         對於列的評註可以使用COMMENT選項來進行指定。評註通過SHOW CREATE TABLESHOW FULL COLUMNS語句顯示。

·         屬性SERIAL可以用作BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的別名。

·         KEY通常是INDEX同義詞。如果關鍵字屬性PRIMARY KEY在列定義中已給定,則PRIMARY KEY也可以只指定爲KEY。這麼做的目的是與其它數據庫系統兼容。

·         UNIQUE索引中,所有的值必須互不相同。如果您在添加新行時使用的關鍵字與原有行的關鍵字相同,則會出現錯誤。例外情況是,如果索引中的一個列允許包含NULL值,則此列可以包含多個NULL值。此例外情況不適用於BDB表。在BDB中,帶索引的列只允許一個單一NULL

·         PRIMARY KEY是一個唯一KEY,此時,所有的關鍵字列必須定義爲NOT NULL。如果這些列沒有被明確地定義爲NOT NULLMySQL應隱含地定義這些列。一個表只有一個PRIMARY KEY。如果您沒有PRIMARY KEY並且一個應用程序要求在表中使用PRIMARY KEY,則MySQL返回第一個UNIQUE索引,此索引沒有作爲PRIMARY KEYNULL列。

·         在已創建的表中,PRIMARY KEY的位置最靠前,然後是所有的UNIQUE索引,然後是非唯一索引。這可以幫助MySQL優化程序選擇優先使用哪個索引,並且更快速的檢測出重複的UNIQUE關鍵字。

·         PRIMARY KEY可以是一個多列索引。但是,在列規約中使用PRIMARY KEY關鍵字屬性無法創建多列索引。這麼做只能把一個列標記爲主列。您必須使用一個單獨的PRIMARY KEYindex_col_name, ...)子句。

·         如果PRIMARY KEYUNIQUE索引只包括一個列,並且此列爲整數類型,則您也可以在SELECT語句中把此列作爲_rowid引用。

·         MySQL中,PRIMARY KEY的名稱爲PRIMARY。對於其它索引,如果您沒有賦予名稱,則索引被賦予的名稱與第一個已編入索引的列的名稱相同,並自選添加後綴(_2, _3,...),使名稱爲唯一名稱。您可以使用SHOW INDEX FROM tbl_name來查看錶的索引名稱。請參見13.5.4.11節,“SHOW INDEX語法”

·         部分存儲引擎允許您在創建索引時指定索引類型。index_type指示語句的語法是USING type_name

示例:

CREATE TABLE lookup
  (id INT, INDEX USING BTREE (id))
  ENGINE = MEMORY;

要了解有關USING的詳細說明,請參見13.1.4節,“CREATE INDEX語法”

要了解有關MySQL如何使用索引的更多信息,請參見7.4.5節,“MySQL如何使用索引”

·         MySQL 5.1中,只有MyISAMInnoDB, BDBMEMORY存儲引擎支持在含有NULL值的列中編索引。在其它情況下,您必須定義已編索引的列爲NOT NULL,否則會出現錯誤。

·         在一個索引規約中使用col_name(length)語法,您可以創建一個索引,此索引只使用一個CHARVARCHAR列的第一個length字符。只對列值的前綴編制索引可以使索引文件大大減小。請參見7.4.3節,“列索引”

MyISAMInnoDB存儲引擎也支持對BLOBTEXT列編索引。當對BLOBTEXT列編索引時,您必須爲索引指定一個前綴長度。例如:

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

對於MyISAMInnoDB表,前綴最長可以爲1000字節,對於其它表格類型,最長可以爲255字節。注意前綴長度限值以字節爲單位,而在CREATE TABLE語句中的前綴長度用字符數目來表述。當爲一個使用多字節字符集的列指定前綴長度時,一定要考慮到這一點。

·         一個index_col_name規約可以以ASCDESC結尾。這些關鍵詞可以在將來進行擴展,用於指定升序或降序的索引值存儲。當前,這些關鍵詞被分析但是被忽略;索引值均以升序儲存。

·         當您在SELECT中的TEXT列或BLOB列中使用ORDER BYGROUP BY時,服務器只使用初始的字節數目對值進行分類。字節數目由max_sort_length系統變量進行指示。請參見11.4.3節,“BLOB和TEXT類型

·         您可以創建特殊的FULLTEXT索引,用於全文搜索。只有MyISAM表類型支持FULLTEXT索引。FULLTEXT索引只可以從CHAR, VARCHARTEXT列中創建。整個列都會被編入索引;不支持對部分列編索引。如果已指定,前綴長度會被忽略。要了解運行的詳細說明,請參見12.7節,“全文搜索功能”

·         您可以爲空間列類型創建SPATIAL索引。只有MyISAM表支持空間類型,已編索引的列必須聲明爲NOT NULL。請參見第19章:MySQL中的空間擴展

·         InnoDB表支持對外鍵限制條件進行檢查。請參見15.2節,“InnoDB存儲引擎”。注意,在InnoDB中,FOREIGN KEY語法比本節開始時介紹的CREATE TABLE語句的語法更嚴格:被引用的表中的列必須有明確的命名。InnoDB支持外鍵的ON DELETEON UPDATE兩種操作。有關精確語法的說明,請參見15.2.6.4節,“FOREIGN KEY約束”

對於其它存儲引擎,MySQL服務器對CREATE TABLE語句中的FOREIGN KEYREFERENCES語法進行分析,但不採取進一步的行動。所有的存儲引擎均對CHECK子句進行分析,但是忽略CHECK子句。請參見1.8.5.5節,“外鍵”

·         對於MyISAM表,每個NULL列要多佔用一位,進位到距離最近的字節。最大記錄長度(以字節爲單位)按照如下方法計算:

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

對於採用靜態記錄格式的表,delete_flag1。靜態表在行記錄中使用一位用作位標記。位標記指示該行是否已被刪除。對於動態表,delete_flag0,因爲在動態行標題中已存儲了位標記。

這些計算方法不適用於InnoDB表。對於InnoDB表,NULL列的存儲量與NOT NULL列的存儲量沒有區別。

ENGINETYPE選項用於爲表指定存儲引擎。ENGINE是首選的選項名稱。

ENGINETYPE選項採用以下值:

存儲引擎

說明

ARCHIVE

檔案存儲引擎。請參見15.8節,“ARCHIVE存儲引擎”

BDB

帶頁面鎖定的事務安全表。也稱爲BerkeleyDB。請參見15.5節,“BDB (BerkeleyDB)存儲引擎”

CSV

值之間用逗號隔開的表。請參見15.9節,“CSV存儲引擎

EXAMPLE

示例引擎。請參見15.6節,“EXAMPLE存儲引擎”

FEDERATED

可以訪問遠程表的存儲引擎。請參見15.7節,“FEDERATED存儲引擎”

HEAP

15.4節,“MEMORY (HEAP)存儲引擎”

(OBSOLETE) ISAM

MySQL 5.1中沒有此引擎。如果您要從以前的版本升級到MySQL 5.1,您應該在進行升級前把原有的ISAM錶轉換爲MyISAM表。請參見第15章:存儲引擎和表類型

InnoDB

帶行鎖定和外鍵的事務安全表。請參見15.2節,“InnoDB存儲引擎”

MEMORY

本表類型的數據只保存在存儲器裏。(在早期MySQL版本中被稱爲HEAP。)

MERGE

MyISAM表的集合,作爲一個表使用。也稱爲MRG_MyISAM。請參見15.3節,“MERGE存儲引擎”

MyISAM

二進制輕便式存儲引擎,此引擎是MySQL所用的默認存儲引擎。請參見15.1節,“MyISAM存儲引擎”

NDBCLUSTER

成簇表,容錯表,以存儲器爲基礎的表。也稱爲NDB。請參見第17章:MySQL簇

要了解有關MySQL存儲引擎的更多信息,請參見第15章:存儲引擎和表類型

如果被指定的存儲引擎無法利用,則MySQL使用MyISAM代替。例如,一個表定義包括ENGINE=BDB選項,但是MySQL服務器不支持BDB表,則表被創建爲MyISAM表。這樣,如果您在主機上有事務表,但在從屬機上創建的是非交互式表(以加快速度)時,可以進行復制設置。在MySQL 5.1中,如果沒有遵守存儲引擎規約,則會出現警告。

其它表選項用於優化表的性質。在多數情況下,您不必指定表選項。這些選項適用於所有存儲引擎,另有說明除外:

·         AUTO_INCREMENT

表的初始AUTO_INCREMENT值。在MySQL 5.1中,本選項只適用於MyISAMMEMORY表。InnoDB也支持本選項。如果引擎不支持AUTO_INCREMENT表選項,則要設置引擎的第一個auto-increment值,需插入一個“假”行。該行的值比創建表後的值小一,然後刪除該假行。

對於在CREATE TABLE語句中支持AUTO_INCREMENT表選項的引擎,您也可以使用ALTER TABLE tbl_name AUTO_INCREMENT = n來重新設置AUTO_INCREMENT值。

·         AVG_ROW_LENGTH

表中平均行長度的近似值。只需要對含尺寸可變的記錄的大型表進行此項設置。

當創建一個MyISAM表時,MySQL使用MAX_ROWSAVG_ROW_LENGTH選項的乘積來確定得出的表有多大。如果有一個選項未指定,則表的最大尺寸爲65,536TB數據。(如果操作系統不支持這麼大的文件,則表的尺寸被限定在操作系統的限值處。)如果您想縮小指針尺寸使索引更小,速度更快,並且您不需要大文件,則您可以通過設置myisam_data_pointer_size系統變量來減少默認指針的尺寸。(見5.3.3節,“服務器系統變量”。)如果您希望所有的表可以擴大,超過默認限值,並且願意讓表稍微慢點,並稍微大點,則您可以通過設置此變量增加默認指針的尺寸。

·         [DEFAULT] CHARACTER SET

用於爲表指定一個默認字符集。CHARSETCHARACTER SET的同義詞。

對於CHARACTER SET.

·         COLLATE

用於爲表指定一個默認整序。

·         CHECKSUM

如果您希望MySQL隨時對所有行進行實時檢驗求和(也就是,表變更後,MySQL自動更新檢驗求和),則應把此項設置爲1。這樣做,表的更新速度會略微慢些,但是更容易尋找到受損的表。CHECKSUM TABLE語句用於報告檢驗求和(僅限於MyISAM)。

·         COMMENT

表的註釋,最長60個字符。

·         CONNECTION

FEDERATED表的連接字符串。( 註釋:較早版本的MySQL使用COMMENT選項用於連接字符串。

·         MAX_ROWS

您打算儲存在表中的行數目的最大值。這不是一個硬性限值,而更像一個指示語句,指示出表必須能存儲至少這麼多行。

·         MIN_ROWS

您打算存儲在表中的行數目的最小值。

·         PACK_KEYS

如果您希望索引更小,則把此選項設置爲1。這樣做通常使更新速度變慢,同時閱讀速度加快。把選項設置爲0可以取消所有的關鍵字壓縮。把此選項設置爲DEFAULT時,存儲引擎只壓縮長的CHARVARCHAR列(僅限於MyISAM)。

如果您不使用PACK_KEYS,則默認操作是隻壓縮字符串,但不壓縮數字。如果您使用PACK_KEYS=1,則對數字也進行壓縮。

在對二進制數字關鍵字進行壓縮時,MySQL採用前綴壓縮:

o        每個關鍵字需要一個額外的字節來指示前一個關鍵字中有多少字節與下一個關鍵字相同。

o        指向行的指針以高位字節優先的順序存儲在關鍵字的後面,用於改進壓縮效果。

這意味着,如果兩個連續行中有許多相同的關鍵字,則後續的“相同”的關鍵字通常只佔用兩個字節(包括指向行的指針)。與此相比,常規情況下,後續的關鍵字佔用storage_size_for_key + pointer_size(指針尺寸通常爲4)。但是,只有在許多數字相同的情況下,前綴壓縮纔有好處。如果所有的關鍵字完全不同,並且關鍵字不能含有NULL值,則每個關鍵字要多使用一個字節。(在這種情況中,儲存壓縮後的關鍵字的長度的字節與用於標記關鍵字是否爲NULL的字節是同一字節。)

·         PASSWORD

使用密碼對.frm文件加密。在標準MySQL版本中,本選項不起任何作用。

·         DELAY_KEY_WRITE

如果您想要延遲對關鍵字的更新,等到表關閉後再更新,則把此項設置爲1(僅限於MyISAM)。

·         ROW_FORMAT

定義各行應如何儲存。當前,此選項只適用於MyISAM表。對於靜態行或長度可變行,此選項值可以爲FIXEDDYNAMICmyisampack用於把類型設置爲COMPRESSED。請參見15.1.3節,“MyISAM表的存儲格式”

在默認情況下,InnoDB記錄以壓縮格式存儲(ROW_FORMAT=COMPACT)。通過指定ROW_FORMAT=REDUNDANT,仍然可以申請用於較早版本的MySQL中的非壓縮格式。

·         RAID_TYPE

MySQL 5.0,RAID支持被刪除了。要了解有關RAID的說明,請參見http://dev.mysql.com/doc/refman/4.1/en/create-table.html

·         UNION

當您想要把一組相同的表當作一個表使用時,採用UNIONUNION僅適用於MERGE表。請參見15.3節,“MERGE存儲引擎”

對於您映射到一個MERGE表上的表,您必須擁有SELECT, UPDATEDELETE權限。(註釋:以前,所有被使用的表必須位於同一個數據庫中,並作爲MERGE表。這些限制不再適用。)

·         INSERT_METHOD

如果您希望在MERGE表中插入數據,您必須用INSERT_METHOD指定應插入行的表。INSERT_METHOD選項僅用於MERGE表。使用FIRSTLAST把行插入到第一個或最後一個表中;或者使用NO,阻止插入行。請參見15.3節,“MERGE存儲引擎”

·         DATA DIRECTORY, INDEX DIRECTORY

通過使用DATA DIRECTORY='directory'INDEX DIRECTORY='directory',您可以指定MyISAM存儲引擎放置表格數據文件和索引文件的位置。注意,目錄應是通向目錄的完整路徑(不是相對路徑)。

僅當您沒有使用--skip-symbolic-links選項時,DATA DIRECTORY, INDEX DIRECTORY才能使用。操作系統必須有一個正在工作的、線程安全的realpath()調用。要了解全面信息,請參見7.6.1.2節,“在Unix平臺上使用表的符號鏈接”。

·         對於用CREATE TABLE創建的表,可以使用partition_options控制分區。如果使用了partition_options,則其中必須包含至少一個PARTITION BY子句。本子句包含用於確定分區的函數;該函數會返回一個整值,範圍從1num。此處num爲分區的數目。此函數中可以使用的選項顯示在下面的清單中。 要點:在本節開始時介紹的用於partition_options的語法中顯示的選項,並不是都能用於所有分區類型。要了解各種類型具體的信息 ,請參見以下各類型的清單。要了解有關在MySQL中的分區的操作和使用情況的全面說明,以及要了解表創建的示例和與MySQL分區有關的其它命令,請參見第18章:分區

o        HASHexpr):用於混編一個或多個列,創建一個關鍵字,用於放置行,並確定行的位置。expr是一個表達式,使用一個或多個表中的列。該表達式可以是任何能夠生成單一整值的合法的MySQL表達式(包括MySQL函數)。例如,這些都是有效的CREATE TABLE語句,語句中使用了PARTITION BY HASH

o                     CREATE TABLE t1 (col1 INT, col2 CHAR(5)) 
o                         PARTITION BY HASH(col1);
o                      
o                     CREATE TABLE t1 (col1 INT, col2 CHAR(5))
o                         PARTITION BY HASH( ORD(col2) );
o                      
o                     CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME)
o                         PARTITION BY HASH ( YEAR(col3) );

VALUES LESS THANVALUES IN子句不能和PARTITION BY HASH一起使用。

PARTITION BY HASH使用expr被分區數目所除後的餘數(也就是模數)。要了解示例和其它信息,請參見18.2.3節,“HASH分區”

LENEAR關鍵詞需要一種不同的算法。在這種情況下,通過一次或多次邏輯AND運算得出的結果,計算出存儲記錄的分區的數目。要了解線形混編的討論和示例,請參見18.2.3.1節,“LINEAR HASH分區”

o        KEY(column_list):與HASH近似,除了有一點不一樣,即MySQL提供了混編函數,以保證均勻的數據分佈。column_list自變量只是各列的一個清單。本示例顯示了由關鍵字進行分區的一個簡單的表,分爲4個分區:

o                     CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
o                         PARTITION BY KEY(col3)
o                         PARTITIONS 4;

採用LINEAR關鍵詞,您可以對由關鍵字分區的表進行線形分區。這與由HASH進行分區的表格有同樣的效果;也就是說,使用&操作符查找分區數目,而不是使用模數(詳細說明見18.2.3.1節,“LINEAR HASH分區”18.2.4節,“KEY分區”)。本示例採用了關鍵字線形分區,用來在5個分區之間分配數據:

CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
    PARTITION BY LINEAR KEY(col3)
    PARTITIONS 5;

VALUES LESS THANVALUES IN子句不能和PARTITION BY KEY一起使用。

o        RANGE:在此情況下,expr使用一套VALUES LESS THAN操作符顯示了某一範圍內的值。當使用範圍分區時,您必須使用VALUES LESS THAN定義至少一個分區。VALUES IN不能和範圍分區一起使用。

VALUES LESS THAN可以與一個文字值同時使用,或者與一個可以求算單一值的表達式同時使用。

舉例說明,假設您有一個表,您希望採用以下方法對包含年份值的一列進行分區:

分區編號:

年份範圍:

0

1990以前

1

1991 - 1994

2

1995 - 1998

3

1999 - 2002

4

2003 - 2005

5

2006年以後

採用這種分區方法的表可以通過如下CREATE TABLE語句實現:

CREATE TABLE t1 (
    year_col INT, 
    some_data INT 
) 
PARTITION BY RANGE (year_col) (
    PARTITION p0 VALUES LESS THAN (1991),
    PARTITION p1 VALUES LESS THAN (1995),
    PARTITION p2 VALUES LESS THAN (1999),
    PARTITION p3 VALUES LESS THAN (2002),
    PARTITION p4 VALUES LESS THAN (2006),
    PARTITION p5 VALUES LESS THAN MAXVALUE
);

PARTITION ... VALUES LESS THAN ...語句按順序執行。VALUES LESS THAN MAXVALUE的作用是指定大於最大值的“其餘”的值。

注意,VALUES LESS THAN子句按順序執行,執行方式類似於switch ... case語段的一部分(許多編程語言,如C, JavaPHP也如此)。也就是說,子句必須按照這樣一種方法排列,每一個後續的VALUES LESS THAN中指定的上限值大於前一個VALUES LESS THAN中指定的上限值,並在清單的最後加一個參照性的MAXVALUE

VALUES IN與一系列的值同時使用。舉例說明,您可以創建如下的分區方法:

CREATE TABLE client_firms (
    id INT,
    name VARCHAR(35)
)
PARTITION BY RANGE (id) (
    PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
    PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
    PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
    PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
);

當前,與VALUES IN...同時使用的值必須只包含整數值。

(因爲此表只使用VALUES IN表達式進行分區,您也可以用PARTITION BY LIST代替,而不是使用PARTITION BY RANGE。請參見下一條。)

在使用VALUES LESS THANVALUES IN情況下,每個分區使用PARTITION name定義,此處name是分區的標識名,後面接VALUES...子句。

o        LIST(expr):當根據含有一系列限定性值(例如州代碼或國家代碼)的列進行分區時使用。在這種情況下,所有與特定的州或國家有關的記錄都被分配到一個單一分區中,或者可以預留出一個分區,用於一系列特定的州或國家。LIST(expr)RANGE類似,除了一點以外,即只有VALUES IN可以被用於爲每個分區指定值。

當使用清單分區時,您必須使用VALUES IN定義至少一個分區。VALUES LESS THAN不能與PARTITION BY LIST一起使用。

o        分區數目可以使用PARTITION num子句,自選進行指定,此處,num是分區的數目。如果本子句和其它PARTITION子句同時使用,則num必須與使用PARTITION子句說明的分區的總數相等。

註釋:不論您在創建一個由RANGELIST進行分區的表時是否使用了PARTITIONS子句,您必須在表定義中包括至少一個PARTITION VALUES(見後)。

o        一個分區可以自選分隔成多個子分區。使用自選的SUBPARTITION BY子句可以指示。子分區可以由HASHKEY進行分隔。兩種方法建立的子分區均爲LINEAR。分隔子分區時的操作方式與以前描述的分區類型的操作方式一樣。(無法由LISTRANGE進行子分區分隔。)

使用SUBPARTITIONS關鍵詞,後面接一個整值,可以對子分區的數目進行指示。

·         使用一個partition_definition子句可以對每個分區分別進行定義。下面是組成這個子句的各個部分:

o        PARTITION partition_name:用於爲分區指定一個邏輯名稱。

o        VALUE子句:對於範圍分區,每個分區必須包括一個VALUES LESS THAN子句;對於清單分區,您必須爲每個分區指定一個VALUES IN子句。本子句用於確定哪些行將被存儲到此分區中。要了解語法示例,請參見第18章:分區中對分區類型的討論。

o        自選的COMMENT子句可以用於描述分區。註釋必須加單引號。舉例說明:

o                     COMMENT = 'Data for the years previous to 1999'

o        DATA DIRECTORYINDEX DIRECTORY可以被用於指示本分區的數據和索引各自的存儲位置的目錄。data_dirindex_dir都必須是絕對系統路徑。例如:

o                     CREATE TABLE th (id INT, name VARCHAR(30), adate DATE)
o                     PARTITION BY LIST(YEAR(adate))
o                     (
o                         PARTITION p1999 VALUES IN (1995, 1999, 2003) DATA DIRECTORY = '/var/appdata/95/data' INDEX DIRECTORY = '/var/appdata/95/idx',
o                         PARTITION p2000 VALUES IN (1996, 2000, 2004) DATA DIRECTORY = '/var/appdata/96/data' INDEX DIRECTORY = '/var/appdata/96/idx',
o                         PARTITION p2001 VALUES IN (1997, 2001, 2005) DATA DIRECTORY = '/var/appdata/97/data' INDEX DIRECTORY = '/var/appdata/97/idx',
o                         PARTITION p2000 VALUES IN (1998, 2002, 2006) DATA DIRECTORY = '/var/appdata/98/data' INDEX DIRECTORY = '/var/appdata/98/idx'
);

DATA DIRECTORYINDEX DIRECTORY的操作方法與CREATE TABLE語句中的table_option子句的操作方法一樣。此table_option子句用於位於MyISAM表管理程序下的各表。

可以爲每個分區指定一個數據目錄和一個索引目錄。如果不指定,則數據和索引被存儲在默認的MySQL數據目錄中。

o        MAX_ROWSMIN_ROWS分別用於將被存儲在分區中的行數目最大值和行數目最小值。max_number_of_rowsmin_number_of_rows的值必須爲正整數。和具有同樣名稱的桌面選項一樣,max_number_of_rowsmin_number_of_rows只作爲對服務器的“建議”值,並不是硬性限值。

o        自選的TABLESPACE子句可以用於爲分區指定一個桌面空間。僅用於MySQL Cluster

o        自選的[STORAGE] ENGINE子句可以把本分區中表的類型改爲指定的類型。表的類型可以是本MySQL服務器支持的所有類型。STORAGE關鍵字和等號(=)均爲自選項。如果沒有使用此選項設置分區存儲引擎,則適用於整個表的引擎可以用於此分區。

註釋:分區管理程序對於PARTITIONSUBPARTITION均接受[STORAGE] ENGINE選項。目前,此子句的使用方式僅限於對所有的分區或子分區設置同一個存儲引擎,如果試圖在同一個表內對不同的分區或子分區設置不同的存儲引擎,則會出現錯誤ERROR 1469 (HY000):在本版本的MySQL中,不允許在各分區中混用管理程序。我們打算在將來的MySQL 5.1版本中加入這種對分區的限定。

o        NODEGROUP選項可以用於使本分區可以作爲節點組的一部分,節點組使用node_group_id識別。本選項僅適用於MySQL Cluster

o        分區定義可以自選地包含一個或多個subpartition_definition子句。每個這種子句至少包括SUBPARTITION name,此處,name是子分區的識別名稱。除了用SUBPARTITION代替PARTITION關鍵詞外,用於子分區定義的語法與用於分區定義的語法一樣。

子分區必須由HASHKEY完成,並且只能對RANGELIST分區進行子分區。請參見18.2.5節,“子分區”

·         分區可以修改、合併、添加到表中,或從表中刪去。要了解有關完成這些任務的MySQL命令的基本說明,請參見13.1.2節,“ALTER TABLE語法”。要了解詳細的說明和示例,請參見18.3節,“分區管理”

您可以在CREATE TABLE語句的末尾添加一個SELECT語句,在一個表的基礎上創建表。

CREATE TABLE new_tbl SELECT * FROM orig_tbl;

MySQL會對SELECT中的所有項創建新列。舉例說明:

mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
    ->        PRIMARY KEY (a), KEY(b))
    ->        TYPE=MyISAM SELECT b,c FROM test2;

本語句用於創建含三個列(a, b, c)的MyISAM表。注意,用SELECT語句創建的列附在表的右側,而不是覆蓋在表上。參考以下示例:

mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+
 
mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0
 
mysql> SELECT * FROM bar;
+------+---+
| m    | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)

對應於表foo中的每一行,在表bar中插入一行,含有表foo中的值以及新列中的默認值。

在由CREATE TABLE...SELECT生成的表中,只在CREATE TABLE部分中命名的列首先出現。在兩個部分中都命名的列和只在SELECT部分中命名的列隨後出現。也可以通過指定CREATE TABLE部分中的列覆蓋SELECT列中的數據類型。

如果在把數據複製到表中時出現錯誤,則表會自動被取消,不會被創建。

CREATE TABLE...SELECT不會自動創建任何索引。索引需要專門創建,以便使語句的靈活性更強。如果您希望爲已創建的表建立索引,您應在SELECT語句前指定索引。

mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;

列的類型會發生部分轉化。例如,AUTO_INCREAMENT屬性不會被保留,VARCHAR列會變成CHAR列。

當使用CREATE...SELECT創建表時,在查詢時一定要對功能調用和表達式起別名。如果不起別名,則CREATE語句會出現錯誤或者生成不符合需要的列名稱。

CREATE TABLE artists_and_works
SELECT artist.name, COUNT(work.artist_id) AS number_of_works
FROM artist LEFT JOIN work ON artist.id = work.artist_id
GROUP BY artist.id;

您也可以明確地爲一個已生成的列指定類型:

CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;

根據其它表的定義(包括在原表中定義的所有的列屬性和索引),使用LIKE創建一個空表:

CREATE TABLE new_tbl LIKE orig_tbl;

CREATE TABLE...LIKE不會複製對原表或外鍵定義指定的DATA DIRECTORYINDEX DIRECTORY表選項。

您可以在SELECT前增加IGNOREREPLACE,指示如何對複製唯一關鍵字值的記錄進行操縱。使用IGNORE後,如果新記錄複製了原有的唯一關鍵字值的記錄,則新記錄被丟棄。使用REPLACE後,新記錄替換具有相同的唯一關鍵字值的記錄。如果沒有指定IGNOREREPLACE,則出現多重唯一關鍵字值時會導致發生錯誤。

爲了確保更新日誌/二進位日誌可以被用於再次創建原表,MySQL不允許在CREATE TABLE...SELECT過程中進行聯合插入。

13.1.5.1. 沉寂的列規格變更

在有些情況下,較早版本的MySQL會靜默地更改在CREATE TABLEALTER TABLE語句中給定的列規約。在MySQL 5.1中不會進行這類變更。如果使用指定的數據類型無法創建列,則會出現錯誤。

13.1.6. DROP DATABASE語法

DROP {DATABASE | SCHEMA} [IF EXISTS] db_name

DROP DATABASE用於取消數據庫中的所用表格和取消數據庫。使用此語句時要非常小心!如果要使用DROP DATABASE,您需要獲得數據庫DROP權限。

IF EXISTS用於防止當數據庫不存在時發生錯誤。

也可以使用DROP SCHEMA

如果您對一個帶有符號鏈接的數據庫使用DROP DATABASE,則鏈接和原數據庫都被取消。

DROP DATABASE會返回已被取消的表的數目。此數目相當於被取消的.frm文件的數目。

在正常操作中MySQL自身會創建出一些文件和目錄。DROP DATABASE語句會從給定的數據庫目錄中取消這些文件和目錄:

·         所有帶這些擴展名的文件:

.BAK

.DAT

.HSH

 

.MRG

.MYD

.ISD

 

.MYI

.db

.frm

 

·         名稱中包含兩位16進制數00-ff的所有子目錄。這些子目錄用於RAID表。(當對RAID表的支持被取消時,在MySQL 5.0中,這些目錄不會被取消。您應該在升級到MySQL 5.0或更新的版本前轉化原有的RAID表,並人工取消這些目錄。請參見MySQL 5.0參考手冊中有關從較早版本升級到MySQL 5.0的章節。MySQL 5.0參考手冊可以從MySQL網站中獲取。)

·         db.opt文件

如果在MySQL取消了上述這些文件之後,在數據庫目錄中仍保留有其它文件和目錄,則數據庫目錄不能被取消。在這種情況下,您必須人工取消所有保留下的文件或目錄,並再次發送DROP DATABASE語句。

您還可以使用mysqladmin來取消文件。請參見8.5節,“mysqladmin:用於管理MySQL服務器的客戶端”

13.1.7. DROP INDEX語法

DROP INDEX index_name ON tbl_name

DROP INDEX用於從表tbl_name中取消名稱爲index_name的索引。本語句被映射到一個ALTER TABLE語句中,用於取消索引。請參見13.1.2節,“ALTER TABLE語法”

13.1.8. DROP TABLE語法

DROP [TEMPORARY] TABLE [IF EXISTS]
    tbl_name [, tbl_name] ...
    [RESTRICT | CASCADE]

DROP TABLE用於取消一個或多個表。您必須有每個表的DROP權限。所有的表數據和表定義會被取消,所以使用本語句要小心!

注意,對於一個帶分區的表,DROP TABLE會永久性地取消表定義,取消各分區,並取消儲存在這些分區中的所有數據。DROP TABLE還會取消與被取消的表有關聯的分區定義(.par)文件。

對與不存在的表,使用IF EXISTS用於防止錯誤發生。當使用IF EXISTS時,對於每個不存在的表,會生成一個NOTE。請參見13.5.4.22節,“SHOW WARNINGS語法”

RESTRICTCASCADE可以使分區更容易。目前,RESTRICTCASCADE不起作用。

註釋:除非您使用TEMPORARY關鍵詞,DROP TABLE會自動提交當前的有效的事務。

TEMPORARY關鍵詞具有以下作用:

·         語句只取消TEMPORARY表。

·         語句不會終止正在進行中的事務。

·         不會查驗存取權。(TEMPORARY表僅對於創建該表的客戶端是可見的,所以查驗是不必要的。)

使用TEMPORARY是確保您不會意外取消一個非TEMPORARY表的良好方法。

13.1.9. RENAME TABLE語法

RENAME TABLE tbl_name TO new_tbl_name
    [, tbl_name2 TO new_tbl_name2] ...

本語句用於對一個或多個表進行重命名。

重命名操作自動進行,這意味着當重命名正在運行時,其它線程不能讀取任何表。例如,如果您有一個原有的表old_table,您可以創建另一個具有相同結構的空表new_table,然後用此空表替換原有的表:

CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;

如果此語句用於對多個表進行重命名,則重命名操作從左至右進行。如果您想要交換兩個表的名稱,您可以這樣做(假設不存在名稱爲tmp_table的表):

RENAME TABLE old_table TO tmp_table,
             new_table TO old_table,
             tmp_table TO new_table;

只要兩個數據庫位於同一文件系統中,您還可以對錶進行重命名,把表從一個數據庫中移動到另一個數據庫中:

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

當您執行RENAME時,您不能有被鎖定的表,也不能有處於活性狀態的事務。您還必須擁有原表的ALTERDROP權限,以及新表的CREATEINSERT權限。

如果MySQL對多個表進行重命名時遇到了錯誤,MySQL會對所有已被重命名的表進行反向重命名,返回到原來的狀態。

只要您不嘗試通過重命名把視圖加入另一個數據庫中,則RENAME TABLE也可以用於視圖。

13.2. 數據操作語句

13.2.1. DELETE語法

單表語法:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT row_count]

多表語法:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    tbl_name[.*] [, tbl_name[.*] ...]
    FROM table_references
    [WHERE where_definition]

或:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    FROM tbl_name[.*] [, tbl_name[.*] ...]
    USING table_references
    [WHERE where_definition]

tbl_name中有些行滿足由where_definition給定的條件。DELETE用於刪除這些行,並返回被刪除的記錄的數目。

如果您編寫的DELETE語句中沒有WHERE子句,則所有的行都被刪除。當您不想知道被刪除的行的數目時,有一個更快的方法,即使用TRUNCATE TABLE。請參見13.2.9節,“TRUNCATE語法”

如果您刪除的行中包括用於AUTO_INCREMENT列的最大值,則該值被重新用於BDB表,但是不會被用於MyISAM表或InnoDB表。如果您在AUTOCOMMIT模式下使用DELETE FROM tbl_name(不含WHERE子句)刪除表中的所有行,則對於所有的表類型(除InnoDBMyISAM外),序列重新編排。對於InnoDB表,此項操作有一些例外,在15.2.6.3節,“AUTO_INCREMENT列如何在InnoDB中運行”中進行了討論。

對於MyISAMBDB表,您可以把AUTO_INCREMENT次級列指定到一個多列關鍵字中。在這種情況下,從序列的頂端被刪除的值被再次使用,甚至對於MyISAM表也如此。請參見3.6.9節,“使用AUTO_INCREMENT”

DELETE語句支持以下修飾符:

·         如果您指定LOW_PRIORITY,則DELETE的執行被延遲,直到沒有其它客戶端讀取本表時再執行。

·         對於MyISAM表,如果您使用QUICK關鍵詞,則在刪除過程中,存儲引擎不會合並索引端結點,這樣可以加快部分種類的刪除操作的速度。

·         在刪除行的過程中,IGNORE關鍵詞會使MySQL忽略所有的錯誤。(在分析階段遇到的錯誤會以常規方式處理。)由於使用本選項而被忽略的錯誤會作爲警告返回。

刪除操作的速度會受到一些因素的影響,這些因素在7.2.18節,“DELETE語句的速度”中進行了討論。

MyISAM表中,被刪除的記錄被保留在一個帶鏈接的清單中,後續的INSERT操作會重新使用舊的記錄位置。要重新使用未使用的空間並減小文件的尺寸,則使用OPTIMIZE TABLE語句或myisamchk應用程序重新編排表。OPTIMIZE TABLE更簡便,但是myisamchk速度更快。請參見13.5.2.5節,“OPTIMIZE TABLE語法”第7章:優化

QUICK修飾符會影響到在刪除操作中索引端結點是否合併。當用於被刪除的行的索引值被來自後插入的行的相近的索引值代替時,DELETE QUICK最爲適用。在此情況下,被刪除的值留下來的空穴被重新使用。

未充滿的索引塊跨越某一個範圍的索引值,會再次發生新的插入。當被刪除的值導致出現未充滿的索引塊時,DELETE QUICK沒有作用。在此情況下,使用QUICK會導致未利用的索引中出現廢棄空間。下面是此種情況的舉例說明:

1.    創建一個表,表中包含已編索引的AUTO_INCREMENT列。

2.    在表中插入很多記錄。每次插入會產生一個索引值,此索引值被添加到索引的高端處。

3.    使用DELETE QUICK從列的低端處刪除一組記錄。

在此情況下,與被刪除的索引值相關的索引塊變成未充滿的狀態,但是,由於使用了QUICK,這些索引塊不會與其它索引塊合併。當插入新值時,這些索引塊仍爲未充滿的狀態,原因是新記錄不含有在被刪除的範圍內的索引值。另外,即使您此後使用DELETE時不包含QUICK,這些索引塊也仍是未充滿的,除非被刪除的索引值中有一部分碰巧位於這些未充滿的塊的之中,或與這些塊相鄰。在這些情況下,如果要重新利用未使用的索引空間,需使用OPTIMIZE TABLE

如果您打算從一個表中刪除許多行,使用DELETE QUICK再加上OPTIMIZE TABLE可以加快速度。這樣做可以重新建立索引,而不是進行大量的索引塊合併操作。

用於DELETEMySQL唯一的LIMIT row_count選項用於告知服務器在控制命令被返回到客戶端前被刪除的行的最大值。本選項用於確保一個DELETE語句不會佔用過多的時間。您可以只重複DELETE語句,直到相關行的數目少於LIMIT值爲止。

如果DELETE語句包括一個ORDER BY子句,則各行按照子句中指定的順序進行刪除。此子句只在與LIMIT聯用是才起作用。例如,以下子句用於查找與WHERE子句對應的行,使用timestamp_column進行分類,並刪除第一(最舊的)行:

DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp_column
LIMIT 1;

您可以在一個DELETE語句中指定多個表,根據多個表中的特定條件,從一個表或多個表中刪除行。不過,您不能在一個多表DELETE語句中使用ORDER BYLIMIT

table_references部分列出了包含在聯合中的表。此語法在13.2.7.1節,“JOIN語法”中進行了說明。

對於第一個語法,只刪除列於FROM子句之前的表中的對應的行。對於第二個語法,只刪除列於FROM子句之中(在USING子句之前)的表中的對應的行。作用是,您可以同時刪除許多個表中的行,並使用其它的表進行搜索:

DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

或:

DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

當搜索待刪除的行時,這些語句使用所有三個表,但是隻從表t1和表t2中刪除對應的行。

以上例子顯示了使用逗號操作符的內部聯合,但是多表DELETE語句可以使用SELECT語句中允許的所有類型的聯合,比如LEFT JOIN

本語法允許在名稱後面加.*,以便與Access相容。

如果您使用的多表DELETE語句包括InnoDB表,並且這些表受外鍵的限制,則MySQL優化程序會對錶進行處理,改變原來的從屬關係。在這種情況下,該語句出現錯誤並返回到前面的步驟。要避免此錯誤,您應該從單一表中刪除,並依靠InnoDB提供的ON DELETE功能,對其它表進行相應的修改。

註釋:當引用表名稱時,您必須使用別名(如果已給定):

DELETE t1 FROM test AS t1, test2 WHERE ...

進行多表刪除時支持跨數據庫刪除,但是在此情況下,您在引用表時不能使用別名。舉例說明:

DELETE test1.tmp1, test2.tmp2 FROM test1.tmp1, test2.tmp2 WHERE ...

目前,您不能從一個表中刪除,同時又在子查詢中從同一個表中選擇。

13.2.2. DO語法

DO expr [, expr] ...
DO用於執行表達式,但是不返回任何結果。DOSELECT expr的簡化表達方式DO有一個優勢,就是如果您不太關心結果的話,DO的速度稍快。

DO主要用於執行有副作用的函數,比如RELEASE_LOCK()

13.2.3. HANDLER語法

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE

HANDLER語句提供通往表存儲引擎接口的直接通道。HANDLER可以用於MyISAMInnoDB表。

HANDLER...OPEN語句用於打開一個表,通過後續的HANDLER...READ語句建立讀取表的通道。本表目標不會被其它線程共享,也不會關閉,直到線程調用HANDLER...CLOSE或線程中止時爲止。如果您使用一個別名打開表,則使用其它HANDLER語句進一步參閱表是必須使用此別名,而不能使用表名。

如果被指定的索引滿足給定的值並且符合了WHERE條件,則第一個HANDLER...READ語法取出一行。如果您有一個多列索引,則指定索引列值爲一個用逗號隔開的清單。既可以爲索引中的所有列指定值,也可以爲索引列的最左邊的前綴指定值。假設一個索引包括三個列,名稱爲col_a, col_b,col_c,並按此順序排列。HANDLER語句可以爲索引中的所有三個列指定值,或者爲一個最左邊前綴中的各列指定值。舉例說明:

HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ...
HANDLER ... index_name = (col_a_val,col_b_val) ...
HANDLER ... index_name = (col_a_val) ...

第二個HANDLER...READ語法按索引的順序從表中取出一行。索引的順序符合WHERE條件。

第三個HANDLER...READ語法按自然行的順序從表中取出一行。自然行的順序符合WHERE條件。當想要對整個表進行掃描時,此語句比HANDLER tbl_name READ index_name更快。自然行的順序指的是行存儲在MyISAM表數據文件的順序。本語句也適用於InnoDB表,但是因爲沒有獨立的數據文件,所以沒有這類概念。

不使用LIMIT子句時,所有形式的HANDLER...READ語句均只取出一行。 如果要返回多個行,應加入一個LIMIT子句。本語句於SELECT語句的語法一樣。請參見13.2.7節,“SELECT語法”

HANDLER...CLOSE用於關閉使用HANDLER...OPEN打開的表。

註釋:要使用HANDLER接口來查閱一個表的PRIMARY KEY,應使用帶引號的識別符`PRIMARY`

HANDLER tbl_name READ `PRIMARY` > (...);

HANDLER是比較低級別的語句。例如,它不能提供一致性。也就是說,HANDLER...OPEN不能爲表做快照,也不能鎖定表。這意味着,當一個HANDLER...OPEN語句被編寫後,表數據可以被更改(用此線程或用其它線程),並且這些更改只會部分地出現在HANDLER...NEXTHANDLER...PREV掃描中。

使用HANDLER接口代替常規的SELECT語句有多個原因:

·         HANDLERSELECT更快:

o        一個指定的存儲引擎管理程序目標爲了HANDLER...OPEN進行整序。該目標被重新用於該表的後續的HANDLER語句;不需要對每個語句進行重新初始化。

o        涉及的分析較少。

o        沒有優化程序或查詢校驗開銷。

o        在兩個管理程序請求之間,不需要鎖定表。

o        管理程序接口不需要提供外觀一致的數據(例如,允許無條理的讀取),所以存儲引擎可以使用優化,而SELECT通常不允許使用優化。

·         有些應用程序使用與ISAM近似的接口與MySQL連接。使用HANDLER可以更容易地與這些應用程序連接。

·         HANDLER允許您採用一種特殊的方式進出數據庫。而使用SELECT時難以採用(或不可能採用)這種方式。有些應用程序可以提供一個交互式的用戶接口與數據庫連接。當與這些應用程序同時使用時,用HANDLER接口觀看數據更加自然。

13.2.4. INSERT語法

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

或:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

或:

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

INSERT用於向一個已有的表中插入新行。INSERT...VALUESINSERT...SET形式的語句根據明確指定的值插入行。INSERT...SELECT形式的語句插入從其它表中選出的行。在13.2.4.1節,“INSERT ... SELECT語法”中對INSERT...SELECT進行了進一步的討論。

行應被插入到tbl_name表中。可以按以下方法指定列。本語句向這些列提供值。

·         列名稱清單或SET子句明確的指示了列。

·         如果您不爲INSERT...VALUESINSERT...SELECT指定列的清單,則表中每列的值必須在VALUES清單中提供,或由SELECT提供。如果您不知道表中各列的順序,則使用DESCRIBE tbl_name查詢。

列值可以採用多種方法給定:

·         如果不是在嚴格模式下運行,則所有沒有明確給定值的列都被設置爲默認值(明確的或隱含的)。例如,如果您指定了一個列清單,但此清單沒有對錶中所有的列進行命名,則未命名的各列被設置爲默認值。默認值的賦值在13.1.5節,“CREATE TABLE語法”中進行了說明。也可參見1.8.6.2節,“對無效數據的約束”

有時候,您需要對所有沒有默認值的列明確地指定值。如果您希望,在沒有明確指定值時,INSERT語句可以生成錯誤信息,則您應該使用STRICT模式。請參見5.3.2節,“SQL服務器模式”

·         使用關鍵詞DEFAULT,明確地把列設置爲默認值。這樣,編寫向所有列賦值的INSERT語句時可以更容易,因爲使用DEFAULT可以避免編寫出不完整的、未包含全部列值的VALUES清單。如果不使用DEFUALT,您必須編寫一個列名稱清單,與VALUES清單中的每個值對應。

您還可以使用DEFAULT(col_name)作爲一種更通用的形式,在表達式中使用,用於生成一個列的默認值。

·         如果列清單和VALUES清單均爲空清單,則INSERT會創建一個行,每個列都被設置爲默認值:

·                mysql> INSERT INTO tbl_name () VALUES();

STRICT模式中,如果有一列沒有默認值,則會出現錯誤。或者,MySQL會對所有沒有明確定義默認值的列使用隱含的默認值。

·         您可以指定一個表達式expr來提供一個列值。如果表達式的類型與列值不匹配,這樣做會造成類型轉化。並且,給定值的轉化會導致不同的插入值,插入何值由列類型而定。例如,向一個INT, FLOAT, DECIMAL(10,6)YEAR列插入字符串'1999.0e-2',插入值分別是199919.992119.9921001999。存儲在INTYEAR列中的值爲1999的原因是,在從字符串到整數的轉化中,只把字符串的前面部分看作有效的整數或年份。對於浮點列和固定點列,在從字符串到浮點的轉化中,把整個字符串均看作有效的浮點值。

表達式expr可以引用在值清單中已設置的所有列。例如,您可以這麼操作,因爲用於col2的值引用了col1,而col1已經被賦值:

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

但是以下語句不合法,因爲用於col1的值引用了col2,而col2col1之後被賦值:

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

有一種例外情況,那就是含有AUTO_INCREMENT值的列。因爲AUTO_INCREMENT值在其它值賦值之後被生成,所以任何在賦值時對AUTO_INCREMENT列的引用都會返回0

INSERT語句支持下列修改符:

·         如果您使用DELAYED關鍵字,則服務器會把待插入的行放到一個緩衝器中,而發送INSERT DELAYED語句的客戶端會繼續運行。如果表正在被使用,則服務器會保留這些行。當表空閒時,服務器開始插入行,並定期檢查是否有新的讀取請求。如果有新的讀取請求,則被延遲的行被延緩執行,直到表再次空閒時爲止。請參見13.2.4.2節,“INSERT DELAYED語法”

·         如果您使用LOW_PRIORITY關鍵詞,則INSERT的執行被延遲,直到沒有其它客戶端從表中讀取爲止。當原有客戶端正在讀取時,有些客戶端剛開始讀取。這些客戶端也被包括在內。此時,INSERT LOW_PRIORITY語句等候。因此,在讀取量很大的情況下,發出INSERT LOW_PRIORITY語句的客戶端有可能需要等待很長一段時間(甚至是永遠等待下去)。(這與INSERT DELAYED形成對比,INSERT DELAYED立刻讓客戶端繼續執行。請參見13.2.4.2節,“INSERT DELAYED語法”。)注意LOW_PRIORITY通常不應用於MyISAM表,因爲這麼做會取消同時進行的插入。請參見15.1節,“MyISAM存儲引擎”

·         如果您指定了HIGH_PRIORITY,同時服務器採用--low-priority-updates選項啓動,則HIGH_PRIORITY將覆蓋--low-priority-updates選項。這麼做還會導致同時進行的插入被取消。

·         使用mysql_affected_rows() C API函數,可以獲得用於INSERT的受影響行的值。請參見25.2.3.1節,“mysql_affected_rows()”

·         如果您在一個INSERT語句中使用IGNORE關鍵詞,在執行語句時出現的錯誤被當作警告處理。例如,沒有使用IGNORE時,如果一個行復制了原有的UNIQUE索引或PRIMARY KEY值,會導致出現重複關鍵字錯誤,語句執行失敗。使用IGNORE時,該行仍然未被插入,但是不會出現錯誤。IGNORE未被指定時,如果數據轉化引發錯誤,則會使語句執行失敗。使用IGNORE後,無效數據被調整到最接近的值,並被插入;此時,生成警告,但是語句執行不會失敗。您可以使用mysql_info() C API函數測定有多少行被插入到表中。

如果您指定了ON DUPLICATE KEY UPDATE,並且插入行後會導致在一個UNIQUE索引或PRIMARY KEY中出現重複值,則執行舊行UPDATE。例如,如果列a被定義爲UNIQUE,並且包含值1,則以下兩個語句具有相同的效果:

mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
    -> ON DUPLICATE KEY UPDATE c=c+1;
 
mysql> UPDATE table SET c=c+1 WHERE a=1;

如果行作爲新記錄被插入,則受影響行的值爲1;如果原有的記錄被更新,則受影響行的值爲2

註釋:如果列b也是唯一列,則INSERT與此UPDATE語句相當:

mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

如果a=1 OR b=2與多個行向匹配,則只有一個行被更新。通常,您應該儘量避免對帶有多個唯一關鍵字的表使用ON DUPLICATE KEY子句。

您可以在UPDATE子句中使用VALUES(col_name)函數從INSERT...UPDATE語句的INSERT部分引用列值。換句話說,如果沒有發生重複關鍵字衝突,則UPDATE子句中的VALUES(col_name)可以引用被插入的col_name的值。本函數特別適用於多行插入。VALUES()函數只在INSERT...UPDATE語句中有意義,其它時候會返回NULL

示例:

mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
    -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

本語句與以下兩個語句作用相同:

mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
    -> ON DUPLICATE KEY UPDATE c=3;
mysql> INSERT INTO table (a,b,c) VALUES (4,5,6)
    -> ON DUPLICATE KEY UPDATE c=9;

當您使用ON DUPLICATE KEY UPDATE時,DELAYED選項被忽略。

您可以使用SQL LAST_INSERT_ID()函數查找用於AUTO_INCREMENT列的值。從C API的內部,使用mysql_insert_id()函數。不過,您應該注意,兩個函數的作用並不總是相同的。在12.9.3節,“信息函數”25.2.3.36節,“mysql_insert_id()”中進一步討論了與AUTO_INCREMENT列有關的INSERT語句的作用。

如果您使用INSERT...VALUES語句時採用了多個值清單或INSERT...SELECT,則該語句按以下格式返回一個信息字符串:

Records: 100 Duplicates: 0 Warnings: 0

記錄指示了經過語句處理的行的數目。(因爲重複數目可以不是零,所以該數目不一定是實際被插入的行的數目。)重複數目指的是不能被插入的行的數目,因爲這些行會複製部分原有的唯一索引值。警告指的是插入有錯誤或有問題的列值的次數。在以下情況下會出現警告:

·         向一個已定義爲NOT NULL的列中插入NULL。對於一個多行INSERT語句或INSERT INTO...SELECT語句,根據列數據的類型,列被設置爲隱含的默認值。對於數字類型,默認值爲0;對於字符串類型,默認值爲空字符串('');對於日期和時間類型,默認值爲“zero”值。對INSERT INTO...SELECT語句的處理方法與對多行插入的處理方法一樣,因爲服務器不能檢測來自SELECT的結果,不能判斷是否返回單一行。(對於單一行INSERT,當NULL被插入一個NOT NULL列時,不會出現警告,而是出現錯誤,並且語句運行失敗。)

·         數字列的值被設置在列的值範圍之外。此值被修改爲未最接近的值範圍端點。

·         向一個數字列賦予一個例如'10.34 a'的值。尾部的非數字文本被刪節,其餘的數字部分被插入,如果字符串值沒有前導的數字部分,則該列被設置爲0

·         向一個字符串列(CHAR, VARCHAR, TEXTBLOB)中插入的字符串超過了列的最大長度。此值被刪節到列的最大長度。

·         向日期或時間列中插入的值對於該列的類型是不合法的。根據列的類型,該列被設置到相應的零值。

如果您正在使用C API,則可以通過調用mysql_info()函數獲取信息字符串。請參見25.2.3.34節,“mysql_info()”

13.2.4.1. INSERT ... SELECT語法

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

使用INSERT...SELECT,您可以快速地從一個或多個表中向一個表中插入多個行。

示例:

INSERT INTO tbl_temp2 (fld_id)
    SELECT tbl_temp1.fld_order_id
    FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;

使用INSERT...SELECT語句時會出現以下情況:

·         明確地指定IGNORE,用於忽略會導致重複關鍵字錯誤的記錄。

·         不要同時使用DELAYEDINSERT...SELECT

·         INSERT語句的目標表會顯示在查詢的SELECT部分的FROM子句中。(在有些舊版本的MySQL中不會出現這種情況。)

·         AUTO_INCREMENT列照常運行。

·         爲了確保二進制日誌可以被用於再次創建原表,MySQL不允許在INSERT...SELECT運行期間同時進行插入操作。

·         目前,您不能在向一個表插入的同時,又在一個子查詢中從同一個表中選擇。

ON DUPLICATE KEY UPDATE的值部分中,只要您不使用SELECT部分中的GROUP BY,您就可以引用在其它表中的列。有一個副作用是,您必須使值部分中的非唯一列的名稱符合要求。

您可以使用REPLACE替代INSERT,來覆蓋舊行。對於包含唯一關鍵字值,並複製了舊行的新行,在進行處理時,REPLACE可以作爲INSERT IGNORE的同類子句:新行被用於替換舊行,而不是被丟棄。

13.2.4.2. INSERT DELAYED語法

INSERT DELAYED ...

用於INSERT語句的DELAYED選項是MySQL相對於標準SQL的擴展。如果您的客戶端不能等待INSERT完成,則這個選項是非常有用的。當您使用MySQL進行日誌編寫時,這是非常常見的問題。您也可以定期運行SELECTUPDATE語句,這些語句花費的時間較長。

當一個客戶端使用INSERT DELAYED時,會立刻從服務器處得到一個確定。並且行被排入隊列,當表沒有被其它線程使用時,此行被插入。

使用INSERT DELAYED的另一個重要的好處是,來自許多客戶端的插入被集中在一起,並被編寫入一個塊。這比執行許多獨立的插入要快很多。

使用DELAYED時有一些限制:

·         INSERT DELAYED僅適用於MyISAM, MEMORYARCHIVE表。對於MyISAM表,如果在數據文件的中間沒有空閒的塊,則支持同時採用SELECTINSERT語句。在這些情況下,基本不需要對MyISAM使用INSERT DELAYED。請參見15.1節,“MyISAM存儲引擎”, 15.4節,“MEMORY (HEAP)存儲引擎”15.8節,“ARCHIVE存儲引擎”

·         INSERT DELAYED應該僅用於指定值清單的INSERT語句。服務器忽略用於INSERT DELAYED...SELECT語句的DELAYED

·         服務器忽略用於INSERT DELAYED...ON DUPLICATE UPDATE語句的DELAYED

·         因爲在行被插入前,語句立刻返回,所以您不能使用LAST_INSERT_ID()來獲取AUTO_INCREMENT值。AUTO_INCREMENT值可能由語句生成。

·         對於SELECT語句,DELAYED行不可見,直到這些行確實被插入了爲止。

·         DELAYED在從屬複製服務器中被忽略了,因爲DELAYED不會在從屬服務器中產生與主服務器不一樣的數據。

注意,目前在隊列中的各行只保存在存儲器中,直到它們被插入到表中爲止。這意味着,如果您強行中止了mysqld(例如,使用kill -9)或者如果mysqld意外停止,則所有沒有被寫入磁盤的行都會丟失。

以下詳細描述了當您對INSERTREPLACE使用DELAYED選項時會發生什麼情況。在這些描述中,“線程”指的是已接受了一個INSERT DELAYED語句的線程,“管理程序”指的是爲某個特定的表處理所有INSERT DELAYED語句的線程。

·         當一個線程對一個表執行DELAYED語句時,會創建出一個管理程序線程(如果原來不存在),對用於本表的所有DELAYED語句進行處理。

·         線程會檢查是否管理程序以前已獲取了DELAYED鎖定;如果沒有獲取,則告知管理程序線程進行此項操作。即使其它線程對錶有READWRITE鎖定,也可以獲得DELAYED鎖定。但是管理程序會等待所有的ALTER TABLE鎖定或FLUSH TABLE鎖定,以確保表的結構是最新的。

·         線程執行INSERT語句,但不是把行寫入表中,而是把最終行的拷貝放入一個由管理程序線程管理的隊列中。線程會提示出現語法錯誤,這些錯誤會被報告到客戶端中。

·         因爲在插入操作之前,INSERT返回已經完成,所以客戶端不能從服務器處獲取重複記錄的數目,也不能獲取生成的行的AUTO_INCREMENT值。(如果您使用C API,則出於同樣的原因,mysql_info()函數不會返回任何有意義的東西。)

·         當行被插入表中時,二進制日誌被管理程序線程更新。在多行插入情況下,當第一行被插入時,二進制日誌被更新。

·         每次delayed_insert_limit行被編寫時,管理程序會檢查是否有SELECT語句仍然未執行。如果有,則會在繼續運行前,讓這些語句先執行。

·         當管理程序的隊列中沒有多餘的行時,表被解鎖。如果在delayed_insert_timeout時間內,沒有接收到新的INSERT DELAYED語句,則管理程序中止。

·         如果在某個特定的管理程序隊列中,有超過delayed_queue_size的行未被執行,則申請INSERT DELAYED的線程會等待,直到隊列中出現空間爲止。這麼做可以確保mysqld不會把所有的存儲器都用於被延遲的存儲隊列。

·         管理程序線程會顯示在MySQL進程清單中,其命令列中包含delayed_insert。如果您執行一個FLUSH TABLES語句或使用KILL thread_id進行刪除,則會刪除此線程。不過,在退出前,線程會首先把所有排入隊列的行存儲到表中。在這期間,該線程不會從其它線程處接受任何新的INSERT語句。如果您在此之後執行一個INSERT DELAYED語句,則會創建出一個新的管理程序線程。

注意,如果有一個INSERT DELAYED管理程序正在運行,則這意味着INSERT DELAYED語句比常規的INSERT語句具有更高的優先權。其它更新語句必須等待,直到INSERT DELAYED語句隊列都運行完畢,或者管理程序線程被中止(使用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

13.2.5. LOAD DATA INFILE語法

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [FIELDS
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char' ]
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number LINES]
    [(col_name_or_user_var,...)]
    [SET col_name = expr,...)]

LOAD DATA INFILE語句用於高速地從一個文本文件中讀取行,並裝入一個表中。文件名稱必須爲一個文字字符串。

要了解有關INSERTLOAD DATA INFILE的效率的對比和有關LOAD DATA INFILE加速的更多信息,請參見7.2.16節,“INSERT語句的速度”

character_set_database系統變量指示的字符集被用於解釋文件中的信息。SET NAMEScharacter_set_client的設置不會影響對輸入的解釋。

注意,目前不能載入UCS2數據文件。

您也可以通過使用mysqlimport應用程序載入數據文件;通過向服務器發送一個LOAD DATA INFILE語句實現此功能。--local選項用於使mysqlimport從客戶主機中讀取數據文件。如果客戶端和服務器支持壓縮協議,則您可以指定—compress選項提高在慢速網絡中的性能。請參見8.10節,“mysqlimport:數據導入程序

如果您使用LOW_PRIORITY,則LOAD DATA語句的執行被延遲,直到沒有其它的客戶端從表中讀取爲止。

如果一個MyISAM表滿足同時插入的條件(即該表在中間有空閒塊),並且您對這個MyISAM表指定了CONCURRENT,則當LOAD DATA正在執行時,其它線程會從表中重新獲取數據。即使沒有其它線程在同時使用本表格,使用本選項也會略微影響LOAD DATA的性能。

如果指定了LOCAL,則被認爲與連接的客戶端有關:

·         如果指定了LOCAL,則文件會被客戶主機上的客戶端讀取,並被髮送到服務器。文件會被給予一個完整的路徑名稱,以指定確切的位置。如果給定的是一個相對的路徑名稱,則此名稱會被理解爲相對於啓動客戶端時所在的目錄。

·         如果LOCAL沒有被指定,則文件必須位於服務器主機上,並且被服務器直接讀取。

當在服務器主機上爲文件定位時,服務器使用以下規則:

·         如果給定了一個絕對的路徑名稱,則服務器使用此路徑名稱。

·         如果給定了帶有一個或多個引導組件的相對路徑名稱,則服務器會搜索相對於服務器數據目錄的文件。

·         如果給定了一個不帶引導組件的文件名稱,則服務器會在默認數據庫的數據庫目錄中尋找文件。

注意,這些規則意味着名爲./myfile.txt的文件會從服務器數據目錄中被讀取,而名爲myfile.txt的同樣的文件會從默認數據庫的數據庫目錄中讀取。例如,下面的LOAD DATA語句會從db1數據庫目錄中讀取文件data.txt,因爲db1是當前數據庫。即使語句明確把文件載入到db2數據庫中的表裏,也會從db1目錄中讀取。

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

注意,使用正斜槓指定Windows路徑名稱,而不是使用反斜槓。如果您使用反斜槓,您必須使用兩個。

出於安全原因,當讀取位於服務器中的文本文件時,文件必須位於數據庫目錄中,或者是全體可讀的。另外,要對服務器文件使用LOAD DATA INFILE,您必須擁有FILE權限。

5.7.3節,“MySQL提供的權限”

與讓服務器直接讀取文件相比,使用LOCAL速度略慢,這是因爲文件的內容必須通過客戶端發送到服務器上。不過,您不需要FILE權限來載入本地文件。

只有當您的服務器和您的客戶端都許可時,LOCAL纔可運行。例如,如果使用—local-infile=0啓動mysqld,則LOCAL不運行。請參見5.6.4節,“LOAD DATA LOCAL安全問題

如果您需要LOAD DATA來從一個管道中讀取,您可以使用以下方法(此處我們把/目錄清單載入一個表格):

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
find / -ls > /mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

有些輸入記錄把原有的記錄複製到唯一關鍵字值上。REPLACEIGNORE關鍵字用於控制這些輸入記錄的操作。

如果您指定了REPLACE,則輸入行會替換原有行(換句話說,與原有行一樣,對一個主索引或唯一索引具有相同值的行)。請參見13.2.6節,“REPLACE語法”

如果您指定IGNORE,則把原有行復制到唯一關鍵字值的輸入行被跳過。如果您這兩個選項都不指定,則運行情況根據LOCAL關鍵詞是否被指定而定。不使用LOCAL時,當出現重複關鍵字值時,會發生錯誤,並且剩下的文本文件被忽略。使用LOCAL時,默認的運行情況和IGNORE被指定時的情況相同;這是因爲在運行中間,服務器沒有辦法中止文件的傳輸。

如果您希望在載入運行過程中忽略外鍵的限制,您可以在執行LOAD DATA前發送一個SET FOREIGN_KEY_CHECKS=0語句。

如果您對一個空的MyISAM表使用LOAD DATA INFILE,則所有的非唯一索引會被創建在一個獨立批中(對於REPAIR TABLE)。當您有許多索引時,這通常會使LOAD DATA INFILE大大加快。通常,LOAD DATA INFILE的速度會非常快,但是在某些極端情況下,您可以在把文件載入到表中之前使用ALTER TABLE...DISABLE KEYS關閉LOAD DATA INFILE,或者在載入文件之後使用ALTER TABLE...ENABLE KEYS再次創建索引,使創建索引的速度更快。請參見7.2.16節,“INSERT語句的速度”

LOAD DATA INFILESELECT...INTO OUTFILE的補語。(見13.2.7節,“SELECT語法”。)要從一個表中把數據寫入一個文件中,應使用SELECT...INTO OUTFILE。要讀取文件,放回到表中,應使用LOAD DATA INFILEFIELDSLINES子句的語法對於兩個語句是一樣的。兩個子句都是自選的,但是如果兩個都被指定了,FIELDS必須位於LINES的前面。

如果您指定了一個FIELDS子句,則每個亞子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BYESCAPED BY)也是自選的。不過,您必須指定其中至少一個。

如果您不指定FIELDS子句,則默認值爲假設您寫下如下語句時的值:

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

如果您不指定LINES子句,則默認值爲假設您寫下如下語句時的值:

LINES TERMINATED BY '\n' STARTING BY ''

換句話說,當讀取輸入值時,默認值會使LOAD DATA INFILE按如下方式運行:

·         在新行處尋找行的邊界。

·         不會跳過任何行前綴。

·         在製表符處把行分解爲字段。

·         不希望字段被包含在任何引號字符之中。

·         出現製表符、新行、或在‘\’前有‘\’時,理解爲作爲字段值一部分的文字字符。

相反的,當編寫輸出值時,默認值會使SELECT...INTO OUTFILE按如下方式運行:

·         在字段之間寫入製表符。

·         不把字段包含在任何引號字符中。

·         當字段值中出現製表符、新行或‘\’時,使用‘\’進行轉義。

·         在行的末端寫入新行。

注意,要寫入FIELDS ESCAPED BY \\’,您必須爲待讀取的值指定兩個反斜槓,作爲一個單反斜槓使用。

註釋:如果您已經在Windows系統中生成了文本文件,您可能必須使用LINES TERMINATED BY \r\n’來正確地讀取文件,因爲Windows程序通常使用兩個字符作爲一個行終止符。部分程序,比如WordPad,當編寫文件時,可能會使用\r作爲行終止符。要讀取這樣的文件,應使用LINES TERMINATED BY \r’。

如果所有您希望讀入的行都含有一個您希望忽略的共用前綴,則您可以使用'prefix_string'來跳過前綴(和前綴前的字符)。如果某行不包括前綴,則整個行被跳過。註釋:prefix_string會出現在一行的中間。

示例:

mysql> LOAD DATA INFILE '/tmp/test.txt'
    -> INTO TABLE test LINES STARTING BY "xxx";

使用此語句,您可以讀入包含有如下內容的文件:

xxx"row",1
something xxx"row",2

並只得到數據("row",1)("row",2)

IGNORE number LINES選項可以被用於在文件的開始處忽略行。例如,您可以使用IGNORE 1 LINES來跳過一個包含列名稱的起始標題行:

mysql> LOAD DATA INFILE '/tmp/test.txt'
    -> INTO TABLE test IGNORE 1 LINES;

當您聯合使用SELECT...INTO OUTFILELOAD DATA INFILE來從一個數據庫中把數據寫入一個文件中,然後再讀取文件,返回到數據庫中時,用於兩個語句的field-line-handling選項必須匹配。否則,LOAD DATA INFILE不會正確地理解文件的內容。假設您使用SELECT...INTO OUTFILE來編寫一個的文件,字段由逗號分隔:

mysql> SELECT * INTO OUTFILE 'data.txt'
    ->          FIELDS TERMINATED BY ','
    ->          FROM table2;

要讀取由逗號分隔的文件並返回,則正確的語句應該是:

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格式的文件具有以逗號分隔並且包含在雙引號中的字段。如果文件中的各行以新行爲結尾,則此處所示的語句描述了您可以用於載入文件的field-line-handling選項:

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

所有field-line-handling選項都可以指定一個空字符串('')。如果字符串不是空的,則FIELDS [OPTIONALLY] ENCLOSED BYFIELDS ESCAPED BY值必須爲單一字符。FIELDS TERMINATED BY, LINES STARTING BYLINES TERMINATED BY值可以超過一個字符。例如,要編寫由回車/換行成對字符作爲結尾的行,或讀取包含這類行的文件,則應指定一個LINES TERMINATED BY \r\n’子句。

如果jokes被由%%組成的行分隔,要讀取包含jokes的文件,您可以這麼操作:

mysql> CREATE TABLE jokes
    ->     (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->     joke TEXT NOT NULL);
mysql> LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes
    ->     FIELDS TERMINATED BY ''
    ->     LINES TERMINATED BY '\n%%\n' (joke);

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"

如果您指定了OPTINALLY,則ENCLOSED BY字符只被用於包含具有字符串數據類型(比如CHAR, BINARY, TEXTENUM)的列中的值:

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字符作爲前綴,對ENCLOSED 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字符爲開始,當出現這類字符時,只有後面接着字段或行TERMINATED 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 BYLINES TERMINATED BY值的第一個字符

·         ASCII 0(在轉義符之後編寫的字符實際上是ASCII0’,而不是一個值爲0的字節)

如果FIELDS ESCAPED BY字符爲空字符,則沒有字符被轉義,並且NULL被作爲NULL輸出,而不是\N。去指定一個空的轉義符不是一個好辦法,特別是如果數據的字段值包含任何剛給定的清單中的字符時,更不能這麼做。

對於輸入值,如果FIELDS ESCAPED BY字符不是空字符,則出現這種字符時會被剝離,然後以下字符被作爲字段值的一部分。例外情況是,被轉義的‘0’或‘N’(例如,\0\N,此時轉義符爲‘\’)。這些序列被理解爲ASCII NUL(一個零值字節)和NULL。用於NULL處理的規則在本節的後部進行說明。

要了解有關‘\-escape語法的更多信息,請參見9.1節,“文字值”

在特定情況下,field-line-handling選項相互影響:

·         如果LINES TERMINATED BY是空字符串,並且FIELDS TERMINATED BY不是空字符串,則各行以FIELDS TERMINATED BY作爲結尾。

·         如果FIELDS TERMINATED BYFIELDS ENCLOSED BY值均爲空值(''),則使用固定行(無分隔)格式。使用固定行格式時,在字段之間不使用分隔符(但是您仍然可以有行終止符)。列值使用列的顯示寬度進行寫入和讀取。例如,如果某列被定義爲INT(7),則使用7字符字段寫入列值。輸出時,通過讀取7個字符獲取列值。

LINES TERMINATED BY仍然用於分隔行。如果某行不包含所有字段,則其餘的各列被設置到默認值。如果您沒有行終止符,您應該把終止符設置爲''。在此情況下,文本文件必須包含每行的所有字段。

固定行格式也會影響NULL值的操作,這將在以後進行介紹。注意,如果您正在使用一個多字節字符集,則固定規格格式不會運行。

根據正在使用中的FIELDSLINES選項的不同,NULL值的操作有所變化:

·         對於默認的FIELDSLINES值,NULL被作爲\N的字段值編寫,用於輸出;\N字段值被作爲NULL讀取,用於輸入(假設ESCAPED BY字符爲‘\’)。

·         如果FIELDS ENCLOSED BY不是空值,則包含以文字詞語NULL爲值的字段被作爲NULL值讀取。這與被FIELDS ENCLOSED BY字符包圍的詞語NULL不同。該詞語被作爲字符串'NULL'讀取。

·         如果FIELDS ESCAPED BY是空值,則NULL被作爲詞語NULL寫入。

·         採用固定行格式時(當FIELDS TERMINATED BYFIELDS ENCLOSED BY均爲空值時採用),NULL被作爲一個空字符串寫入。注意,這會導致在被寫入文件時,表中的NULL值和空字符串均無法辨別,這是因爲兩者都被作爲空字符串寫入。如果您需要在讀取文件並返回時能夠分辨兩者,則您不應使用固定行格式。

LOAD DATA INFILE不支持有些情況:

·         固定規格行(FIELDS TERMINATED BYFIELDS ENCLOSED BY均爲空值)和BLOBTEXT列。

·         如果您指定了一個分隔符,並且該分隔符與其它的前綴一樣,則LOAD DATA INFILE不能正確地理解輸入值。例如,下面的FIELDS子句會導致問題:

·                FIELDS TERMINATED BY '"' ENCLOSED BY '"'

·         如果FIELDS ESCAPED BY爲空值,則包含FIELDS ENCLOSED BYLINES TERMINATED BY的字段值後面再接FIELDS TERMINATED BY值會導致LOAD DATA INFILE過早地停止讀取一個字段或行。出現這種情況的原因是LOAD DATA INFILE不能正確地決定字段或行值在哪裏結束。

以下的例子載入了persondata表中的所有列:

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

默認情況下,如果在LOAD DATA INFILE語句的末尾處沒有設列清單時,則輸入行預計會包含一個字段,用於表中的每個列。如果您只想載入一個表的部分列,則應指定一個列清單:

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

如果輸入文件中各字段的順序與表中各列的順序不同,您也必須指定一個列清單。否則,MySQL不能把輸入字段和表中的列匹配起來。

列清單可以包含列名稱或用戶變量。支持SET子句。這使您可以把輸入值賦予用戶變量,然後在把結果賦予列之前,對這些值進行變換。

SET子句中的用戶變量可以採用多種方式使用。以下例子使用數據文件中的第一列,直接用於t1.column1的值。在用戶變量被用於t2.column2值之前,把第二列賦予用戶變量。該變量從屬於一個分割運行。

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @var1)
  SET column2 = @var1/100;

SET子句可以被用於提供不是來源於輸入文件的值。以下語句把column3設置爲當前的日期和時間:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, column2)
  SET column3 = CURRENT_TIMESTAMP;

您也可以通過把輸入值賦予一個用戶變量,同時不把變量賦予表中的列,來丟棄此輸入值:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @dummy, column2, @dummy, column3);

/變量清單和SET子句的使用受到以下限定:

·         SET子句中的賦值應只含有位於賦值操作符的左側的列名稱。

·         您可以在SET賦值的右側使用子查詢。如果子查詢可以返回一個值,並且此值將被賦予到一個列中,則此子查詢只能是標量子查詢。另外,您不能使用子查詢從一個正在被載入的表中選擇。

·         對於於列/變量清單或SET子句,被IGNORE子句忽略的行不被處理。

·         當載入採用固定行格式的數據時,不能使用用戶變量,因爲用戶變量沒有顯示寬度。

當處理一個輸入行時,LOAD DATA會依據列/變量清單和SET子句,把行拆分成字段,並使用值。然後,得到的行被插入表中。如果有用於表的BEFORE INSERTAFTER INSERT觸發器,則在插入行之前和插入行之後分別啓動觸發器。

如果一個輸入行含有過多的字段,則多餘的字段被忽略,並且警告的數量增加。

如果一個輸入行含有的字段過少,則輸入字段缺失的表中的列被設置爲默認值。默認值賦值在13.1.5節,“CREATE TABLE語法”中進行了說明。

如果字段值缺失,則對一個空字段值會被按不同方式理解:

·         對於字符串類型,列被設置爲空字符串。

·         對於數字類型,列被設置爲0

·         對於日期和時間類型,列被設置爲該類型相應的“zero”。請參見11.3節,“日期和時間類型”

如果您明確地把一個空字符串賦予一個INSERTUPDATE語句中的字符串類型、數字類型或日期或時間類型,則產生的這些值相同。

只有在兩種情況下TIMESTAMP列被設置爲當前日期和時間。一種情況時當列有一個NULL值(也就是\N)時;另一種情況是(僅對於第一個TIMESTAMP列),當一個字段清單被指定時,TIMESTAMP列會從字段清單中被略去。

LOAD DATA INFILE把所有的輸入值當作字符串,所以您不能按照使用INSERT語句的方式使用ENUMSET列的數字值。所有的ENUMSET值必須被指定爲字符串。

LOAD DATA INFILE語句結束時,會按以下格式返回一個信息字符串:

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

如果您正在使用C API,您可以通過調用mysql_info()函數獲取有關語句的信息。請參見25.2.3.34節,“mysql_info()”

當值通過INSERT語句被插入時或出現相同情況時,會發生警告(見13.2.4節,“INSERT語法”)。例外情況是,當輸入行中字段過多或過少時,LOAD DATA INFILE也生成警告。這些警告並不存儲;警告的數量只用於指示運行是否良好。

您可以使用SHOW WARNINGS來得到第一批max_error_count警告的清單,作爲有關運行錯誤的信息。請參見13.5.4.22節,“SHOW WARNINGS語法”

13.2.6. REPLACE語法

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...

或:

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...

或:

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...

REPLACE的運行與INSERT很相像。只有一點除外,如果表中的一箇舊記錄與一個用於PRIMARY KEY或一個UNIQUE索引的新記錄具有相同的值,則在新記錄被插入之前,舊記錄被刪除。請參見13.2.4節,“INSERT語法”

注意,除非表有一個PRIMARY KEYUNIQUE索引,否則,使用一個REPLACE語句沒有意義。該語句會與INSERT相同,因爲沒有索引被用於確定是否新行復制了其它的行。

所有列的值均取自在REPLACE語句中被指定的值。所有缺失的列被設置爲各自的默認值,這和INSERT一樣。您不能從當前行中引用值,也不能在新行中使用值。如果您使用一個例如“SET col_name = col_name + 1”的賦值,則對位於右側的列名稱的引用會被作爲DEFAULT(col_name)處理。因此,該賦值相當於SET col_name = DEFAULT(col_name) + 1

爲了能夠使用REPLACE,您必須同時擁有表的INSERTDELETE權限。

REPLACE語句會返回一個數,來指示受影響的行的數目。該數是被刪除和被插入的行數的和。如果對於一個單行REPLACE該數爲1,則一行被插入,同時沒有行被刪除。如果該數大於1,則在新行被插入前,有一個或多箇舊行被刪除。如果表包含多個唯一索引,並且新行復制了在不同的唯一索引中的不同舊行的值,則有可能是一個單一行替換了多箇舊行。

受影響的行數可以容易地確定是否REPLACE只添加了一行,或者是否REPLACE也替換了其它行:檢查該數是否爲1(添加)或更大(替換)。

如果您正在使用C API,則可以使用mysql_affected_rows()函數獲得受影響的行數。

目前,您不能在一個子查詢中,向一個表中更換,同時從同一個表中選擇。

以下是所用算法的更詳細的說明(該算法也用於LOAD DATA...REPLACE):

1.    嘗試把新行插入到表中

2.    當因爲對於主鍵或唯一關鍵字出現重複關鍵字錯誤而造成插入失敗時:

a.    從表中刪除含有重複關鍵字值的衝突行

b.    再次嘗試把新行插入到表中

13.2.7. SELECT語法

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [INTO OUTFILE 'file_name' export_options
      | INTO DUMPFILE 'file_name']
    [FROM table_references
    [WHERE where_definition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_definition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC] , ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT用於恢復從一個或多個表中選擇的行,並可以加入UNION語句和子查詢。請參見13.2.7.2節,“UNION語法
13.2.8節,“Subquery語法”

·         每個select_expr都指示一個您想要恢復的列。

·         table_references指示行從哪個表或哪些表中被恢復。在13.2.7.1節,“JOIN語法”中對該語法進行了說明。

·         where_definition包括關鍵詞WHERE,後面接一個表達式。該表達式指示被選擇的行必須滿足的條件。

有的行在計算時未引用任何表。SELECT也可以用於恢復這類行。

舉例說明:

mysql> SELECT 1 + 1;
        -> 2

所有被使用的子句必須按語法說明中顯示的順序嚴格地排序。例如,一個HAVING子句必須位於GROUP BY子句之後,並位於ORDER BY子句之前。

·         使用AS alias_name可以爲select_expr給定一個別名。此別名用作表達式的列名,可以用於GROUP BYORDER BYHAVING子句。例如:

·                mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
·                    -> FROM mytable ORDER BY full_name;

在爲select_expr給定別名時,AS關鍵詞是自選的。前面的例子可以這樣編寫:

mysql> SELECT CONCAT(last_name,', ',first_name) full_name
    -> FROM mytable ORDER BY full_name;

因爲AS是自選的,如果您忘記在兩個select_expr表達式之間加逗號,則會出現一個小問題:MySQL會把第二個表達式理解爲一個別名。例如,在以下語句中,columnb被作爲別名對待:

mysql> SELECT columna columnb FROM mytable;

因此,使用AS明確地指定列的別名,把它作爲習慣,是一個良好的操作規範。

·         在一個WHERE子句中使用列別名是不允許的,因爲當執行WHERE子句時,列值可能還沒有被確定。請參見A.5.4節,“與列別名有關的問題”

·         FROM table_references子句指示行從哪些表中被恢復。如果您命名的表多於一個,則您在進行一個聯合操作。要了解有關聯合語法的說明,請參見13.2.7.1節,“JOIN語法”。對於每一個被指定的表,您可以自選地指定一個別名。

·                tbl_name [[AS] alias]
·                    [{USE|IGNORE|FORCE} INDEX (key_list)]

使用USE INDEXIGNORE INDEXFORCE INDEX可以向優化符提示如何選擇索引。這部分內容在13.2.7.1節,“JOIN語法”中進行了討論。

您可以使用SET max_seeks_for_key=value作爲一種替代方法,來促使MySQL優先採用關鍵字掃描,替代表掃描。

·         您可以把當前數據庫中的一個表作爲tbl_name(在當前數據庫中)引用,或作爲db_name.tbl_name引用,來明確地指定一個數據庫。您可以把一列作爲col_name, tbl_name.col_name引用或作爲db_name.tbl_name.col_name引用。您不需要對一個列引用指定一個tbl_namedb_name.tbl_name前綴,除非此引用意義不明確。意義不明確時,要求指定明確的列引用格式。有關示例見9.2節,“數據庫、表、索引、列和別名”

·         在沒有表被引用的情況下,允許您指定DUAL作爲一個假的表名。

·                mysql> SELECT 1 + 1 FROM DUAL;
·                        -> 2

有些服務器要求一個FROM子句。DUAL僅用於與這些服務器兼容。如果沒有表被引用,則MySQL不要求該子句,前面的語句可以按以下方法編寫:

mysql> SELECT 1 + 1;
        -> 2

·         使用tbl_name AS alias_nametbl_name 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;

·         WHERE子句中,您可以使用MySQL支持的所有函數,不過總計(總結)函數除外。請參見第12章:函數和操作符

·         被選擇的用於輸出的列可以使用列名稱、列別名或列位置被引用到ORDER BYGROUP 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關鍵詞明確地指定。

不建議使用列位置,因爲該語法已經從SQL標準中刪除。

·         如果您使用GROUP BY,則輸出行根據GROUP BY列進行分類,如同您對相同的列進行了ORDER BYMySQLGROUP BY進行了擴展,因此您可以在各列(在子句中進行命名)的後面指定ASCDESC

·                SELECT a, COUNT(b) FROM test_table GROUP BY a DESC

·         MySQLGROUP BY的使用進行了擴展,允許選擇在GROUP BY子句中沒有被提到的字段。如果您沒有得到預期的結果,請閱讀GROUP BY的說明,請參見12.10節,“與GROUP BY子句同時使用的函數和修改程序

·         GROUP BY允許一個WITH ROLLUP修飾符。請參見12.10.2節,“GROUP BY修改程序”

·         HAVING子句基本上是最後使用,只位於被髮送給客戶端的條目之前,沒有進行優化。(LIMIT用於HAVING之後。)

SQL標準要求HAVING必須引用GROUP BY子句中的列或用於總計函數中的列。不過,MySQL支持對此工作性質的擴展,並允許HAVING因爲SELECT清單中的列和外部子查詢中的列。

如果HAVING子句引用了一個意義不明確的列,則會出現警告。在下面的語句中,col2意義不明確,因爲它既作爲別名使用,又作爲列名使用:

mysql> SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;

標準SQL工作性質具有優先權,因此如果一個HAVING列名既被用於GROUP BY,又被用作輸出列清單中的起了別名的列,則優先權被給予GROUP BY列中的列。

·         HAVING不能用於應被用於WHERE子句的條目。例如,不能編寫如下語句:

·                mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;

而應這麼編寫:

mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;

·         HAVING子句可以引用總計函數,而WHERE子句不能引用:

·                mysql> SELECT user, MAX(salary) FROM users
·                    ->     GROUP BY user HAVING MAX(salary)>10;

(在有些較早版本的MySQL中,本語句不運行。)

·         LIMIT子句可以被用於限制被SELECT語句返回的行數。LIMIT取一個或兩個數字自變量,自變量必須是非負的整數常數(當使用已預備的語句時除外)。

使用兩個自變量時,第一個自變量指定返回的第一行的偏移量,第二個自變量指定返回的行數的最大值。初始行的偏移量爲0(不是1):

mysql> SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

爲了與PostgreSQL兼容,MySQL也支持LIMIT row_count OFFSET offset語法。

如果要恢復從某個偏移量到結果集合的末端之間的所有的行,您可以對第二個參數是使用比較大的數。本語句可以恢復從第96行到最後的所有行:

mysql> SELECT * FROM tbl LIMIT 95,18446744073709551615;

使用1個自變量時,該值指定從結果集合的開頭返回的行數:

mysql> SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows

換句話說,LIMIT nLIMIT 0,n等價。

對於已預備的語句,您可以使用位置保持符。以下語句將從tb1表中返回一行:

mysql> SET @a=1;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?";
mysql> EXECUTE STMT USING @a;

以下語句將從tb1表中返回第二到第六行:

mysql> SET @skip=1; SET @numrows=5;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?";
mysql> EXECUTE STMT USING @skip, @numrows;

·         SELECT...INTO OUTFILE 'file_name'形式的SELECT可以把被選擇的行寫入一個文件中。該文件被創建到服務器主機上,因此您必須擁有FILE權限,才能使用此語法。file_name不能是一個原有的文件。原有文件會阻止例如“/etc/passwd”的文件和數據庫表被銷燬。

SELECT...INTO OUTFILE語句的主要作用是讓您可以非常快速地把一個錶轉儲到服務器機器上。如果您想要在服務器主機之外的部分客戶主機上創建結果文件,您不能使用SELECT...INTO OUTFILE。在這種情況下,您應該在客戶主機上使用比如“mysql e "SELECT ..." > file_name”的命令,來生成文件。

SELECT...INTO OUTFILELOAD DATA INFILE的補語;用於語句的exort_options部分的語法包括部分FIELDSLINES子句,這些子句與LOAD DATA INFILE語句同時使用。請參見13.2.5節,“LOAD DATA INFILE語法”

FIELDS ESCAPED BY用於控制如何寫入特殊字符。如果FIELDS ESCAPED BY字符不是空字符,則被用於在輸出中對以下字符設前綴:

o        FIELDS ESCAPED BY字符

o        FIELDS [OPTIONALLY] ENCLOSED BY字符

o        FIELDS TERMINATED BYLINES TERMINATED BY值的第一個字符

o        ASCII 0(在編寫時接在轉義符後面的是ASCII 0’,而不是一個零值字節)

如果FIELDS ESCAPED BY字符是空字符,則沒有字符被轉義,並且NULL被作爲NULL輸出,而不是作爲\N輸出。指定一個空的轉義符不是一個好的主意。特別是當您的數據中的字段值包含剛被給予的清單中的字符時,更是如此。

其原因是您必須對所有FIELDS TERMINATED BY, ENCLOSED BY, ESCAPED BYLINES TERMINATED BY字符進行轉義,才能可靠地讀取文件並返回。ASCII NUL被轉義,以便更容易地使用調頁程序觀看。

生成的文件不必符合SQL語法,所以沒有其它的字符需要被轉義。

在下面的例子中,生成一個文件,各值用逗號隔開。這種格式可以被許多程序使用。

SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;

·         如果您使用INTO DUMPFILE代替INTO OUTFILE,則MySQL只把一行寫入到文件中,不對任何列或行進行終止,也不執行任何轉義處理。如果您想要把一個BLOB值存儲到文件中,則這個語句是有用的。

·         註釋:任何由INTO OUTFILEINTO DUMPFILE創建的文件都可以被服務器主機上的所有用戶編寫。原因是,MySQL服務器不能創建這樣的文件,即文件的所有者不是該文件運行時所屬的用戶(任何時候,您都不能出於此原因或出於其它原因把mysqld作爲根段運行)。該文件必須是全局可寫的,這樣您就可以操作其中的內容。

·         有的過程應在結果集合內處理數據。PROCEDURE子句用於對這些過程進行命名。要了解示例,請參見27.3.1節,“步驟分析”

·         存儲引擎使用頁面或行鎖。如果您對存儲引擎使用FOR UPDATE,則受到查詢檢驗的行會被進行寫鎖定,直到當前事務結束爲止。使用LOCK IN SHARE MODE可以設置一個共享鎖。共享鎖可以防止其它事務更新或刪除被檢驗的行。請參見15.2.10.5節,“鎖定讀取SELECT ... FOR UPDATE和SELECT ... LOCK IN SHARE MODE”

SELECT關鍵詞的後面,您可以使用許多選項。這些選項可以影響語句的運行。

ALL, DISTINCTDISTINCTROW選項指定是否重複行應被返回。如果這些選項沒有被給定,則默認值爲ALL(所有的匹配行被返回)。DISTINCTDISTINCTROW是同義詞,用於指定結果集合中的重複行應被刪除。

HIGH_PRIORITY, STRAIGHT_JOIN和以SQL_爲開頭的選項是MySQL相對於標準SQL的擴展。

·         HIGH_PRIORITY給予SELECT更高的優先權,高於用於更新表的語句。您應該只對查詢使用HIGH_PRIORITY。查詢速度非常快,而且立刻被執行。SELECT HIGH_PRIORITY查詢在表被鎖定用於讀取時被髮出。即使有一個新的語句正在等待表變爲空閒,查詢也會運行。

HIGH_PRIORITY不能和SELECT語句同時使用。SELECT語句是UNION的一部分。

·         STRAIGHT_JOIN用於促使優化符把表聯合在一起,順序按照這些表在FROM子句中排列的順序。如果優化符聯合表時順序不佳,您可以使用STRAIGHT_JOIN來加快查詢的速度。請參見7.2.1節,“EXPLAIN語法(獲取關於SELECT的信息)STRAIGHT_JOIN也可以被用於table_references清單中。請參見13.2.7.1節,“JOIN語法”

·         SQL_BIG_RESULT可以與GROUP BYDISTINCT同時使用,來告知優化符結果集合有很多行。在這種情況下,MySQL直接使用以磁盤爲基礎的臨時表(如果需要的話)。在這種情況下,MySQL還會優先進行分類,不優先使用臨時表。臨時表對於GROUP BY組分帶有關鍵字。

·         SQL_BUFFER_RESULT促使結果被放入一個臨時表中。這可以幫助MySQL提前解開表鎖定,在需要花費較長時間的情況下,也可以幫助把結果集合發送到客戶端中。

·         SQL_SMALL_RESULT可以與GROUP BYDISTINCT同時使用,來告知優化符結果集合是較小的。在此情況下,MySAL使用快速臨時表來儲存生成的表,而不是使用分類。在MySQL 5.1中,通常不需要這樣。

·         SQL_CALC_FOUND_ROWS告知MySQL計算有多少行應位於結果集合中,不考慮任何LIMIT子句。行的數目可以使用SELECT FOUND_ROWS()恢復。請參見12.9.3節,“信息函數”

·         如果您正在使用一個query_cache_type值,值爲2DEMAND,則SQL_CACHE告知MySQL把查詢結果存儲在查詢緩存中。對於使用UNION的查詢或子查詢,本選項會影響查詢中的所有SELECT。請參見5.13節,“MySQL查詢高速緩衝”

·         SQL_NO_CACHE告知MySQL不要把查詢結果存儲在查詢緩存中。請參見5.13節,“MySQL查詢高速緩衝”。對於一個使用UNION或子查詢的查詢,本選項會影響查詢中的SELECT

13.2.7.1. JOIN語法

MySQL支持以下JOIN語法。這些語法用於SELECT語句的table_references部分和多表DELETEUPDATE語句:

table_references:
    table_reference [, table_reference] …

table_reference:
    table_factor
  | join_table

table_factor:
    tbl_name [[AS] alias]
        [{USE|IGNORE|FORCE} INDEX (key_list)]
  | ( table_references )
  | { OJ table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }

join_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_condition]
  | table_reference STRAIGHT_JOIN table_factor
  | table_reference STRAIGHT_JOIN table_factor ON condition
  | table_reference LEFT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [LEFT [OUTER]] JOIN table_factor
  | table_reference RIGHT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor

join_condition:
    ON conditional_expr
  | USING (column_list)

一個表引用還被稱爲一個聯合表達式。

SQL標準相比,table_factor的語法被擴展了。SQL標準只接受table_reference,而不是圓括號內的一系列條目。

如果我們把一系列table_reference條目中的每個逗號都看作相當於一個內部聯合,則這是一個穩妥的擴展。例如:

SELECT * FROM t1 LEFT JOIN (t2, t3, t4)
                 ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)

相當於:

SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)
                 ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)

MySQL中,CROSS JOIN從語法上說與INNER JOIN等同(兩者可以互相替換。在標準SQL中,兩者是不等同的。INNER JOINON子句同時使用,CROSS JOIN以其它方式使用。

通常,在只含有內部聯合運行的聯合表達式中,圓括號可以被忽略。MySQL也支持嵌套的聯合(見7.2.10節,“MySQL如何優化嵌套Join”)。

通常,您不應對ON部分有任何條件。ON部分用於限定在結果集合中您想要哪些行。但是,您應在WHERE子句中指定這些條件。這條規則有一些例外。

在前面的清單中顯示的{ OJ ... LEFT OUTER JOIN ...}語法的目的只是爲了保持與ODBC的兼容性。語法中的花括號應按字面書寫;該括號不是中間語法。中間語法用於語法描述的其它地方。

·         表引用可以使用tbl_name AS alias_nametbl_name 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;

·         ON條件句是可以被用於WHERE子句的格式的任何條件表達式。

·         如果對於在LEFT JOIN中的ONUSING部分中的右表沒有匹配的記錄,則所有列被設置爲NULL的一個行被用於右表。如果一個表在其它表中沒有對應部分,您可以使用這種方法在這種表中查找記錄:

·                mysql> SELECT table1.* FROM table1
·                    ->        LEFT JOIN table2 ON table1.id=table2.id
·                    ->        WHERE table2.id IS NULL;

本例查找在table1中含有一個id值的所有行。同時,在table2中沒有此id值(即,table1中的所有行在table2中沒有對應的行)。本例假設table2.id被定義爲NOT NULL。請參見7.2.9節,“MySQL如何優化LEFT JOIN和RIGHT JOIN”

·         USING(column_list)子句用於爲一系列的列進行命名。這些列必須同時在兩個表中存在。如果表a和表b都包含列c1, c2c3,則以下聯合會對比來自兩個表的對應的列:

·                a LEFT JOIN b USING (c1,c2,c3)

·         兩個表的NATURAL [LEFT] JOIN被定義爲與INNER JOIN語義相同,或與使用USING子句的LEFT JOIN語義相同。USING子句用於爲同時存在於兩個表中的所有列進行命名。

·         INNER JOIN和,(逗號)在無聯合條件下是語義相同的:兩者都可以對指定的表計算出笛卡兒乘積(也就是說,第一個表中的每一行被聯合到第二個表中的每一行)。

·         RIGHT JOIN的作用與LEFT JOIN的作用類似。要使代碼可以在數據庫內移植,建議您使用LEFT JOIN代替RIGHT JOIN

·         STRAIGHT_JOINJOIN相同。除了有一點不一樣,左表會在右表之前被讀取。STRAIGH_JOIN可以被用於這樣的情況,即聯合優化符以錯誤的順序排列表。

您可以提供提示,當從一個表中恢復信息時,MySQL應使用哪個索引。通過指定USE INDEXkey_list),您可以告知MySQL只使用一個索引來查找表中的行。另一種語法IGNORE INDEXkey_list)可以被用於告知MySQL不要使用某些特定的索引。如果EXPLAIN顯示MySQL正在使用來自索引清單中的錯誤索引時,這些提示會有用處。

您也可以使用FORCE INDEX,其作用接近USE INDEXkey_list),不過增加了一項作用,一次表掃描被假設爲代價很高。換句話說,只有當無法使用一個給定的索引來查找表中的行時,才使用表掃描。

USE KEYIGNORE KEYFORCE KEYUSE INDEXIGNORE INDEXFORCE INDEX的同義詞。

註釋:當MySQL決定如何在表中查找行並決定如何進行聯合時,使用USE INDEXIGNORE INDEXFORCE INDEX只會影響使用哪些索引。當分解一個ORDER BYGROUP BY時,這些語句不會影響某個索引是否被使用。

部分的聯合示例:

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;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
    ->          WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
    ->          WHERE key1=1 AND key2=2 AND key3=3;

7.2.9節,“MySQL如何優化LEFT JOIN和RIGHT JOIN”

註釋:自然聯合和使用USING的聯合,包括外部聯合變量,依據SQL:2003標準被處理。這些變更時MySQL與標準SQL更加相符。不過,對於有些聯合,這些變更會導致不同的輸出列。另外,有些查詢在舊版本(5.0.12以前)工作正常,但也必須重新編寫,以符合此標準。對於有關當前聯合處理和舊版本中的聯合處理的效果的對比,以下列表提供了更詳細的信息。

·         NATURAL聯合或USING聯合的列會與舊版本不同。特別是,不再出現冗餘的輸出列,用於SELECT *擴展的列的順序會與以前不同。

示例:

CREATE TABLE t1 (i INT, j INT);
CREATE TABLE t2 (k INT, j INT);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t2 VALUES(1,1);
SELECT * FROM t1 NATURAL JOIN t2;
SELECT * FROM t1 JOIN t2 USING (j);

對於舊版本,語句會產生以下輸出:

+------+------+------+------+
| i    | j    | k    | j    |
+------+------+------+------+
|    1 |    1 |    1 |    1 |
+------+------+------+------+
+------+------+------+------+
| i    | j    | k    | j    |
+------+------+------+------+
|    1 |    1 |    1 |    1 |
+------+------+------+------+

在第一個SELECT語句中,列i同時出現在兩個表中,爲一個聯合列,所以,依據標準SQL,該列在輸出中只出現一次。與此類似,在第二個SELECT語句中,列jUSING子句中被命名,應在輸出中只出現一次。但是,在兩種情況下,冗餘的列均沒被消除。另外,依據標準SQL,列的順序不正確。

現在,語句產生如下輸出:

+------+------+------+
| j    | i    | k    |
+------+------+------+
|    1 |    1 |    1 |
+------+------+------+
+------+------+------+
| j    | i    | k    |
+------+------+------+
|    1 |    1 |    1 |
+------+------+------+

冗餘的列被消除,並且依據標準SQL,列的順序是正確的:

o        第一,兩表共有的列,按在第一個表中的順序排列

o        第二,第一個表中特有的列,按該表中的順序排列

o        第三,第二個表中特有的列,按該表中的順序排列

·         對多方式自然聯合的估算會不同。方式要求重新編寫查詢。假設您有三個表t1(a,b), t2(c,b)t3(a,c),每個表有一行:t1(1,2), t2(10,2)t3(7,10)。同時,假設這三個表具有NATURAL JOIN

·                SELECT  FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;

在舊版本中,第二個聯合的左操作數被認爲是t2,然而它應該爲嵌套聯合(t1 NATURAL JOIN t2)。結果,對t3的列進行檢查時,只檢查其在t2中的共有列。如果t3t1有共有列,這些列不被用作equi-join列。因此,在舊版本的MySQL中,前面的查詢被轉換爲下面的equi-join

SELECT  FROM t1, t2, t3
  WHERE t1.b = t2.b AND t2.c = t3.c;

此聯合又省略了一個equi-join謂語(t1.a = t3.a)。結果是,該聯合產生一個行,而不是空結果。正確的等價查詢如下:

SELECT  FROM t1, t2, t3
  WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;

如果您要求在當前版本的MySQL中獲得和舊版本中相同的查詢結果,應把自然聯合改寫爲第一個equi-join

·         在舊版本中,逗號操作符(,)和JOIN均有相同的優先權,所以聯合表達式t1, t2 JOIN t3被理解爲((t1, t2) JOIN t3)。現在,JOIN有更高的優先權,所以表達式被理解爲(t1, (t2 JOIN t3))。這個變更會影響使用ON子句的語句,因爲該子句只參閱聯合操作數中的列。優先權的變更改變了對什麼是操作數的理解。

示例:

CREATE TABLE t1 (i1 INT, j1 INT);
CREATE TABLE t2 (i2 INT, j2 INT);
CREATE TABLE t3 (i3 INT, j3 INT);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t2 VALUES(1,1);
INSERT INTO t3 VALUES(1,1);
SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);

在舊版本中,SELECT是合法的,因爲t1, t2被隱含地歸爲(t1,t2)。現在,JOIN取得了優先權,因此用於ON子句的操作數是t2t3。因爲t1.i1不是任何一個操作數中的列,所以結果是出現在'on clause'中有未知列't1.i1'的錯誤。要使聯合可以被處理,用使用圓括號把前兩個表明確地歸爲一組,這樣用於ON子句的操作數爲(t1,t2)t3

SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);

本變更也適用於INNER JOINCROSS JOINLEFT JOINRIGHT JOIN

·         在舊版本中,ON子句可以參閱在其右邊命名的表中的列。現在,ON子句只能參閱操作數。

示例:

CREATE TABLE t1 (i1 INT);
CREATE TABLE t2 (i2 INT);
CREATE TABLE t3 (i3 INT);
SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;

在舊版本中,SELECT語句是合法的。現在該語句會運行失敗,出現在'on clause'中未知列'i3'的錯誤。這是因爲i3t3中的一個表,而t3不是ON子句中的操作數。本語句應進行如下改寫:

SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);

·         在舊版本中,一個USING子句可以被改寫爲一個ON子句。ON子句對比了相應的列。例如,以下兩個子句具有相同的語義:

·                a LEFT JOIN b USING (c1,c2,c3)
·                a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3

現在,這兩個子句不再是一樣的:

o        在決定哪些行滿足聯合條件時,兩個聯合保持語義相同。

o        在決定哪些列顯示SELECT *擴展時,兩個聯合的語義不相同。USING聯合選擇對應列中的合併值,而ON聯合選擇所有表中的所有列。對於前面的USING聯合,SELECT *選擇這些值:

o                     COALESCE(a.c1,b.c1), COALESCE(a.c2,b.c2), COALESCE(a.c3,b.c3)

對於ON聯合,SELECT *選擇這些值:

a.c1, a.c2, a.c3, b.c1, b.c2, b.c3

使用內部聯合時,COALESCE(a.c1,b.c1)a.c1b.c1相同,因爲兩列將具有相同的值。使用外部聯合時(比如LEFT JOIN),兩列中有一列可以爲NULL。該列將會從結果中被忽略。

13.2.7.2. UNION語法
 

SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]

UNION用於把來自許多SELECT語句的結果組合到一個結果集合中。

列於每個SELECT語句的對應位置的被選擇的列應具有相同的類型。(例如,被第一個語句選擇的第一列應和被其它語句選擇的第一列具有相同的類型。)在第一個SELECT語句中被使用的列名稱也被用於結果的列名稱。

SELECT語句爲常規的選擇語句,但是受到如下的限定:

·         只有最後一個SELECT語句可以使用INTO OUTFILE

·         HIGH_PRIORITY不能與作爲UNION一部分的SELECT語句同時使用。如果您對第一個SELECT指定了HIGH_PRIORITY,則不會起作用。如果您對其它後續的SELECT語句指定了HIGH_PRIORITY,則會產生語法錯誤。

如果您對UNION不使用關鍵詞ALL,則所有返回的行都是唯一的,如同您已經對整個結果集合使用了DISTINCT。如果您指定了ALL,您會從所有用過的SELECT語句中得到所有匹配的行。

DISTINCT關鍵詞是一個自選詞,不起任何作用,但是根據SQL標準的要求,在語法中允許採用。(在MySQL中,DISTINCT代表一個共用體的默認工作性質。)

您可以在同一查詢中混合UNION ALLUNION DISTINCT。被混合的UNION類型按照這樣的方式對待,即DISTICT共用體覆蓋位於其左邊的所有ALL共用體。DISTINCT共用體可以使用UNION DISTINCT明確地生成,或使用UNION(後面不加DISTINCTALL關鍵詞)隱含地生成。

如果您想使用ORDER BYLIMIT子句來對全部UNION結果進行分類或限制,則應對單個地SELECT語句加圓括號,並把ORDER BYLIMIT放到最後一個的後面。以下例子同時使用了這兩個子句:

(SELECT a FROM tbl_name WHERE a=10 AND B=1)
UNION
(SELECT a FROM tbl_name WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;

這種ORDER BY不能使用包括表名稱(也就是,採用tbl_name.col_name格式的名稱)列引用。可以在第一個SELECT語句中提供一個列別名,並在ORDER BY中參閱別名,或使用列位置在ORDER BY中參閱列。(首選採用別名,因爲不建議使用列位置。)

另外,如果帶分類的一列有別名,則ORDER BY子句必須引用別名,而不能引用列名稱。以下語句中的第一個語句必須運行,但是第二個會運行失敗,出現在'order clause'中有未知列'a'的錯誤:

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;

To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT:   爲了對單個SELECT使用ORDER BYLIMIT,應把子句放入圓括號中。圓括號包含了SELECT

(SELECT a FROM tbl_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM tbl_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

圓括號中用於單個SELECT語句的ORDER BY只有當與LIMIT結合後,才起作用。否則,ORDER BY被優化去除。

UNION結果集合中的列的類型和長度考慮了被所有SELECT語句恢復的數值。例如,考慮如下語句:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| bbbbbbbbbb    |
+---------------+

(在部分早期版本的MySQL中,第二行已被刪節到長度爲1。)

13.2.8. Subquery語法

子查詢是另一個語句中的一個SELECT語句。

MySQL支持SQL標準要求的所有子查詢格式和操作,也支持MySQL特有的幾種特性。

以下是一個子查詢的例子:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

在本例中,SELECT * FROM t1...是外部查詢(或外部語句),SELECT column1 FROM t2)是子查詢。我們可以說子查詢嵌套在外部查詢中。實際上,子查詢也可以嵌套在其它子查詢中,嵌套程度可以很深。子查詢必須要位於圓括號中。

子查詢的主要優勢爲:

·         子查詢允許結構化的查詢,這樣就可以把一個語句的每個部分隔離開。

·         有些操作需要複雜的聯合和關聯。子查詢提供了其它的方法來執行這些操作。

·         在許多人看來,子查詢是可讀的。實際上,子查詢給予人們調用早期SQL“結構化查詢語言”的原本的想法,這是子查詢的創新。

以下是一個示例語句。該語句顯示了有關子查詢語法的要點。子查詢語法由SQL標準指定並被MySQL支持。

DELETE FROM t1
WHERE s11 > ANY
(SELECT COUNT(*) /* no hint */ FROM t2
WHERE NOT EXISTS
(SELECT * FROM t3
WHERE ROW(5*t2.s1,77)=
(SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
(SELECT * FROM t5) AS t5)));

一個子查詢會返回一個標量(單一值)、一個行、一個列或一個表(一行或多行及一列或多列)。這些子查詢被稱爲標量、列、行和表子查詢。可返回一個特定種類結果的子查詢經常只被用於特定的語境中,在後面各節中有說明。

有些語句可以使用子查詢。對這些語句的類型基本沒有限定。子查詢可以包括普通SELECT可以包括的任何關鍵詞或子句:DISTINCT, GROUP BY, ORDER BY, LIMIT, 聯合, 索引提示, UNION結構化, 評註和函數等。

有一個限定是,一個子查詢的外部語句必須是以下語句之一:SELECT, INSERT, UPDATE, DELETE, SETDO。還有一個限定是,目前,您不能在一個子查詢中修改一個表,又在同一個表中選擇。這適用於DELETE, INSERT, REPLACEUPDATE語句。在附錄I:特性限制中給出了對子查詢使用的更綜合的討論。

13.2.8.1. 子查詢作爲標量操作數

子查詢最簡單的形式是返回單一值的標量子查詢。標量子查詢是一個單一操作數。只要單一列值或文字是合法的,並且您希望子查詢具有所有操作數都具有的特性,則您就可以使用子查詢。操作數具有的特性包括:一個數據類型、一個長度、一個指示是否可以爲NULL的標誌等。舉例說明:
CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
INSERT INTO t1 VALUES(100, 'abcde');
SELECT (SELECT s2 FROM t1);

在本SELECT中的子查詢返回一個單一值('abcde')。該單一值的數據類型爲CHAR,長度爲5,字符集和整序與在CREATE TABLE時有效的默認值相同,並有一個指示符號,指示列中的值可以爲NULL。實際上,基本上所有的子查詢都爲NULL。如果在本例中使用的表爲空表,則子查詢的值應爲NULL

在有些情況下,標量子查詢不能使用。如果一個語句只允許一個文字值,您不能使用子查詢。例如,LIMIT要求文字整數自變量,LOAD DATA要求一個文字字符串文件名。您不能使用子查詢來提供這些值。

後面各節包括更簡練的結構(SELECT column1 FROM t1)。當您在這些章節中觀看例子時,請設想一下您自己的代碼包含更多樣、更復雜的結構。

舉例說明,假設我們製作兩個表:

CREATE TABLE t1 (s1 INT);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (s1 INT);
INSERT INTO t2 VALUES (2);

然後執行一個SELECT

SELECT (SELECT s1 FROM t2) FROM t1;

結果爲2,因爲t2中有一行包含s1s1有一個值爲2

一個標量子查詢可以爲一個表達式的一部分。不要忘記圓括號。即使是子查詢是一個爲函數提供自變量的操作數時,也不要忘記圓括號。舉例說明:

SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

13.2.8.2. 使用子查詢進行比較

子查詢最常見的一種使用方式如下:

non_subquery_operand comparison_operator (subquery)

comparison_operator是以下 操作符之一時:

=  >  <  >=  <=  <>

例如:

  ... 'a' = (SELECT column1 FROM t1)

有時,子查詢的合法位置只能在比較式的右側,您可以發現,在有些舊的DBMSs中仍保持這一點。

以下是一個常見格式的子查詢比較的例子。您不能使用聯合進行此類比較。表t1中有些值與表t2中的最大值相同。該比較可以查找出所有這類值:

SELECT column1 FROM t1
WHERE column1 = (SELECT MAX(column2) FROM t2);

下面還有另一個例子,該例子也不可能使用聯合,因爲該例子涉及對其中一個表進行總計。表t1中的有些行含有的值會在給定的列中出現兩次。該例子可以查找出所有這些行:

SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);

對於採用這些操作符之一進行的比較,子查詢必須返回一個標量。有一個例外,那就是=可以和行子查詢同時使用。請參見13.2.8.5節,“行子查詢”

13.2.8.3. 使用ANY, IN和SOME進行子查詢

語法:

operand comparison_operator ANY (subquery)
operand IN (subquery)
operand comparison_operator SOME (subquery)

ANY關鍵詞必須後面接一個比較操作符。ANY關鍵詞的意思是“對於在子查詢返回的列中的任一數值,如果比較結果爲TRUE的話,則返回TRUE”。例如:

SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

假設表t1中有一行包含(10)。如果表t2包含(21147),則表達式爲TRUE,因爲t2中有一個值爲7,該值小於10。如果表t2包含(2010),或者如果表t2爲空表,則表達式爲FALSE。如果表t2包含(NULL, NULL, NULL),則表達式爲UNKNOWN

詞語IN是=ANY的別名。因此,這兩個語句是一樣的:

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

不過,NOT IN不是<> ANY的別名,但是是<> ALL的別名。請參見13.2.8.4節,“使用ALL進行子查詢

詞語SOMEANY的別名。因此,這兩個語句是一樣的:

SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);

使用詞語SOME的機會很少,但是本例顯示了爲什麼SOME是有用的。對於多數人來說,英語短語“a is not equal to any b”的意思是“沒有一個ba相等”,但是在SQL語法中不是這個意思。該語法的意思是“有部分ba不相等”。使用<> SOME有助於確認每個人都理解該查詢的真正含義。

13.2.8.4. 使用ALL進行子查詢

語法:
operand comparison_operator ALL (subquery)

詞語ALL必須接在一個比較操作符的後面。ALL的意思是“對於子查詢返回的列中的所有值,如果比較結果爲TRUE,則返回TRUE。”例如:

SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

假設表1中有一行包含(10)。如果表t2包含(-50,+5),則表達式爲TRUE,因爲10t2中的所有三個值都大。如果表t2包含(126NULL,-100),則表達式爲FALSE,因爲表t2中有一個值12大於10。如果表t2包含(0NULL1),則表達式爲unknown

最後,如果表t2爲空表,則結果爲TRUE。因此,當表t2爲空表時,以下語句爲TRUE

SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

但是,當表t2爲空表時,本語句爲NULL

SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

另外,當表t2爲空表時,以下語句爲NULL

SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

通常,包含NULL值的表和空表爲“邊緣情況”。當編寫子查詢代碼時,都要考慮您是否把這兩種可能性計算在內。

NOT IN<> ALL的別名。因此,以下兩個語句是相同的:

SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);

13.2.8.5. 行子查詢

對於本點的討論屬於標量或列子查詢,即返回一個單一值或一列值的子查詢。行子查詢是一個能返回一個單一行的子查詢變量,因此可以返回一個以上的列值。以下是兩個例子:
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

如果在表t2的一個行中,column1=1並且column2=2,則查詢結果均爲TRUE

表達式(12)和ROW12)有時被稱爲行構造符。兩者是等同的,在其它的語境中,也是合法的。例如,以下兩個語句在語義上是等同的(但是目前只有第二個語句可以被優化):

  SELECT * FROM t1 WHERE (column1,column2) = (1,1);
  SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

行構造符通常用於與對能返回兩個或兩個以上列的子查詢進行比較。例如,以下查詢可以答覆請求,“在表t1中查找同時也存在於表t2中的所有的行”:

SELECT column1,column2,column3
FROM t1
WHERE (column1,column2,column3) IN
(SELECT column1,column2,column3 FROM t2);

13.2.8.6. EXISTS和NOT EXISTS

如果一個子查詢返回任何的行,則EXISTS subqueryFALSE。例如:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

過去,EXISTS子查詢以SELECT *爲開始,但是可以以SELECT 5SELECT column1或其它的爲開始。MySQL在這類子查詢中忽略了SELECT清單,因此沒有區別。

對於前面的例子,如果t2包含任何行,即使是隻含有NULL值的行,EXISTS條件也爲TRUE。這實際上是一個不可能的例子,因爲基本上所有的[NOT] EXISTS子查詢均包含關聯。以下是一些更現實的例子:

·         哪些種類的商店出現在一個或多個城市裏?

·                SELECT DISTINCT store_type FROM stores
·                  WHERE EXISTS (SELECT * FROM cities_stores
·                                WHERE cities_stores.store_type = stores.store_type);

·         哪些種類的商店沒有出現在任何城市裏?

·                SELECT DISTINCT store_type FROM stores
·                  WHERE NOT EXISTS (SELECT * FROM cities_stores
·                                    WHERE cities_stores.store_type = stores.store_type);

·         哪些種類的商店出現在所有城市裏?

·                SELECT DISTINCT store_type FROM stores s1
·                  WHERE NOT EXISTS (
·                    SELECT * FROM cities WHERE NOT EXISTS (
·                      SELECT * FROM cities_stores
·                       WHERE cities_stores.city = cities.city
·                       AND cities_stores.store_type = stores.store_type));

最後一個例子是一個雙嵌套NOT EXISTS查詢。也就是,該查詢包含一個NOT EXISTS子句,該子句又包含在一個NOT EXISTS子句中。該查詢正式地回答了這個問題,“是否有某個城市擁有沒有列在Stores中的商店?”。可以比較容易的說,一個帶嵌套的NOT EXISTS可以回答這樣的問題,“是否對於所有的yx都爲TRUE?”

13.2.8.7. 關聯子查詢

相關聯的子查詢是一個包含對錶的引用的子查詢。該表也顯示在外部查詢中。例如:
SELECT * FROM t1 WHERE column1 = ANY
(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

注意,即使子查詢的FROM子句不提及表t1,該子查詢也會包含一個對t1中一列的引用。所以,MySQL看上去位於子查詢的外部,並在外部查詢中查找t1

假設表t1包含一行,在此行中column1=5並且column2=6;同時,表t2包含一行,在此行中column1=5並且column2=7。簡單的表達式... WHERE column1 = ANY (SELECT column1 FROM t2)會爲TRUE。但是在本例中,在子查詢中的WHERE子句爲FALSE(因爲(56)不等於(57)),所以子查詢總體上爲FALSE

範圍劃分規則:MySQL從內到外進行評估。例如:

SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));

在本語句中,x.column2必須是表t2中的列,因爲SELECT column1 FROM t2 AS x ...t2進行了重命名。它不是表t1中的列,因爲SELECT column1 FROM t1 ...是一個更靠外的外部查詢。

對於HAVINGORDER BY子句中的子查詢,MySQL也會在外部選擇清單中尋找列名稱。

對於特定的情況,相關聯的子查詢被優化。例如:

val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)

否則,這些子查詢效率不高,可能速度會慢。把查詢作爲聯合進行改寫可能會改進效率。

相關聯的子查詢不能從外部查詢中引用總計函數的結果。

13.2.8.8. FROM子句中的子查詢

SELECT語句的FROM子句中,子查詢是合法的。實際的語法是:

SELECT ... FROM (subquery) [AS] name ...

[AS] name子句是強制性的,因爲FROM子句中的每個表必須有一個名稱。在子查詢選擇列表中的任何列都必須有唯一的名稱。您可以在本手冊中的其它地方找到對本語法的說明。在該處,所用的詞語是“導出表”。

爲了進行詳細說明,假設您有如下一個表:

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

下面使用了示例表,解釋了在FROM子句中如何使用子查詢:

INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;

結果:2, '2', 4.0

下面是另一個例子:假設您想了解一個分類後的表的一組和的平均值。採用如下操作:

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

不過,本查詢提供所需的信息:

SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;

注意,在子查詢中使用的列名稱(sum_column1)被整理到外部查詢中。

FROM子句中的子查詢可以返回標量、列、行或表。FROM子句中的子查詢不能爲有關聯的子查詢。

即使對EXPLAIN語句(即建立臨時導出表),FROM子句中的子查詢也會被執行。這是因爲在優化過程中,上一級的查詢需要有關所有表的信息。

13.2.8.9. 子查詢錯誤

以下錯誤只適用於子查詢。本節把這些錯誤歸在一起。

·         來自子查詢的列的數目不正確

·                ERROR 1241 (ER_OPERAND_COL)
·                SQLSTATE = 21000
·                Message = "Operand should contain 1 column(s)"

在出現以下情況時,發生此錯誤:

SELECT (SELECT column1, column2 FROM t2) FROM t1;

如果您的目的是進行比較,您可以使用能返回多個列的子查詢。請參見13.2.8.5節,“行子查詢”。不過,在其它的語境下,子查詢必須爲標量操作數。

·         來自子查詢的行的數目不正確:

·                ERROR 1242 (ER_SUBSELECT_NO_1_ROW)
·                SQLSTATE = 21000
·                Message = "Subquery returns more than 1 row"

如果在語句中,子查詢返回的行多於一個,則發生此錯誤。請考慮以下例子:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

如果SELECT column1 FROM t2只返回一行,則將執行以前的查詢。如果子查詢返回的行多於一個,則將出現錯誤1242。在這種情況下,該查詢將被改寫爲:

SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);

·         在子查詢中表格使用不正確:

·                Error 1093 (ER_UPDATE_TABLE_USED)
·                SQLSTATE = HY000
·                Message = "You can't specify target table 'x'
·                for update in FROM clause"

在如下情況下,發生該錯誤:

UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);

SELECT語句一樣,在UPDATEDELETE語句中,子查詢是合法的。所以您可以在UPDATE語句中使用子查詢進行賦值。不過,您不能把同一個表(在本例中爲表t1)既用於子查詢的FROM子句,又用於更新目標。

對於事務存儲引擎,子查詢的錯誤會導致整個語句失效。對於非事務存儲引擎,在遇到錯誤之前進行的數據修訂會被保留。

13.2.8.10. 優化子查詢

開發過程不斷進展,所以從長遠來看,沒有一個可靠的優化技巧。有些技巧您可能會感興趣,並原意採用:

·         有些子句會影響在子查詢中的行的數量和順序。使用這類子句。例如:

·                SELECT * FROM t1 WHERE t1.column1 IN
·                (SELECT column1 FROM t2 ORDER BY column1);
·                SELECT * FROM t1 WHERE t1.column1 IN
·                (SELECT DISTINCT column1 FROM t2);
·                SELECT * FROM t1 WHERE EXISTS
·                (SELECT * FROM t2 LIMIT 1);

·         用子查詢替換聯合。例如,試進行如下操作:

·                SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
·                SELECT column1 FROM t2);

代替如下操作:

SELECT DISTINCT t1.column1 FROM t1, t2
WHERE t1.column1 = t2.column1;

·         部分子查詢可以被轉換爲聯合,以便與不支持子查詢的舊版本的MySQL相兼容。不過,在有些情況下,把子查詢轉化爲聯合可以提高效果。請參見13.2.8.11節,“把子查詢作爲用於早期MySQL版本的聯合進行改寫”

·         把子句從子查詢的外部轉移到內部。例如,使用此查詢:

·                SELECT * FROM t1
·                WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);

代替此查詢:

SELECT * FROM t1
WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);

另一個例子是,使用此查詢:

SELECT (SELECT column1 + 5 FROM t1) FROM t2;

代替此查詢:

SELECT (SELECT column1 FROM t1) + 5 FROM t2;

·         使用行子查詢,代替關聯子查詢。舉例說明,使用此查詢:

·                SELECT * FROM t1
·                WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);

代替此查詢:

SELECT * FROM t1
WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
AND t2.column2=t1.column2);

·         Use NOT (a = ANY (...)) rather than a <> ALL (...).

·         Use x = ANY (table containing (1,2)) rather than x=1 OR x=2.

·         Use = ANY rather than EXISTS.

·         對於只返回一行的無關聯子查詢,IN的速度慢於=。舉例說明,使用此查詢:

·                SELECT * FROM t1 WHERE t1.col_name
·                = (SELECT a FROM t2 WHERE b = some_const);

代替此查詢:

SELECT * FROM t1 WHERE t1.col_name
IN (SELECT a FROM t2 WHERE b = some_const);

使用這些技巧可以使程序更快或更慢。使用BENCHMARK()函數等MySQL工具,您可以瞭解到在您所處的情況下,哪些技巧會有幫助。

MySQL本身進行的部分優化包括:

·         MySQL只執行一次無關聯子查詢。使用EXPLAIN確認給定的子查詢確實是無關聯的。

·         MySQL改寫IN, ALL, ANYSOME子查詢,目的是如果子查詢中的select-list列已編制索引,則能發揮出此優勢。

·         MySQL使用index-lookup函數代替以下格式的子查詢。EXPLAIN把此函數描述爲特殊的聯合類型(unique_subqueryindex_subquery):

·                ... IN (SELECT indexed_column FROM single_table ...)

·         當表達式中不包含NULL值或空集時,MySQL使用一個包含MIN()MAX()的表達式,對以下格式的表達式進行擴展:

·                value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)

例如,本WHERE子句:

WHERE 5 > ALL (SELECT x FROM t)

可以用優化符進行如下處理:

WHERE 5 > (SELECT MAX(x) FROM t)

MySQL內部手冊中有一章名爲“MySQL如何轉換子查詢”,可以從http://dev.mysql.com/doc/獲取。

13.2.8.11. 把子查詢作爲用於早期MySQL版本的聯合進行改寫

在較早版本的MySQL中(早於MySQL 4.1),只支持INSERT...SELECTREPLACE...SELECT...格式的帶嵌套的查詢。雖然在MySQL 5.1中沒有這種情況,但有時,仍然有其它的方法測試一組值的從屬關係。並且,在有些情況下,不僅可以在沒有子查詢時對查詢進行改寫,而且有時使用這些方法比使用子查詢效率更高。這些方法之一是IN()結構:

舉例說明,本查詢:

SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

可以被改寫爲:

SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;

以下查詢:

SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

也可以使用IN()進行改寫:

SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
WHERE table2.id IS NULL;

LEFT [OUTER] JOIN可以比對應的子查詢更快,因爲服務器可能對其進行更好的優化——這一點對於單獨的MySQL服務器並不明確。在SQL-92之前,不存在外部聯合,因此在做某些事情時,子查詢是唯一的方法。現在,MySQL服務器和其它許多先進的數據庫系統都能提供多種的外部聯合類型。

MySQL支持multiple-table DELETE語句,該語句可以被用於高效地刪除行。刪除時依據來自一個表或同時來自多個表的信息。同時也支持Multiple-table UPDATE語句。

13.2.9. TRUNCATE語法

TRUNCATE [TABLE] tbl_name

TRUNCATE TABLE用於完全清空一個表。從邏輯上說,該語句與用於刪除所有行的DELETE語句等同,但是在有些情況下,兩者在使用上有所不同。

對於InnoDB表,如果有需要引用表的外鍵限制,則TRUNCATE TABLE被映射到DELETE上;否則使用快速刪減(取消和重新創建表)。使用TRUNCATE TABLE重新設置AUTO_INCREMENT計數器,設置時不考慮是否有外鍵限制。

對於其它存儲引擎,在MySQL 5.1中,TRUNCATE TABLEDELETE FROM有以下幾處不同:

·         刪減操作會取消並重新創建表,這比一行一行的刪除行要快很多。

·         刪減操作不能保證對事務是安全的;在進行事務處理和表鎖定的過程中嘗試進行刪減,會發生錯誤。

·         被刪除的行的數目沒有被返回。

·         只要表定義文件tbl_name.frm是合法的,則可以使用TRUNCATE TABLE把表重新創建爲一個空表,即使數據或索引文件已經被破壞。

·         表管理程序不記得最後被使用的AUTO_INCREMENT值,但是會從頭開始計數。即使對於MyISAMInnoDB也是如此。MyISAMInnoDB通常不再次使用序列值。

·         當被用於帶分區的表時,TRUNCATE TABLE會保留分區;即,數據和索引文件被取消並重新創建,同時分區定義(.par)文件不受影響。

TRUNCATE TABLE是在MySQL中採用的一個Oracle SQL擴展。

13.2.10. UPDATE語法

Single-table語法:

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT row_count]

Multiple-table語法:

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]

UPDATE語法可以用新值更新原有錶行中的各列。SET子句指示要修改哪些列和要給予哪些值。WHERE子句指定應更新哪些行。如果沒有WHERE子句,則更新所有的行。如果指定了ORDER BY子句,則按照被指定的順序對行進行更新。LIMIT子句用於給定一個限值,限制可以被更新的行的數目。

UPDATE語句支持以下修飾符:

·         如果您使用LOW_PRIORITY關鍵詞,則UPDATE的執行被延遲了,直到沒有其它的客戶端從表中讀取爲止。

·         如果您使用IGNORE關鍵詞,則即使在更新過程中出現錯誤,更新語句也不會中斷。如果出現了重複關鍵字衝突,則這些行不會被更新。如果列被更新後,新值會導致數據轉化錯誤,則這些行被更新爲最接近的合法的值。

如果您在一個表達式中通過tbl_name訪問一列,則UPDATE使用列中的當前值。例如,以下語句把年齡列設置爲比當前值多一:

mysql> UPDATE persondata SET age=age+1;

UPDATE賦值被從左到右評估。例如,以下語句對年齡列加倍,然後再進行增加:

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

如果您把一列設置爲其當前含有的值,則MySQL會注意到這一點,但不會更新。

如果您把被已定義爲NOT NULL的列更新爲NULL,則該列被設置到與列類型對應的默認值,並且累加警告數。對於數字類型,默認值爲0;對於字符串類型,默認值爲空字符串('');對於日期和時間類型,默認值爲“zero”值。

UPDATE會返回實際被改變的行的數目。Mysql_info() C API函數可以返回被匹配和被更新的行的數目,以及在UPDATE過程中產生的警告的數量。

您可以使用LIMIT row_count來限定UPDATE的範圍。LIMIT子句是一個與行匹配的限定。只要發現可以滿足WHERE子句的row_count行,則該語句中止,不論這些行是否被改變。

如果一個UPDATE語句包括一個ORDER BY子句,則按照由子句指定的順序更新行。

您也可以執行包括多個表的UPDATE操作。table_references子句列出了在聯合中包含的表。該語法在13.2.7.1節,“JOIN語法”中進行了說明。以下是一個例子:

UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

以上的例子顯示出了使用逗號操作符的內部聯合,但是multiple-table UPDATE語句可以使用在SELECT語句中允許的任何類型的聯合,比如LEFT JOIN

註釋:您不能把ORDER BYLIMITmultiple-table UPDATE同時使用。

在一個被更改的multiple-table UPDATE中,有些列被引用。您只需要這些列的UPDATE權限。有些列被讀取了,但是沒被修改。您只需要這些列的SELECT權限。

如果您使用的multiple-table UPDATE語句中包含帶有外鍵限制的InnoDB表,則MySQL優化符處理表的順序可能與上下層級關係的順序不同。在此情況下,語句無效並被 回滾。同時,更新一個單一表,並且依靠ON UPDATE功能。該功能由InnoDB提供,用於對其它表進行相應的修改。請參見15.2.6.4節,“FOREIGN KEY約束”

目前,您不能在一個子查詢中更新一個表,同時從同一個表中選擇。

13.3. MySQL實用工具語句

13.3.1. DESCRIBE語法(獲取有關列的信息)

{DESCRIBE | DESC} tbl_name [col_name | wild]

DESCRIBE可以提供有關表中各列的信息。它是SHOW COLUMNS FROM的快捷方式。這些語句也可以顯示語句,用於閱覽。

13.5.4.3節,“SHOW COLUMNS語法”

col_name可以是一個列名稱,或一個包含‘%’和‘_’的通配符的字符串,用於獲得對於帶有與字符串相匹配的名稱的各列的輸出。沒有必要在引號中包含字符串,除非其中包含空格或其它特殊字符。

mysql> DESCRIBE city;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

NULL字段指示是否NULL可以被存儲在列中。

Key字段指示是否該列已編制索引。PRI的值指示該列是表的主鍵的一部分。UNI指示,該列是UNIQUE索引的一部分。MUL值指示,在列中某個給定值多次出現是允許的。

MUL將被顯示在UNIQUE索引中,原因之一是多個列會組合成一個複合UNIQUE索引;儘管列的組合是唯一的,但每個列仍可以多次出現同一個給定值。注意,在複合索引中,只有索引最左邊的列可以進入Key字段中。

默認字段指示,默認值被賦予該列。

Extra字段包含可以獲取的與給定列有關的附加信息。在我們的例子中,Extra字段指示,Id列使用AUTO_INCREMENT關鍵詞創建。

如果列類型與您預計的依據CREATE TABLE語句得出的列類型不同,則請注意,MySQL有時會改變列類型。請參見13.1.5.1節,“沉寂的列規格變更”

DESCRIBE語句被設立出來,用於與Oracle相兼容。

SHOW CREATE TABLESHOW TABLE STATUS語句也可以提供有關表的信息。請參見13.5.4節,“SHOW語法”

13.3.2. USE語法

USE db_name

USE db_name語句可以通告MySQLdb_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數據庫訪問作者表,並從db2數據庫訪問編輯表:

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

USE語句被設立出來,用於與Sybase相兼容。

13.4. MySQL事務處理和鎖定語句

MySQL通過SET AUTOCOMMIT, START TRANSACTION, COMMITROLLBACK等語句支持本地事務(在給定的客戶端連接中)。請參見13.4.1節,“START TRANSACTION, COMMIT和ROLLBACK語法”XA事務支持還可以允許MySQL參與分佈式事務。請參見13.4.7節,“XA事務”

13.4.1. START TRANSACTION, COMMIT和ROLLBACK語法

START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}

START TRANSACTIONBEGIN語句可以開始一項新的事務。COMMIT可以提交當前事務,是變更成爲永久變更。ROLLBACK可以 回滾當前事務,取消其變更。SET AUTOCOMMIT語句可以禁用或啓用默認的autocommit模式,用於當前連接。

自選的WORK關鍵詞被支持,用於COMMITRELEASE,與CHAINRELEASE子句。CHAINRELEASE可以被用於對事務完成進行附加控制。Completion_type系統變量的值決定了默認完成的性質。請參見5.3.3節,“服務器系統變量”

AND CHAIN子句會在當前事務結束時,立刻啓動一個新事務,並且新事務與剛結束的事務有相同的隔離等級。RELEASE子句在終止了當前事務後,會讓服務器斷開與當前客戶端的連接。包含NO關鍵詞可以抑制CHAINRELEASE完成。如果completion_type系統變量被設置爲一定的值,使連鎖或釋放完成可以默認進行,此時NO關鍵詞有用。

默認情況下,MySQL採用autocommit模式運行。這意味着,當您執行一個用於更新(修改)表的語句之後,MySQL立刻把更新存儲到磁盤中。

如果您正在使用一個事務安全型的存儲引擎(如InnoDB, BDBNDB簇),則您可以使用以下語句禁用autocommit模式:

SET AUTOCOMMIT=0;

通過把AUTOCOMMIT變量設置爲零,禁用autocommit模式之後,您必須使用COMMIT把變更存儲到磁盤中,或着如果您想要忽略從事務開始進行以來做出的變更,使用ROLLBACK

如果您想要對於一個單一系列的語句禁用autocommit模式,則您可以使用START TRANSACTION語句:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

使用START TRANSACTIONautocommit仍然被禁用,直到您使用COMMITROLLBACK結束事務爲止。然後autocommit模式恢復到原來的狀態。

BEGINBEGIN WORK被作爲START TRANSACTION的別名受到支持,用於對事務進行初始化。START TRANSACTION是標準的SQL語法,並且是啓動一個ad-hoc事務的推薦方法。BEGIN語句與BEGIN關鍵詞的使用不同。BEGIN關鍵詞可以啓動一個BEGIN...END複合語句。後者不會開始一項事務。請參見20.2.7節,“BEGIN ... END複合語句”

您也可以按照如下方法開始一項事務:

START TRANSACTION WITH CONSISTENT SNAPSHOT;

WITH CONSISTENT SNAPSHOT子句用於啓動一個一致的讀取,用於具有此類功能的存儲引擎。目前,該子句只適用於InnoDB。該子句的效果與發佈一個START TRANSACTION,後面跟一個來自任何InnoDB表的SELECT的效果一樣。請參見15.2.10.4節,“一致的非鎖定讀”

開始一項事務會造成一個隱含的UNLOCK TABLES被執行。

爲了獲得最好的結果,事務應只使用由單一事務存儲引擎管理的表執行。否則,會出現以下問題:

·         如果您使用的表來自多個事務安全型存儲引擎(例如InnoDBBDB),並且事務隔離等級不是SERIALIZABLE,則有可能當一個事務提交時,其它正在進行中的、使用同樣的表的事務將只會發生由第一個事務產生的變更。也就是,用混合引擎不能保證事務的原子性,並會造成不一致。(如果混合引擎事務不經常有,則您可以根據需要使用SET TRANSACTION ISOLATION LEVEL把隔離等級設置到SERIALIZABLE。)

·         如果您在事務中使用非事務安全型表,則對這些表的任何變更被立刻存儲,不論autocommit模式的狀態如何。

如果您在更新了事務中一個事務表之後,發佈一個ROLLBACK語句,則會出現一個ER_WARNING_NOT_COMPLETE_ROLLBACK警告。對事務安全型表的變更被 回滾,但是對非事務安全型表沒有變更。

每個事務被存儲在一個組塊中的二進制日誌中,在COMMIT之上。被回滾的事務不被計入日誌。(例外情況:對非事務表的更改不會被 回滾。如果一個被回滾的事務包括對非事務表的更改,則整個事務使用一個在末端的ROLLBACK語句計入日誌,以確保對這些表的更改進行復制。)見5.11.3節,“二進制日誌”

您可以使用SET TRANSACTION ISOLATION LEVEL更改事務的隔離等級。請參見13.4.6節,“SET TRANSACTION語法”

回滾可以慢速運行。在用戶沒有明確要求時,也可以進行回滾(例如,當錯誤發生時)。因此,在明確地和隱含的(ROLLBACK SQL命令)回滾時,SHOW PROCESSLIST會在Stage列中顯示Rolling back,用於連接。

13.4.2. 不能回滾的語句

有些語句不能被回滾。通常,這些語句包括數據定義語言(DDL)語句,比如創建或取消數據庫的語句,和創建、取消或更改表或存儲的子程序的語句。

您在設計事務時,不應包含這類語句。如果您在事務的前部中發佈了一個不能被回滾的語句,則後部的其它語句會發生錯誤,在這些情況下,通過發佈ROLLBACK語句不能 回滾事務的全部效果。

13.4.3. 會造成隱式提交的語句

以下語句(以及同義詞)均隱含地結束一個事務,似乎是在執行本語句前,您已經進行了一個COMMIT

·         ALTER FUNCTION, ALTER PROCEDURE, ALTER TABLE, BEGIN, CREATE DATABASE, CREATE FUNCTION, CREATE INDEX, CREATE PROCEDURE, CREATE TABLE, DROP DATABASE, DROP FUNCTION, DROP INDEX, DROP PROCEDURE, DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET AUTOCOMMIT=1, START TRANSACTION, TRUNCATE TABLE, UNLOCK TABLES.

·         噹噹前所有的表均被鎖定時,UNLOCK TABLES可以提交事務。

·         CREATE TABLE, CREATE DATABASE DROP DATABASE, TRUNCATE TABLE, ALTER FUNCTION, ALTER PROCEDURE, CREATE FUNCTION, CREATE PROCEDURE, DROP FUNCTIONDROP PROCEDURE等語句會導致一個隱含提交。

·         InnoDB中的CREATE TABLE語句被作爲一個單一事務進行處理。這意味着,來自用戶的ROLLBACK不會撤銷用戶在事務處理過程中創建的CREATE TABLE語句。

事務不能被嵌套。這是隱含COMMIT的結果。當您發佈一個START TRANSACTION語句或其同義詞時,該COMMIT被執行,用於任何當前事務。

13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT語法

SAVEPOINT identifier
ROLLBACK [WORK] TO SAVEPOINT identifier
RELEASE SAVEPOINT identifier

InnoDB支持SQL語句SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT和自選的用於ROLLBACKWORK關鍵詞。

SAVEPOINT語句用於設置一個事務保存點,帶一個標識符名稱。如果當前事務有一個同樣名稱的保存點,則舊的保存點被刪除,新的保存點被設置。

ROLLBACK TO SAVEPOINT語句會向以命名的保存點回滾一個事務。如果在保存點被設置後,當前事務對行進行了更改,則這些更改會在 回滾中被撤銷。但是,InnoDB不會釋放被存儲在保存點之後的存儲器中的行鎖定。(注意,對於新插入的行,鎖定信息被存儲在行中的事務ID承載;鎖定沒有被分開存儲在存儲器中。在這種情況下,行鎖定在撤銷中被釋放。)在被命名的保存點之後設置的保存點被刪除。

如果語句返回以下錯誤,則意味着不存在帶有指定名稱的保存點:

ERROR 1181: Got error 153 during ROLLBACK

RELEASE SAVEPOINT語句會從當前事務的一組保存點中刪除已命名的保存點。不出現提交或 回滾。如果保存點不存在,會出現錯誤。

如果您執行COMMIT或執行不能命名保存點的ROLLBACK,則當前事務的所有保存點被刪除。

13.4.5. LOCK TABLES和UNLOCK TABLES語法

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

LOCK TABLES可以鎖定用於當前線程的表。如果表被其它線程鎖定,則造成堵塞,直到可以獲取所有鎖定爲止。UNLOCK TABLES可以釋放被當前線程保持的任何鎖定。當線程發佈另一個LOCK TABLES時,或當與服務器的連接被關閉時,所有由當前線程鎖定的表被隱含地解鎖。

  表鎖定只用於防止其它客戶端進行不正當地讀取和寫入。保持鎖定(即使是讀取鎖定)的客戶端可以進行表層級的操作,比如DROP TABLE

注意,下面是對事務表使用LOCK TABLES的說明:

·         在嘗試鎖定表之前,LOCK TABLES不是事務安全型的,會隱含地提交所有活性事務。同時,開始一項事務(例如,使用START TRANSACTION),會隱含地執行UNLOCK TABLES。(見13.4.3節,“會造成隱式提交的語句”

·         對事務表(如InnoDB)使用LOCK TABLES的正確方法是,設置AUTOCOMMIT=0並且不能調用UNLOCK TABLES,直到您明確地提交事務爲止。當您調用LOCK TABLES時,InnoDB會內部地取其自己的表鎖定,MySQL取其自己的表鎖定。InnoDB在下一個提交時釋放其表鎖定,但是,對於MySQL,要釋放表鎖定,您必須調用UNLOCK TABLES。您不應該讓AUTOCOMMIT=1,因爲那樣的話,InnoDB會在調用LOCK TABLES之後立刻釋放表鎖定,並且很容易形成死鎖定。注意,如果AUTOCOMMIT=1,我們根本不能獲取InnoDB表鎖定,這樣就可以幫助舊的應用軟件避免不必要的死鎖定。

·         ROLLBACK不會釋放MySQL的非事務表鎖定。

要使用LOCK TABLES,您必須擁有相關表的LOCK TABLES權限和SELECT權限。

使用LOCK TABLES的主要原因是仿效事務,或在更新表時加快速度。這將在後面進行更詳細的解釋。

如果一個線程獲得對一個表地READ鎖定,該線程(和所有其它線程)只能從該表中讀取。如果一個線程獲得對一個表的WRITE鎖定,只有保持鎖定的線程可以對錶進行寫入。其它的線程被阻止,直到鎖定被釋放時爲止。

READ LOCALREAD之間的區別是,READ LOCAL允許在鎖定被保持時,執行非衝突性INSERT語句(同時插入)。但是,如果您正打算在MySQL外面操作數據庫文件,同時您保持鎖定,則不能使用READ LOCAL。對於InnoDB表,READ LOCALREAD相同。

當您使用LOCK TABLES時,您必須鎖定您打算在查詢中使用的所有的表。雖然使用LOCK TABLES語句獲得的鎖定仍然有效,但是您不能訪問沒有被此語句鎖定的任何的表。同時,您不能在一次查詢中多次使用一個已鎖定的表——使用別名代替,在此情況下,您必須分別獲得對每個別名的鎖定。

mysql> LOCK TABLE t WRITE, t AS t1 WRITE;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;

如果您的查詢使用一個別名引用一個表,那麼您必須使用同樣的別名鎖定該表。如果沒有指定別名,則不會鎖定該表。

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

相反的,如果您使用一個別名鎖定一個表,您必須使用該別名在您的查詢中引用該表。

mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;

WRITE鎖定通常比READ鎖定擁有更高的優先權,以確保更新被儘快地處理。這意味着,如果一個線程獲得了一個READ鎖定,則另一個線程會申請一個WRITE鎖定,後續的READ鎖定申請會等待,直到WRITE線程獲得鎖定並釋放鎖定。您可以使用LOW_PRIORITY WRITE鎖定來允許其它線程在該線程正在等待WRITE鎖定時獲得READ鎖定。只有當您確定最終將有一個時機,此時沒有線程擁有READ鎖定時,您才應該使用LOW_PRIORITY WRITE鎖定。

LOCK TABLES按照如下方式執行:

1.    按照內部定義的順序,對所有要被鎖定的表進行分類。從用戶的角度,此順序是未經定義的。

2.    如果使用一個讀取和一個寫入鎖定對一個表進行鎖定,則把寫入鎖定放在讀取鎖定之前。

3.    一次鎖定一個表,直到線程得到所有鎖定爲止。

該規則確保表鎖定不會出現死鎖定。但是,對於該規則,您需要注意其它的事情:

如果您正在對一個表使用一個LOW_PRIORITY WRITE鎖定,這隻意味着,MySQL等待特定的鎖定,直到沒有申請READ鎖定的線程時爲止。當線程已經獲得WRITE鎖定,並正在等待得到鎖定表清單中的用於下一個表的鎖定時,所有其它線程會等待WRITE鎖定被釋放。如果這成爲對於應用程序的嚴重的問題,則您應該考慮把部分錶轉化爲事務安全型表。

您可以安全地使用KILL來結束一個正在等待表鎖定的線程。請參見13.5.5.3節,“KILL語法”

注意,您不能使用INSERT DELAYED鎖定任何您正在使用的表,因爲,在這種情況下,INSERT由另一個線程執行。

通常,您不需要鎖定表,因爲所有的單個UPDATE語句都是原子性的;沒有其它的線程可以干擾任何其它當前正在執行的SQL語句。但是,在幾種情況下,鎖定表會有好處:

·         如果您正在對一組MyISAM表運行許多操作,鎖定您正在使用的表,可以快很多。鎖定MyISAM表可以加快插入、更新或刪除的速度。不利方面是,沒有線程可以更新一個用READ鎖定的表(包括保持鎖定的表),也沒有線程可以訪問用WRITE鎖定的表(除了保持鎖定的表以外)。

有些MyISAM操作在LOCK TABLES之下更快的原因是,MySQL不會清空用於已鎖定表的關鍵緩存,直到UNLOCK TABLE被調用爲止。通常,關鍵緩存在每個SQL語句之後被清空。

·         如果您正在使用MySQL中的一個不支持事務的存儲引擎,則如果您想要確定在SELECTUPDATE之間沒有其它線程,您必須使用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,有可能另一個線程會在執行SELECTUPDATE語句之間在trans表中插入一個新行。

通過使用相對更新(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函數,您可以在許多情況下避免使用LOCK TABLES。請參見1.8.5.3節,“事務和原子操作”

通過使用用戶層級的顧問式鎖定函數GET_LOCK()RELEASE_LOCK(),您也可以在有些情況下避免鎖定表。這些鎖定被保存在服務器中的一個混編表中,使用pthread_mutex_lock() pthread_mutex_unlock(),以加快速度。請參見12.9.4節,“其他函數”

要了解更多有關鎖定規則的說明,請參見7.3.1節,“鎖定方法”

您可以使用FLUSH TABLES WITH READ LOCK語句鎖定位於所有帶有讀取鎖定的數據庫中的所有表。請參見13.5.5.2節,“FLUSH語法”。如果您有一個可以及時拍攝快照的文件系統,比如Veritas,這是獲得備份的一個非常方便的方式。

註釋:如果您對一個已鎖定的表使用ALTER TABLE,該表可能會解鎖。請參見A.7.1節,“與ALTER TABLE有關的問題”

13.4.6. SET TRANSACTION語法

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

本語句用於設置事務隔離等級,用於下一個事務,或者用於當前會話。

在默認情況下,SET TRANSACTION會爲下一個事務(還未開始)設置隔離等級。如果您使用GLOBAL關鍵詞,則語句會設置全局性的默認事務等級,用於從該點以後創建的所有新連接。原有的連接不受影響。要進行此操作,您需要SUPER權限。使用SESSION關鍵測可以設置默認事務等級,用於對當前連接執行的所有將來事務。

要了解對每個InnoDB事務隔離等級的描述,請參見15.2.10.3節,“InnoDB和TRANSACTION ISOLATION LEVEL”InnoDB支持MySQL 5.1中的各個等級。默認的等級是REPEATABLE READ

您可以使用--transaction-isolation選項,對mysqld設置初始的默認全局隔離等級。請參見5.3.1節,“mysqld命令行選項”

13.4.7. XA事務

對於InnoDB存儲引擎,可以獲得對XA事務的支持。MySQL XA的執行依據X/Open CAE文件Distributed Transaction Processing: The XA Specification。本文件由Open Group出版,可以從http://www.opengroup.org/public/pubs/catalog/c193.htm獲取。在I.5節,“對XA事務的限制”對當前XA執行的限制進行了描述。

在客戶端方面,沒有特殊要求。連接MySQL服務器的XA接口由以XA關鍵詞開頭的SQL語句組成。MySQL客戶端必須能發送SQL語句,並能理解XA語句接口的語義,但是它們不需要被鏈接到特定的MySQL客戶庫上。

當前,在MySQL連接器當中,MySQL連接器/J 5.0.0直接支持XA(也就是,通過一個可以控制XA SQL語句接口的等級接口)。

XA支持分佈式的事務,具備能力,讓多個獨立的事務資源參加全局的事務。事務資源通常是RDBMSs,不過也可以是其它種類的資源。

一個全局事務會涉及到多個行動,這些行動本身是事務性的。不過,所有行動都必須作爲一個羣組成功完成,或者作爲一個羣組被回滾。實際上,這會延伸ACID性質,“提高等級”,這樣,多個ACID事務就可以一起執行,相當於也擁有ACID性質的全局操作的組件。(但是,對於一個分佈式事務,您必須使用SERAILIZABLE隔離等級,以實現ACID性質。對於一個非分佈式事務,使用REPEATABLE READ就足夠了。但是對於分佈式事務,使用REPEATABLE READ是不夠的。)

分佈式事務的部分示例:

·         應用程序相當於一個把消息傳遞服務和RDBMS組合在一起的整合工具。應用程序可以確保,所有進行消息發送、回收和處理的事務(同時包含一個事務數據庫)均在一個全局事務中發生。您可以把這看作是“事務電子郵件。”

·         應用程序執行的行動會涉及到不同數據庫服務器,比如MySQL服務器和Oracle服務器(或多個MySQL服務器)。涉及到多個服務器的行動必須作爲一個全局事務的一部分發生,而不是作爲針對每個服務器的獨立的本地事務發生。

·         銀行把帳戶信息保存在RDBMS中,並通過自動取款機(ATMs)分發和收取欠款。必須要確保ATM行動被正確地反映到帳戶中,但是這不能只由RDBMS單獨完成。全局事務管理器會整合ATM和數據庫資源,以確保財務事務的整體一致性。

使用全局事務的應用程序涉及一個或多個資源管理器和一個事務管理器:

·         資源管理器(RM)用於提供通向事務資源的途徑。數據庫服務器是一種資源管理器。該管理器必須可以提交或 回滾由RM管理的事務。

·         事務管理器(TM)用於協調作爲一個全局事務一部分的事務。TM與管理每個事務的RMs進行通訊。一個全局事務中各個單個事務均是全局事務的“分支”。全局事務和各分支通過一種命名方法進行標識。這種命名方法在後面進行講述。

MySQL執行XA MySQL時,MySQL服務器相當於一個用於管理全局事務中的XA事務的資源管理器。與MySQL服務器連接的客戶端相當於事務管理器。

要執行一個全局事務,必須知道涉及到了哪些組件,並且把每個組件引到一點,在此時,組件可以被提交或回滾時。根據每個組件報告的有關組件效能的內容,這些組件必須作爲一個原子性羣組全部提交或 回滾。即,要麼所有的組件必須提交,要麼所有的組件必須回滾。要管理一個全局事務,必須要考慮任何組件或連接網絡可能會故障。

用於執行全局事務的過程使用兩階段提交(2PC),發生時間在由全局事務的分支進行的行動已經被執行之後。

1.    在第一階段,所有的分支被預備好。即,它們被TM告知要準備提交。通常,這意味着用於管理分支的每個RM會記錄對於被穩定保存的分支的行動。分支指示是否它們可以這麼做。這些結果被用於第二階段。

2.    在第二階段,TM告知RMs是否要提交或 回滾。如果在預備分支時,所有的分支指示它們將能夠提交,則所有的分支被告知要提交。如果在預備時,有任何分支指示它將不能提交,則所有分支被告知 回滾。

在有些情況下,一個全局事務可能會使用一階段提交(1PC)。例如,當一個事務管理器發現,一個全局事務只由一個事務資源組成(即,單一分支),則該資源可以被告知同時進行預備和提交。

13.4.7.1. XA事務SQL語法

要在MySQL中執行XA事務,應使用以下語句:

XA {START|BEGIN} xid [JOIN|RESUME]
 
XA END xid [SUSPEND [FOR MIGRATE]]
 
XA PREPARE xid
 
XA COMMIT xid [ONE PHASE]
 
XA ROLLBACK xid
 
XA RECOVER

對於XA STARTJOINRESUME子句不被支持。

對於XA ENDSUSPEND [FOR MIGRATE]子句不被支持。

每個XA語句以XA關鍵詞爲開頭,多數語句要求一個xid值。 xid是一個XA事務標識符。它指示該語句適用於哪個事務。xid值由客戶端提供,或由MySQL服務器生成。xid值包含一到三個部分:

xid: gtrid [, bqual [, formatID ]]

gtrid是一個全局事務標識符,bqual是一個分支限定符,formatID是一個數字,用於標識由gtridbqual值使用的格式。根據語法的表示,bqualformatID是自選的。如果沒有給定,默認的bqual值是''。如果沒有給定,默認的fromatID值是1

gtridbqual必須爲字符串文字,每個的長度最多爲64字節(不是字符)。gtridbqual可以用多種方法指定。您可以使用帶引號的字符串('ab'),十六進制字符串(0x6162, X'ab'),或位值(b'nnnn')

formatID是一個無符號的整數。

通過MySQL服務器的帶下劃線的XA支持子程序,gtridbqual值被理解爲以字節爲單位。但是,在包含XA語句的SQL語句正在被分析的同時,服務器會去操作一些特定的字符集。爲了安全,把gtridbqual作爲十六進制字符串寫入。

通常,xid值由事務管理器生成。由一個TM生成的值必須與由其它TMs生成的值不同。一個給定的TM必須能識別自己的xid值。這些值位於由XA RECOVER語句返回的值清單中。

XA START xid用於啓動一個帶給定xid值的XA事務。每個XA事務必須有一個唯一的xid值,因此該值當前不能被其它的XA事務使用。使用gtridbqual值評估唯一性。所有下列的用於XA事務的XA語句必須使用與XA START語句中給定的相同的xid值進行指定。如果您使用這些語句,但是指定的xid值與部分原有的XA事務不對應的話,會發生錯誤。

一項或多項XA事務可以是同一個全局事務的一部分。在一個給定的全局事務中的所有XA事務必須在xid值中使用同樣的gtrid值。出於這個原因,gtrid值必須爲全局唯一的,這樣,有關一個給定的XA事務是哪個全局事務的一部分的問題就不會含糊不清。對於一個全局事務中的每個XA事務,xid值中的bqual部分必須不一樣。(bqual值應不一樣,這個要求是當前執行MySQL XA的一個限制條件。這不是XA規約的一部分。)

對於在MySQL服務器上的處於PREPARED狀態的XA事務,XA RECOVER語句會返回信息。(見13.4.7.2節,“XA事務狀態”.。)輸出包括一個行,該行用於服務器上的每個這類XA事務,不論是哪個客戶端啓動了它。

XA RECOVER輸出行看上去像這樣(例如,xid值包括'abc', 'def'7等部分):

mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data   |
+----------+--------------+--------------+--------+
|        7 |            3 |            3 | abcdef |
+----------+--------------+--------------+--------+

輸出列有以下意義:

·         formatID是事務xidformatID部分

·         gtrid_lengthxidgtrid部分的長度,以字節爲單位

·         bqual_lengthxidbqual部分的長度,以字節爲單位

·         dataxidgtrid部分和bqual部分的串聯

13.4.7.2. XA事務狀態

XA事務在以下狀態下進展:

1.    使用XA START來啓動一個XA事務,並把它放入ACTIVE狀態。

2.    對於一個ACTIVE XA事務,發佈構成事務的SQL語句,然後發佈一個XA END語句。XA END把事務放入IDLE狀態。

3.    對於一個IDLE XA事務,您可以發佈一個XA PREPARE語句或一個XA COMMITONE PHASE語句:

·         XA PREPARE把事務放入PREPARED狀態。在此點上的XA RECOVER語句將在其輸出中包括事務的xid值,因爲XA RECOVER會列出處於PREPARED狀態的所有XA事務。

·         XA COMMITONE PHASE用於預備和提交事務。xid值將不會被XA RECOVER列出,因爲事務終止。

4.    對於一個PREPARED XA事務,您可以發佈一個XA COMMIT語句來提交和終止事務,或者發佈XA ROLLBACK來回滾並終止事務。

下面是一個簡單的XA事務,該事務把一行作爲一個全局事務的一部分插入一個表中。

mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
 
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)

根據一個給定的客戶端連接的語境,XA事務和本地(非XA)事務互相排斥。舉例說明,如果已經發布了XA START來開始一項XA事務,則本地事務不會被啓動,直到XA事務已經被提交或被 回滾爲止。相反的,如果已經使用START TRANSACTION啓動一個本地事務,則XA語句不能被使用,直到該事務被提交或被 回滾爲止。

13.5. 數據庫管理語句

13.5.1. 賬戶管理語句

13.5.1.1. CREATE USER語法

CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
    [, user [IDENTIFIED BY [PASSWORD] 'password']] ...

CREATE USER用於創建新的MySQL賬戶。要使用CREATE USER,您必須擁有mysql數據庫的全局CREATE USER權限,或擁有INSERT權限。對於每個賬戶,CREATE USER會在沒有權限的mysql.user表中創建一個新記錄。如果 賬戶已經存在,則出現錯誤。

使用自選的IDENTIFIED BY子句,可以爲賬戶給定一個密碼。user值和 密碼的給定方法和GRANT語句一樣。特別是,要在純文本中指定密碼,需忽略PASSWORD關鍵詞。要把 密碼指定爲由PASSWORD()函數返回的混編值,需包含關鍵字PASSWORD。請參見13.5.1.3節,“GRANT和REVOKE語法”

13.5.1.2. DROP USER語法

DROP USER user [, user] ...

DROP USER語句用於刪除一個或多個MySQL賬戶。要使用DROP USER,您必須擁有mysql數據庫的全局CREATE USER權限或DELETE權限。使用與GRANTREVOKE相同的格式爲每個 賬戶命名;例如,'jeffrey'@'localhost'。 賬戶名稱的用戶和主機部分與用戶表記錄的UserHost列值相對應。

使用DROP USER,您可以取消一個賬戶和其權限,操作如下:

DROP USER user;

該語句可以刪除來自所有授權表的帳戶權限記錄。

要點:DROP USER不能自動關閉任何打開的用戶對話。而且,如果用戶有打開的對話,此時取消用戶,則命令不會生效,直到用戶對話被關閉後才生效。一旦對話被關閉,用戶也被取消,此用戶再次試圖登錄時將會失敗。這是有意設計的。

13.5.1.3. GRANT和REVOKE語法

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON [object_type] {tbl_name | * | *.* | db_name.*}
    TO user [IDENTIFIED BY [PASSWORD] 'password']
        [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
    [REQUIRE
        NONE |
        [{SSL| X509}]
        [CIPHER 'cipher' [AND]]
        [ISSUER 'issuer' [AND]]
        [SUBJECT 'subject']]
    [WITH with_option [with_option] ...]

object_type =
    TABLE
  | FUNCTION
  | PROCEDURE

with_option =
    GRANT OPTION
  | MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON [object_type] {tbl_name | * | *.* | db_name.*}
    FROM user [, user] ...

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

GRANTREVOKE語句允許系統管理員創建MySQL用戶 賬戶,授予權限和撤銷權限。

MySQL賬戶信息存儲在mysql數據庫的表中。在第5章:數據庫管理中對本數據庫和訪問控制系統進行了詳盡的討論。要了解更多詳細信息,您應該查詢此章。

如果授權表擁有含有mixed-case數據庫或表名稱的權限記錄,並且lower_case_table_names系統變量已設置,則不能使用REVOKE撤銷權限,必須直接操縱授權表。(當lower_case_table_names已設置時,GRANT將不會創建此類記錄,但是此類記錄可能已經在設置變量之前被創建了。)

授予的權限可以分爲多個層級:

·         全局層級

全局權限適用於一個給定服務器中的所有數據庫。這些權限存儲在mysql.user表中。GRANT ALL ON *.*REVOKE ALL ON *.*只授予和撤銷全局權限。

·         數據庫層級

數據庫權限適用於一個給定數據庫中的所有目標。這些權限存儲在mysql.dbmysql.host表中。GRANT ALL ON db_name.*REVOKE ALL ON db_name.*只授予和撤銷數據庫權限。

·         表層級

表權限適用於一個給定表中的所有列。這些權限存儲在mysql.talbes_priv表中。GRANT ALL ON db_name.tbl_nameREVOKE ALL ON db_name.tbl_name只授予和撤銷表權限。

·         列層級

列權限適用於一個給定表中的單一列。這些權限存儲在mysql.columns_priv表中。當使用REVOKE時,您必須指定與被授權列相同的列。

·         子程序層級

CREATE ROUTINE, ALTER ROUTINE, EXECUTEGRANT權限適用於已存儲的子程序。這些權限可以被授予爲全局層級和數據庫層級。而且,除了CREATE ROUTINE外,這些權限可以被授予爲子程序層級,並存儲在mysql.procs_priv表中。

當後續目標是一個表、一個已存儲的函數或一個已存儲的過程時,object_type子句應被指定爲TABLEFUNCTIONPROCEDURE。當從舊版本的MySQL升級時,要使用本子句,您必須升級您的授權表。請參見2.10.2節,“升級授權表”

要使用GRANTREVOKE,您必須擁有GRANT OPTION權限,並且您必須用於您正在授予或撤銷的權限。

要撤銷所有權限,需使用以下語法。此語法用於取消對於已命名的用戶的所有全局層級、數據庫層級、表層級和列層級的權限。

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

要使用本REVOKE語法,您必須擁有mysql數據庫的全局CREATE USER權限或UPDATE權限。

對於GRANTREVOKE語句,priv_type可以被指定爲以下任何一種:

權限

意義

ALL [PRIVILEGES]

設置除GRANT OPTION之外的所有簡單權限

ALTER

允許使用ALTER TABLE

ALTER ROUTINE

更改或取消已存儲的子程序

CREATE

允許使用CREATE TABLE

CREATE ROUTINE

創建已存儲的子程序

CREATE TEMPORARY TABLES

允許使用CREATE TEMPORARY TABLE

CREATE USER

允許使用CREATE USER, DROP USER, RENAME USERREVOKE ALL PRIVILEGES

CREATE VIEW

允許使用CREATE VIEW

DELETE

允許使用DELETE

DROP

允許使用DROP TABLE

EXECUTE

允許用戶運行已存儲的子程序

FILE

允許使用SELECT...INTO OUTFILELOAD DATA INFILE

INDEX

允許使用CREATE INDEXDROP INDEX

INSERT

允許使用INSERT

LOCK TABLES

允許對您擁有SELECT權限的表使用LOCK TABLES

PROCESS

允許使用SHOW FULL PROCESSLIST

REFERENCES

未被實施

RELOAD

允許使用FLUSH

REPLICATION CLIENT

允許用戶詢問從屬服務器或主服務器的地址

REPLICATION SLAVE

用於複製型從屬服務器(從主服務器中讀取二進制日誌事件)

SELECT

允許使用SELECT

SHOW DATABASES

SHOW DATABASES顯示所有數據庫

SHOW VIEW

允許使用SHOW CREATE VIEW

SHUTDOWN

允許使用mysqladmin shutdown

SUPER

允許使用CHANGE MASTER, KILL, PURGE MASTER LOGSSET GLOBAL語句,mysqladmin debug命令;允許您連接(一次),即使已達到max_connections

UPDATE

允許使用UPDATE

USAGE

“無權限”的同義詞

GRANT OPTION

允許授予權限

當從舊版本的MySQL升級時,要使用EXECUTE, CREATE VIEW, SHOW VIEW, CREATE USER, CREATE ROUTINEALTER ROUTINE權限,您必須首先升級您的授權表。請參見2.10.2節,“升級授權表”

REFERENCES權限目前未被使用。

當您想要創建一個沒有權限的用戶時,可以指定USAGE

使用SHOW GRANTS來確定帳戶擁有什麼權限。請參見13.5.4.10節,“SHOW GRANTS語法”

您可以通過使用ON *.*語法賦予全局權限,或通過使用ON db_name.*語法賦予數據庫層級權限。如果您指定了ON *並且您已經選擇了一個默認數據庫,則權限被賦予到這個數據庫中。(警告:如果您指定了ON *同時您沒有選擇一個默認數據庫,則權限是全局的。)

FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWNSUPER權限是管理性權限,只能進行全局授權(使用ON *.*語法)。

其它權限可以被全局授權,或被賦予爲其它層級。

對於一個表,您可以指定的priv_type值只能是SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEXALTER

對於一個列(也就是,當您使用一個column_list子句時),您可以指定的priv_type值只能是SELECT, INSERTUPDATE

在子程序層級,您可以指定的priv_type值只能是ALTER ROUTINE, EXECUTEGRANT OPTIONCREATE ROUTINE不是一個子程序層級的權限,因爲您必須擁有此權限,才能創建一個子程序。

對於全局、數據庫、表和子程序層級,GRANT ALL只能賦予在您正在授權的層級中存在的權限。例如,如果您使用GRANT ALL ON db_name.*,這是一個數據庫層級語句,因此不會授予全局權限,如FILE等。

MySQL允許您對不存在的數據庫目標授予權限。在此情況下,將被授予的權限必須包括CREATE權限。這個性質是有意設計的,目的是允許數據庫管理員爲將在此後被創建的數據庫目標預備用戶 賬戶和權限。

要點:當您取消一個表或數據庫時,MySQL不會自動撤銷任何權限。但是,如果您取消一個子程序,則被賦予該子程序的所有子程序層級的權限都被撤銷。

注意:GRANT語句用於在全局層級或數據庫層級賦予權限。當在GRANT語句中指定數據庫名稱時,允許使用‘_’和‘%’通配符。這意味着,如果您想要使用‘_’字符作爲一個數據庫名稱的一部分,您應該在GRANT語句中指定它爲‘\_’,以防止用戶可以訪問其它符合此通配符格式的數據庫;例如,GRANT ... ON `foo\_bar`.* TO ...

爲了接納對來自任意主機的用戶授權的權利,MySQL支持以user_name@host_name的形式指定user值。如果一個user_namehost_name與一個不加引號的標識符一樣是合法的,那麼您不需要對它加引號。不過,要指定一個包含特殊字符(如‘-’)的user_name字符串,或一個包含特殊字符或通配字符(如‘%’),則引號是必要的;例如,'test-user'@'test-hostname'。分別對usernamehostname加引號。

您可以在hostname中指定通配符。例如user_name@'%.loc.gov'適用於在loc.gov域中的任何主機的user_name。同時user_name@'144.155.166.%'適用於144.155.166 C級子網中的任何主機的user_name

簡單形式user_nameuser_name@'%'的同義詞。

MySQL不支持usernames中的通配符。通過把帶有User=''的登錄項插入到mysql.user表中,或通過使用GRANT語句創建一個帶有空名稱的用戶,可以定義匿名用戶:

mysql> GRANT ALL ON test.* TO ''@'localhost' ...

當把帶引號的值是,需使用反勾號(`)爲數據庫、表、列和子程序名稱加引號。使用單引號(')hostnamesusernames和 密碼加引號。

警告:如果您允許匿名用戶連接到MySQL服務器,則您應該同時向所有本地用戶授予user_name@localhost權限。否則,當有名稱的用戶試圖從本地機器登錄MySQL服務器時,mysql.user表中的用於localhost的匿名用戶帳戶會被使用。

您可以通過執行以下查詢來確定是否這適合於您。以下查詢列舉了所有匿名用戶:

mysql> SELECT Host, User FROM mysql.user WHERE User='';

如果您想要刪除本地匿名用戶賬戶,以避免出現剛纔談到的問題,則需使用以下語句:

mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql> FLUSH PRIVILEGES;

GRANT支持最長爲60個字符的hostnames。數據庫、表、列和子程序名稱最長可爲64個字符。Usernames最長可爲16個字符。 註釋:不能通過更改mysql.user表來改變usernames的允許長度。如果試圖這麼做,會導致出現不可預見的問題,可能會造成用戶無法登錄MySQL服務器。除了採用由MySQL公司提供的用於升級MySQL服務器的mysql_fix_privilege_tables原稿之外,請您不要以任何方式變更授權表。

對於表或列的權限是作爲各個權限層級的邏輯OR權限被附加形成的。例如,如果mysql.user表指定一個用戶擁有全局SELECT權限,則該權限不能被數據庫、表或列層級的登錄項定義。

可以按下列方法計算列權限:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

在多數情況下,您只在一個權限層級下向用戶授予權利,所以壽命通常不是那麼複雜。有關權限檢查規程的細節,請參見5.7節,“MySQL訪問權限系統”

如果您對一個在mysql.user表中不存在的username/hostname組合授予權限,則增加一個登錄項並保持在此處,直到使用DELETE語句刪除爲止。換句話說,GRANT可以創建用戶表登錄項,但是REVOKE不會取消它們;您必須使用DROP USERDELETE明確地操作。

如果創建了一個新的用戶,或者如果您擁有全局授權權限,則用戶密碼被設置爲由IDENTIFIED BY子句指定的密碼(如果給定了一個)。如果用戶已擁有了一個密碼,則此密碼被新密碼替代。

警告:如果您創建了一個新用戶,但是不指定IDENTIFIED BY子句,則用戶沒有 密碼。這是很不安全的。不過,您可以啓用NO_AUTO_CREATE_USER SQL模式,來防止GRANT創建一個新用戶(否則GRANT會這麼做),除非給定了IDENTIFIED BY來爲新用戶提供一個密碼。

使用SET PASSWORD語句也可以設置密碼。請參見13.5.1.5節,“SET PASSWORD語法”

IDENTIFIED BY子句中,密碼應被作爲文字密碼只被給定。沒有必要使用PASSWORD()函數,因爲該函數用於SET PASSWORD語句。例如:

GRANT ... IDENTIFIED BY 'mypass';

如果您不想以明白的文字發送密碼,並且您知道PASSWORD()返回給密碼的混編值,則您可以指定混編值,前面加入關鍵詞PASSWORD

GRANT ...
IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';

在一個C程序中,您可以通過使用make_scrambled_password() C API函數得到混編值。

如果您爲一個數據庫授予權限,則在mysql.db表中,會根據需要創建登錄項。如果使用REVOKE刪除了所有的數據庫權限,則本登錄項被刪除。

如果一個用戶不擁有表權限,則當用戶申請表清單時(例如,使用SHOW TABLES語句),表名稱不顯示。

SHOW DATABASES權限允許賬戶通過發佈SHOW DATABASE語句來觀看數據名稱。不擁有此權限的賬戶只能看到他們擁有部分權限的數據庫,並且如果使用--skip-show-database選項啓動服務器,則根本不能使用本語句。

WITH GRANT OPTION子句給予用戶能力,可以在指定的權限層級,向其它用戶給定其擁有的任何權限。您應該留心您給予了誰GRANT OPTION權限,因爲擁有不同權限的兩個用戶可以聯合使用權限!

您不能向其它用戶授予您自己沒有的權限;GRANT OPTION權限只允許您賦予您自己擁有的權限。

要注意,當您在某個特定權限層級向一個用戶授予GRANT OPTION權限時,用戶擁有的該層級的任何權限(或未來將被給定的權限)也可以由該用戶授予。假設您向一個用戶賦予了數據庫INSERT權限。如果您然後賦予數據庫SELECT權限,並指定了WITH GRANT OPTION,則該用戶不僅可以向其它用戶給予SELECT權限,還可以給予INSERT。如果您然後向用戶授予數據庫UPDATE權限,則用戶可以授予INSERT, SELECTUPDATE

您不應該向一個常規用戶授予ALTER權限。如果您這麼做,則該用戶可以嘗試通過對錶重新命名來破壞授權系統!

The MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR count, and MAX_CONNECTIONS_PER_HOUR count options limit the number of queries, updates, and logins a user can perform during any given one-hour period. If count is 0 (the default), this means that there is no limitation for that user.      MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR countMAX_CONNECTIONS_PER_HOUR count選項限制了在任何給定的一小時期間,用戶可以執行的查詢、更新和登錄的數目。如果count0(默認值),這意味着,對該用戶沒有限制。

MAX_USER_CONNECTIONS count選項限制了賬戶可以同時進行的連接的最大數目。如果count0(默認值),則max_user_connections系統可以決定該 賬戶同時連接的數目。

註釋:要對一個原有的用戶指定任何這類資源限制型選項,同時又不影響原有的權限,需使用GRANT USAGE ON *.* ... WITH MAX_...

5.8.4節,“限制賬戶資源”

除了根據username和密碼進行常規鑑定外,MySQL還可以檢查X509證明屬性。要爲MySQL賬戶指定與SSL有關的選項,需使用GRANT語句的REQUIRE子句。(要了解有關在MySQL中使用SSL的背景信息,請參見5.8.7節,“使用安全連接”。)

對於一個給定的賬戶,有多種可能性可以限制連接類型:

·         如果賬戶沒有SSLX509要求,並且如果username和 密碼是有效的,則允許不加密連接。但是,如果客戶端有正確的證明和關鍵文件,則根據客戶端的選擇,也可以使用加密連接。

·         REQUIRE SSL選項用於告知服務器,對於該賬戶只允許SSL加密連接。注意,如果有允許任何非SSL連接的訪問控制記錄,則本選項可以被忽略。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;

·         REQUIRE X509意味着客戶端必須擁有一個有效證明,除非不需要確切的證明、發佈者和主題。唯一的要求是,應可以使用CA證明其中之一來驗證簽名。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret' REQUIRE X509;

·         REQUIRE ISSUER 'issuer'用於對連接嘗試進行限定,客戶端必須出示一個由CAissuer’發佈的有效的X509證明。如果客戶端出示的證明是有效的,但是有一個不同的發佈者,則服務器會拒絕連接。使用X509證明就意味着要加密,所以在這種情況下,SSL選項是不必要的。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
·                       O=MySQL Finland AB/CN=Tonu Samuel/[email protected]';

注意,ISSUER值應被作爲一個單一字符串輸入。

·         REQUIRE SUBJECT 'subject'用於對連接嘗試進行限定,客戶端必須出示一個包含主題subject的有效的X509證明。如果客戶端出示的證明是有效的,但是有一個不同的主題,則服務器會拒絕連接。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
·                       O=MySQL demo client certificate/
·                       CN=Tonu Samuel/[email protected]';

注意,SUBJECT值應被作爲一個單一字符串輸入。

·         需要REQUIRE CIPHER 'cipher'來確認使用了密碼和足夠長度的關鍵字。如果使用了採用短型加密關鍵字的舊算法,SSL本身會比較脆弱。使用本選項,您可以要求使用特定的密碼方法來許可一個連接。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

SUBJECT, ISSUERCIPHER選項可以在REQUIRE子句中結合,如下:

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
    -> IDENTIFIED BY 'goodsecret'
    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
       O=MySQL demo client certificate/
       CN=Tonu Samuel/[email protected]'
    -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
       O=MySQL Finland AB/CN=Tonu Samuel/[email protected]'
    -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

注意,SUBJECTISSUER值各自應被作爲一個單一字符串輸入。

REQUIRE各選項之間,AND關鍵詞是自選的。

選項的順序無所謂,但是選項不能被指定兩次。

mysqld啓動後,所有的權限被讀入存儲器中。要了解詳細說明,請參見5.7.7節,“權限更改何時生效”

注意,如果您正在使用表權限或列權限,即使只對一個用戶使用,服務器也會對所有用戶檢查表權限和列權限,這會略微降低MySQL的速度。與此類似,如果您對某些用戶限制查詢、更新或連接的數目,則服務器必須監測這些值。

標準SQL版本和MySQL版本的GRANT之間的最大區別是:

·         MySQL中,權限與hostnameusername的組合有關,與 單一的username無關。

·         標準SQL不擁有全局層級或數據庫層級權限,也不支持MySQL支持的所有權限類型。

·         MySQL不支持標準SQL TRIGGERUNDER權限。

·         標準SQL權限以一種分等級的方式進行組織。如果您取消一個用戶,則用戶被授予的所有權限都被撤銷。在MySQL中,如果您使用DROP USER,也會如此。請參見13.5.1.2節,“DROP USER語法”

·         在標準SQL中,當您取消一個表時,對一個表的所有權限會被撤銷。在標準SQL中,當您撤銷一個權限時,根據該權限被授予的所有權限也會被撤銷。在MySQL中,只有使用明確的REVOKE語句,或通過操作存儲在MySQL授權表中的值,才能取消權限。

·         MySQL中,可以只對一個表中的部分列擁有INSERT權限。在此情況下,如果您忽略您不擁有INSERT權限的那些列,,您仍然可以對錶執行INSERT語句。如果沒有啓用嚴格的SQL模式,則被忽略的列被設置爲各自隱含的默認值。在嚴格模式下,如果某個被忽略的列沒有默認值,則該語句被拒絕。5.3.2節,“SQL服務器模式”對嚴格模式進行了討論。13.1.5節,“CREATE TABLE語法”對隱含默認值進行了討論。

您不擁有INSERT權限的列被設置爲各自的默認值。標準SQL要求您擁有所有列的INSERT權限。

MySQL中,如果您只擁有一個表中的部分列的INSERT權限,同時,如果您從INSERT語句中忽略您不擁有權限的列,則您仍然可以對錶執行INSERT語句;那些列將被設置爲各自的默認值。在嚴格模式下(即當sql_mode='traditional'時,如果某些被忽略的列沒有默認值,則INSERT語句將被拒絕。

13.5.1.4. RENAME USER語法

RENAME USER old_user TO new_user
    [, old_user TO new_user] ...

RENAME USER語句用於對原有MySQL賬戶進行重命名。要使用RENAME USER,您必須擁有全局CREATE USER權限或mysql數據庫UPDATE權限。如果舊 賬戶不存在或者新賬戶已存在,則會出現錯誤。old_usernew_user值的給定方法與GRANT語句一樣。

13.5.1.5. SET PASSWORD語法

SET PASSWORD = PASSWORD('some password')
SET PASSWORD FOR user = PASSWORD('some password')

SET PASSWORD語句用於向一個原有MySQL用戶 賬戶賦予一個密碼。

第一個語法爲當前用戶設置密碼。已使用一個非匿名賬戶連接到服務器上的任何客戶即都可以更改該賬戶的密碼。

第二個語法爲當前服務器主機上的一個特定賬戶設置密碼。只有擁有mysql數據庫UPDATE權限的客戶端可以這麼做。user值應以user_name@host_name的格式被給定,此處user_namehost_namemysql.user表登錄項的UserHost列中列出的完全一樣。舉例說明,如果您有一個登錄項,UserHost列值爲'bob''%.loc.gov',您應該按如下方法寫語句:

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

這相當於以下語句:

mysql> UPDATE mysql.user SET Password=PASSWORD('newpass')
    -> WHERE User='bob' AND Host='%.loc.gov';
mysql> FLUSH PRIVILEGES;

註釋:如果您正在使用一個4.1以前的客戶端連接到一個MySQL 4.1MySQL 4.1以後的服務器,則在閱讀5.7.9節,“MySQL 4.1中的密碼哈希處理”之前,不能使用前面的SET PASSWORDUPDATE語句。 密碼格式在MySQL 4.1中變更了,並且在特定情況下,如果您更改密碼,您可能無法在連接到服務器上。

您可以通過執行SELECT CURRENT_USER()觀看您當前的鑑定user@host登錄項。

13.5.2. 表維護語句

13.5.2.1. ANALYZE TABLE語法

ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

本語句用於分析和存儲表的關鍵字分佈。在分析期間,使用一個讀取鎖定對錶進行鎖定。這對於MyISAM, BDBInnoDB表有作用。對於MyISAM表,本語句與使用myisamchk -a相當。

MySQL使用已存儲的關鍵字分佈來決定,當您對除常數以外的對象執行聯合時,表按什麼順序進行聯合。

本語句會返回一個含有以下列的表:

Table

表名稱

Op

進行分析

Msg_type

狀態、錯誤、信息或警告之一

Msg_text

消息

您可以使用SHOW INDEX語句檢查已存儲的關鍵字分佈。請參見13.5.4.11節,“SHOW INDEX語法”

如果從上一個ANALYZE TABLE語句開始,表沒有變化,則不再分析該表。

ANALYZE TABLE語句被寫入二進制日誌中,除非使用了自選的NO_WRITE_TO_BINLOG關鍵詞(或其別名LOCAL)。

13.5.2.2. BACKUP TABLE語法

BACKUP TABLE tbl_name [, tbl_name] ... TO '/path/to/backup/directory'

註釋:本語句不理想。我們正在努力尋找一種更好的替代方式,該方式將提供在線備份能力。同時,也可以使用mysqlhotcopy原本替代。

BACKUP TABLE用於在刷新了所有對磁盤的緩衝變更後,把恢復表所需的最少數目的表文件拷貝到備份目錄中。本語句只對MyISAM表起作用。它可以拷貝.frm定義文件和.MYD數據文件。.MYI索引文件可以從這兩個文件中重建。本目錄應被指定爲一個完整的路徑名。

在使用本語句前,請參見5.9.1節,“數據庫備份”

在備份期間,爲每個表保持一個讀取鎖定,每次一個,在正在備份時鎖定。如果您想要把多個表作爲一個快照來備份(防止它們在備份操作過程中被更改),您必須實現發佈一個LOCK TABLES語句,以獲得對一個組羣中的每個表的讀取鎖定。

該語句會返回一個含有以下列的表:

Table

表名稱

Op

進行備份

Msg_type

狀態、錯誤、信息或警告之一

Msg_text

消息

13.5.2.3. CHECK TABLE語法

CHECK TABLE tbl_name [, tbl_name] ... [option] ...
 
option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

檢查一個或多個表是否有錯誤。CHECK TABLEMyISAMInnoDB表有作用。對於MyISAM表,關鍵字統計數據被更新。

CHECK TABLE也可以檢查視圖是否有錯誤,比如在視圖定義中被引用的表已不存在。

CHECK TABLE語句會返回一個含有以下列的表:

Table

表名稱

Op

進行檢查

Msg_type

狀態、錯誤、信息或錯誤之一

Msg_text

消息

注意,該語句可能會爲每個被檢查的表產生多行信息。最後一行有一個Msg_type狀態值。Msg_text通常應爲OK。如果您沒有得到OK,或表已經更新了,則您通常應該運行修復後的表。請參見5.9.4節,“表維護和崩潰恢復”。表已經更新了,這意味着表的存儲引擎指示沒有必要檢查表。

可以給予的不同的檢查選項列於下表中。這些選項只適用於檢查MyISAM表。對於InnoDB表和視圖,這些選項被忽略。

類型

意義

QUICK

不掃描行,不檢查錯誤的鏈接。

FAST

只檢查沒有被正確關閉的表。

CHANGED

只檢查上次檢查後被更改的表,和沒有被正確關閉的表。

MEDIUM

掃描行,以驗證被刪除的鏈接是有效的。也可以計算各行的關鍵字校驗和,並使用計算出的校驗和驗證這一點。

EXTENDED

對每行的所有關鍵字進行一個全面的關鍵字查找。這可以確保表是100%一致的,但是花的時間較長。

如果沒有指定QUICK, MEDIUMEXTENDED選項,則對於動態格式MyISAM表,默認檢查類型是MEDIUM。這與對錶運行myisamchk --medium-check tbl_name的結果相同。對於靜態格式MyISAM表,默認檢查類型也是MEDIUM,除非CHANGEDFAST已被指定。在此情況下,默認值爲QUICK。對於CHANGEDFAST,行掃描被跳過,因爲行極少被破壞。

您可以組合檢查選項,如下面的例子所示。該例子對錶進行了一個快速檢查,來查看該表是否被正確關閉:

CHECK TABLE test_table FAST QUICK;

註釋:在有些情況下,CHECK TABLE會更改表。如果表被標記爲“corrupted”或“not closed properly”,則出現這種情況。但是CHECK TABLE不會找出表中的問題。在這種情況下,CHECK TABLE會把表標記爲良好。

如果一個表被破壞,很有可能問題在索引中,而不在數據部分中。所有前述的檢查類型都可以徹底地檢查索引,因此,可以找出多數的錯誤。

如果您只想要檢查您假定的表是良好的,您應該不使用檢查選項或QUICK選項。當您時間匆忙時,應使用QUICKQUICK無法找出數據文件中的錯誤的風險非常小。(在多數情況下,在正常使用中,MySQL應能在數據文件中找出錯誤。如果找出了錯誤,表被標記爲“corrupted”,並不能被使用,直到修復爲止。)

如果您想要時常檢查表,FASTCHANGED多數情況下從原本中被使用(例如,從cron中被執行)。在多數情況下,FAST優先於CHANGED。(只有一種情況FAST不優先於CHANGED,那就是當您懷疑您在MyISAM代碼中發現了錯誤。)

MySQL試圖通過關鍵字更新一行或查找一行時,如果您已經運行了一個常規檢查後但仍得到來自表的奇怪的錯誤,此時使用EXTENDED。(如果常規的檢查運行成功,則基本用不着EXTENDED。)

CHECK TABLE報告的部分問題不會被自動修正:

·         發現行。此行中,auto_increment列有0值。

這意味着,您在表中有一行,該行的AUTO_INCREMENT索引列包含0值。(可以通過使用UPDATE語句,明確地把列設置爲0,以創建一個AUTO_INCREMENT列爲0的行。)

這本身不是一個錯誤,但是如果您決定轉儲表並恢復表,或對錶進行ALTER TABLE,那麼會導致出現麻煩。在此情況下,AUTO_INCREMENT列會根據AUTO_INCREMENT列的結果更改值,這會導致出現問題,如重複關鍵字錯誤等。

要消除警告,只需執行一個UPDATE語句,把列設置爲除0以外的值。

13.5.2.4. CHECKSUM TABLE語法

CHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]

報告一個表校驗和。

如果指定了QUICK,則報告活性表校驗和,否則報告NULL。這是非常快的。活性表通過指定CHECKSUM1表選項啓用,目前只支持用於MyISAM表。請參見13.1.5節,“CREATE TABLE語法”

EXTENDED模式下,整個表被一行一行地讀取,並計算校驗和。對於大型表,這是非常慢的。

默認情況下,如果既沒有指定QUICK,也沒有指定EXTENDED,並且如果表存儲引擎支持,則MySQL返回一個活性校驗和,否則會對錶進行掃描。

CHECKSUM TABLE對於不存在的表會返回NULL。對於這種情況,會生成一個警告。

13.5.2.5. OPTIMIZE TABLE語法

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

如果您已經刪除了表的一大部分,或者如果您已經對含有可變長度行的表(含有VARCHAR, BLOBTEXT列的表)進行了很多更改,則應使用OPTIMIZE TABLE。被刪除的記錄被保持在鏈接清單中,後續的INSERT操作會重新使用舊的記錄位置。您可以使用OPTIMIZE TABLE來重新利用未使用的空間,並整理數據文件的碎片。

在多數的設置中,您根本不需要運行OPTIMIZE TABLE。即使您對可變長度的行進行了大量的更新,您也不需要經常運行,每週一次或每月一次即可,只對特定的表運行。

OPTIMIZE TABLE只對MyISAM, BDBInnoDB表起作用。

對於MyISAM表,OPTIMIZE TABLE按如下方式操作:

1.    如果表已經刪除或分解了行,則修復表。

2.    如果未對索引頁進行分類,則進行分類。

3.       如果表的統計數據沒有更新(並且通過對索引進行分類不能實現修復),則進行更新。

對於BDB表,OPTIMIZE TABLE目前被映射到ANALYZE TABLE上。對於InnoDB表,OPTIMIZE TABLE被映射到ALTER TABLE上,這會重建表。重建操作能更新索引統計數據並釋放成簇索引中的未使用的空間。請參見13.5.2.1節,“ANALYZE TABLE語法”

使用—skip-new或—safe-mode選項可以啓動mysqld。通過啓動mysqld,您可以使OPTIMIZE TABLE對其它表類型起作用。

注意,在OPTIMIZE TABLE運行過程中,MySQL會鎖定表。

OPTIMIZE TABLE語句被寫入到二進制日誌中,除非使用了自選的NO_WRITE_TO_BINLOG關鍵詞(或其別名LOCAL)。已經這麼做了,因此,用於MySQL服務器的OPTIMIZE TABLE命令的作用相當於一個複製主服務器,在默認情況下,這些命令將被複制到複製從屬服務器中。

13.5.2.6. REPAIR TABLE語法

REPAIR [LOCAL | NO_WRITE_TO_BINLOG] TABLE
    tbl_name [, tbl_name] ... [QUICK] [EXTENDED] [USE_FRM]

REPAIR TABLE用於修復被破壞的表。默認情況下,REPAIR TABLEmyisamchk --recover tbl_name具有相同的效果。REPAIR TABLEMyISAMARCHIVE表起作用。請參見15.1節,“MyISAM存儲引擎”, 15.8節,“ARCHIVE存儲引擎”

通常,您基本上不必運行此語句。但是,如果災難發生,REPAIR TABLE很有可能從MyISAM表中找回所有數據。如果您的表經常被破壞,您應該盡力找到原因,以避免使用REPAIR TALBE。請參見A.4.2節,“如果MySQL依然崩潰,應作些什麼”。同時也見15.1.4節,“MyISAM表方面的問題”

本語句會返回一個含有以下列的表:

Table

表名稱

Op

進行修復

Msg_type

狀態、錯誤、信息或警告之一

Msg_text

消息

對於每個被修復的表,REPAIR TABLE語句會產生多行的信息。上一行含有一個Msg_type狀態值。Msg_test通常應爲OK。如果您沒有得到OK,您應該嘗試使用myisamchk --safe-recover修復表,因爲REPAIR TABLE尚不會執行所有的myisamchk選項。我們計劃在將來使它的靈活性更強。

如果給定了QUICK,則REPAIR TABLE會嘗試只修復索引樹。這種類型的修復與使用myisamchk --recover --quick相似。

如果您使用EXTENDED,則MySQL會一行一行地創建索引行,代替使用分類一次創建一個索引。這種類型的修復與使用myisamchk --safe-recover相似。

對於REPAIR TABLE,還有一種USE_FRM模式可以利用。如果.MYI索引文件缺失或標題被破壞,則使用此模式。在這種模式下,MySQL可以使用來自.frm文件重新創建.MYI文件。這種修復不能使用myisamchk來完成。 註釋:只能在您不能使用常規REPAIR模式是,才能使用此模式。.MYI標題包含重要的表元數據(特別是,當前的AUTO_INCREMENT值和Delete鏈接)。這些元數據在REPAIR...USE_FRM中丟失。如果表被壓縮,則不能使用USE_FRM。因爲本信息也存儲在.MYI文件中。

REPAIR TABLE語句被寫入二進制日誌中,除非使用了自選的NO_WRITE_TO_BINLOG關鍵詞(或其別名LOCAL)。

警告:如果在REPAIR TABLE運行過程中,服務器停機,則在重新啓動之後,在執行其它操作之前,您必須立刻對錶再執行一個REPAIR TABLE語句。(通過製作一個備份來啓動是一個好辦法。)再最不利情況下,您可以有一個新的乾淨的索引文件,不含有關數據文件的信息。然後,您執行的下一個操作會覆蓋數據文件。這很少發生,但是是有可能的。

13.5.2.7. RESTORE TABLE語法

RESTORE TABLE tbl_name [, tbl_name] ... FROM '/path/to/backup/directory'

用於恢復來自用BACKUP TABLE製作的備份的表。原有的表不會被覆蓋;如果您試圖覆蓋一個原有的表,會發生錯誤。和BACKUP TABLE一樣,RESTORE TABLE目前只對MyISAM表起作用。目錄應被指定爲一個完整路徑名。

每個表的備份包括其.frm格式文件和.MYD數據文件。恢復操作會恢復這些文件,然後使用這些文件來重建.MYI索引文件。恢復操作比備份操作花的時間更長,這是因爲需要重建索引。表含有的索引越多,花的時間就越長。

該語句會返回一個含有以下列的表:

Table

表名稱

Op

進行恢復

Msg_type

狀態、錯誤、信息或警告之一

Msg_text

消息

13.5.3. SET語法

SET variable_assignment [, variable_assignment] ...
 
variable_assignment:
      user_var_name = expr
    | [GLOBAL | SESSION] system_var_name = expr
    | @@[global. | session.]system_var_name = expr

SET用於設置不同類型的變量。這些變量會影響服務器或客戶端的操作。SET可以用於向用戶變量或系統變量賦值。

用於分配賬戶密碼的SET PASSWORD語句在13.5.1.5節,“SET PASSWORD語法”中進行了討論。

多數系統變量可以在運行時間被更改。可以被動態設置的系統變量在5.3.3.1節,“動態系統變量”中進行了討論。

註釋:舊版本的MySQL採用SET OPTION作爲這個命令,但是由於有了SET,現在不贊成使用SET OPTION

以下例子顯示了您可以用於設置變量的不同語法。

用戶變量可以被寫作@var_name,並可以進行如下設置:

SET @var_name = expr;

9.3節,“用戶變量”中給出了有關用戶變量的更多信息。

系統變量可以被作爲var_name引用到SET語句中。在名稱的前面可以自選地添加GLOBAL@@global,以明確地指示該變量是全局變量。或者在名稱前面添加SESSION, @@session,或@@,以指示它是一個會話變量。LOCAL@@localSESSION@@session地同義詞。如果沒有修改符,則SET設置會話變量。

支持系統變量的@@var_name語法,以便使MySQL語法與其它數據庫系統相兼容。

如果您在同一個語句中設置多個系統變量,則最後一個GLOBALSESSION選項被用於沒有指定模式的變量。

SET sort_buffer_size=10000;
SET @@local.sort_buffer_size=10000;
SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
SET @@sort_buffer_size=1000000;
SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;

如果您使用SESSION(默認情況)設置一個系統變量,則該值仍然有效,直到當前會話結束爲止,或者直到您吧變量設置爲一個不同的值爲止。如果您使用GLOBAL(要求SUPER權限)來設置一個系統變量,則該值被記住,並被用於新的連接,直到服務器重新啓動爲止。如果您想要進行永久式變量設置,您應該把它放入一個選項文件。請參見4.3.2節,“使用選項文件”

爲了防止不正確的使用,如果您使用SET GLOBAL時同時使用了一個只能與SET SESSION同時使用的變量,或者如果您在設置一個全局變量時未指定GLOBAL(或@@),則MySQL會產生一個錯誤。

如果您想要把一個SESSION變量設置爲GLOBAL值或把一個GLOBAL值設置爲內部MySQL默認值,需使用DEFAULT關鍵詞。例如,在把max_join_size會話值設置爲全局值時,以下兩個語句是一樣的:

SET max_join_size=DEFAULT;
SET @@session.max_join_size=@@global.max_join_size;

您可以使用SHOW VARIABLES來得到系統變量清單。(見13.5.4.21節,“SHOW VARIABLES語法”。)要獲得與樣式匹配的一個具體的變量名稱或者名稱清單,需使用LIKE子句,使用方法如下:

SHOW VARIABLES LIKE 'max_join_size';
SHOW GLOBAL VARIABLES LIKE 'max_join_size';

要得到名稱與樣式匹配的變量的清單,需使用通配符‘%’:

SHOW VARIABLES LIKE 'have%';
SHOW GLOBAL VARIABLES LIKE 'have%';

通配符可以被用於相匹配的樣式中的任何位置。

您也可以通過使用@@[global.|local.]var_name語法和SELECT來得到值:

SELECT @@max_join_size, @@global.max_join_size;

當您使用SELECT @@var_name(即您不指定全局、會話或本地)來恢復一個變量時,則MySQL會返回SESSION值(如果存在)或者GLOBAL值。

以下清單用於描述帶有非標準語法的變量,或描述在系統變量清單中(見5.3.3節,“服務器系統變量”。)中沒有描述的變量。儘管這些變量沒有被SHOW VARIABLES顯示,但是您可以使用SELECT來獲得它們的值(例外情況是,使用CHARACTER SETSET NAMES)。例如:

mysql> SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
|            1 |
+--------------+

·         AUTOCOMMIT = {0 | 1}

設置autocommit模式。如果設置爲1,則所有對錶的更改會立刻生效。如果設置爲0,則您必須使用COMMIT來接受一個事務,或使用ROLLBACK來取消它。如果您把AUTOCOMMIT模式從0改爲1,則MySQL會對開放事務執行一個自動COMMIT。開始一個事務的另一種方法是使用一個START TRANSACTIONBEGIN語句。請參見13.4.1節,“START TRANSACTION, COMMIT和ROLLBACK語法”

·         BIG_TABLES = {0 | 1}

如果設置爲1,所有的臨時表被存儲在磁盤中,而不是存儲在儲存期中。這樣會稍微慢些,但是對於需要一個大型臨時表的SELECT操作,不會發生The table tbl_name is full錯誤。對於一個新連接,默認值爲0(使用存儲器內部臨時表)。通常,您不必設置此變量,因爲根據需要,存儲器內部表會被自動轉換爲以磁盤爲基礎的表。( 註釋:本變量以前被命名爲SQL_BIG_TABLES。)

·         CHARACTER SET {charset_name | DEFAULT}

本語句使用給定的映射爲所有來自客戶端和指向客戶端的字符串建立映射。您可以通過在MySQL源分佈中編輯sql/convert.cc來添加新的映射。SET CHARACTER SET用於設定三個會話系統變量:character_set_clientcharacter_set_results被設置爲給定的字符集,character_set_connection被設置爲character_set_database值。

可以通過使用DEFAULT值恢復默認的映射。

注意,SET CHARACTER SET的語法與設置其它選項的語法不同。

·         FOREIGN_KEY_CHECKS = {0 | 1}

如果設置爲1(默認情況),則檢查InnoDB表的外鍵限制條件。如果設置爲0,則限制條件被忽略。如果重新載入InnoDB表時按照的順序與上級/下級目錄所要求的順序不同,此時禁用外鍵檢查是有用的。請參見15.2.6.4節,“FOREIGN KEY約束”

·         IDENTITY = value

該變量是LAST_INSERT_ID變量的同義詞。該變量的作用是保持與其它數據庫兼容。您可以使用SELECT @@IDENTITY讀取其值,並可以使用SET IDENTITY設置它。

·         INSERT_ID = value

用於設置將被以下INSERTALTER TABLE語句使用的值。此值在插入一個AUTO_INCREMENT值時使用。本語句主要和二進制日誌同時使用。

·         LAST_INSERT_ID = value

用於設定將從LAST_INSERT_ID()被返回的值。當您在用於更新表的語句中使用LAST_INSERT_ID()時,它被存儲在二進制日誌中。設置此變量不會更新由mysql_insert_id() C API函數返回的值。

·         NAMES {'charset_name' | DEFAULT}

SET NAMES用於把三個會話系統變量character_set_client, character_set_connectioncharacter_set_results設置爲給定的字符集。把character_set_connection設置爲charset_name時,同時把collation_connection設置爲charset_name的默認整序。

使用一個DEFAULT值可以恢復默認的映射。

注意,SET NAMES的語法與用於設置其它選項的語法不同。

·         ONE_SHOT

這不是一個服務器系統變量,但是它可以被用來影響用於設置字符集、整序和時區的變量的效果。ONE_SHOT主要被用於複製:mysqlbinlog使用SET ONE_SHOT來暫時地修改字符集、整序和時區變量的值,以反映出它們原先的值。

您不能在使用ONE_SHOT時使用除允許的變量以外的變量;如果您這麼做,您會得到如下錯誤:

mysql> SET ONE_SHOT max_allowed_packet = 1;
ERROR 1382 (HY000): The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server 

如果同時使用ONE_SHOT和被允許的變量,則會根據要求更改變量,但是會在下一個語句後,重新設置所有的字符集、整序和與時區有關的服務器系統變量。唯一的例外是,當下一個語句是SET語句時,不會進行重新設置。換句話說,在下一個非SET語句之後,纔會進行重新設置。例如:

mysql> SET ONE_SHOT character_set_connection = latin5;
 
mysql> SET ONE_SHOT collation_connection = latin5_turkish_ci;
 
mysql> SHOW VARIABLES LIKE '%_connection';
+--------------------------+-------------------+
| Variable_name            | Value             |
+--------------------------+-------------------+
| character_set_connection | latin5            |
| collation_connection     | latin5_turkish_ci |
+--------------------------+-------------------+
 
mysql> SHOW VARIABLES LIKE '%_connection';
+--------------------------+-------------------+
| Variable_name            | Value             |
+--------------------------+-------------------+
| character_set_connection | latin1            |
| collation_connection     | latin1_swedish_ci |
+--------------------------+-------------------+

·         SQL_NOTES = {0 | 1}

當設置爲1時(默認情況),“注意”一級的警報被記錄下來。當設置爲0時,“注意”警告被壓制。Mysqldump包含輸出,用於把此變量設置爲0,這樣,對於不會影響重新載入操作整體性的事件,重新載入轉儲文件時不會產生警告。

·         SQL_AUTO_IS_NULL = {0 | 1}

如果設置爲1(默認情況),您可以通過使用以下結構查找包含一個AUTO_INCREMENT列的表的最後插入的行:

WHERE auto_increment_column IS NULL

此性質被有些ODBC程序,比如Access使用。

·         SQL_BIG_SELECTS = {0 | 1}

如果設定爲0,則MySQL會放棄有可能會花很長時間來執行的SELECT語句(也就是,對於這些語句,優化程序估算被檢查的行的數目超過了max_join_size的值)。當一個不妥當的WHERE語句被髮布後,本語句有用。一個新連接的默認值爲1,這可以允許所有的SELECT語句。

如果您把max_join_size系統變量設置爲除DEFAULT以外的值,則SQL_BIG_SELECTS被設置爲0

·         SQL_BUFFER_RESULT = {0 | 1}

SQL_BUFFER_RESULT會迫使來自SELECT語句的結果被放入臨時表中。這可以幫助MySQL早點解除表鎖定。當需要花較長時間把結果發送給客戶端時,這是有好處的。

·         SQL_LOG_BIN = {0 | 1}

如果設置爲0,則客戶端的二進制日誌中不會記錄日誌。客戶端必須擁有SUPER權限來設置此選項。

·         SQL_LOG_OFF = {0 | 1}

如果設置爲1,則此客戶端的總查詢日誌中不會記錄日誌。客戶端必須擁有SUPER權限來設置此選項。

·         SQL_LOG_UPDATE = {0 | 1}

不贊成使用本變量。本變量被映射到SQL_LOG_BIN

·         SQL_QUOTE_SHOW_CREATE = {0 | 1}

如果設置爲1,則SHOW CREATE TABLE會對錶和列的名稱加引號。如果設置爲0,則加引號操作被禁用。默認情況下,本選項被啓用,因此對於含有需要加引號的名稱的表,複製操作起作用。請參見13.5.4.5節,“SHOW CREATE TABLE語法”

·         SQL_SAFE_UPDATES = {0 | 1}

如果設置爲1,則MySQL會放棄在WHERE子句或LIMIT子句中不使用關鍵字的UPDATEDELETE語句。這樣,當關鍵字使用不正確時,也有可能理解UPDATEDELETE語句。這樣就可以更改或刪除大量的行。

·         SQL_SELECT_LIMIT = {value | DEFAULT}

SELECT語句返回的記錄的最大數目。對於一個新連接,默認值是“unlimited”。如果您更改了限值,可以使用SQL_SELECT_LIMIT DEFAULT值恢復默認值。

如果SELECT有一個LIMIT子句,則LIMIT優先於SQL_SELECT_LIMIT值。

SQL_SELECT_LIMT不適用於在被存儲的子程序中執行的SELECT語句。它也不適用於不會產生將被返回到客戶端的結果集合的SELECT語句。這些包括子查詢中的SELECT語句,CREATE TABLE...SELECTINSERT INTO...SELECT

·         SQL_WARNINGS = {0 | 1}

本變量用於控制當出現警告時,單行INSERT語句是否產生一個信息字符串。默認值爲0。把值設置爲1,來產生一個信息字符串。

·         TIMESTAMP = {timestamp_value | DEFAULT}

用於爲此客戶端設置時間。當您使用二進制日誌來恢復行時,本語句用於得到原始的時間標記。timestamp_value應爲一個Unix時間標記,而不是MySQL時間標記。

·         UNIQUE_CHECKS = {0 | 1}

如果設置爲1(默認情況),則會對InnoDB表中的二級索引執行唯一性檢查。如果設置爲0,則對於被插入到InnoDB的插入緩衝器中的索引登錄項,不執行唯一性檢查。如果您可以肯定您的數據不違反唯一性要求,則您可以把此值設定爲0,以加快向InnoDB導入大型表的速度。

13.5.4. SHOW語法

SHOW有多種形式,可以提供有關數據庫、表、列或服務器狀態的信息。本節敘述以下內容:

SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
SHOW CREATE DATABASE db_name
SHOW CREATE TABLE tbl_name
SHOW DATABASES [LIKE 'pattern']
SHOW ENGINE engine_name {LOGS | STATUS }
SHOW [STORAGE] ENGINES
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW GRANTS FOR user
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW INNODB STATUS
SHOW [BDB] LOGS
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']
SHOW TRIGGERS
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
SHOW WARNINGS [LIMIT [offset,] row_count]

SHOW語句還有一些形式,可以提供有關複製型主服務器和從屬服務器的信息。這些形式在13.6節,“複製語句”中進行了敘述。

SHOW BINLOG EVENTS
SHOW MASTER LOGS
SHOW MASTER STATUS
SHOW SLAVE HOSTS
SHOW SLAVE STATUS

如果一個給定的SHOW語句的語法包括一個LIKE 'pattern'部分,則'pattern'是一個可以包含SQL %’和‘_’通配符的字符串。對於把語句輸出值限定爲匹配值,本樣式是有用的。

13.5.4.1. SHOW CHARACTER SET語法

SHOW CHARACTER SET [LIKE 'pattern']

SHOW CHARACTER SET語句用於顯示所有可用的字符集。該語句取一個自選的LIKE子句。該子句指示哪些字符集名稱可以匹配。舉例說明:

mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description                 | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1  | cp1252 West European        | latin1_swedish_ci |      1 |
| latin2  | ISO 8859-2 Central European | latin2_general_ci |      1 |
| latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |      1 |
| latin7  | ISO 8859-13 Baltic          | latin7_general_ci |      1 |
+---------+-----------------------------+-------------------+--------+

Maxlen列顯示用於存儲一個字符的最大的字節數目。

13.5.4.2. SHOW COLLATION語法

SHOW COLLATION [LIKE 'pattern']

來自SHOW COLLATION的輸出包括所有可用的字符集。該語句取一個自選的LIKE子句。該子句的pattern指示哪些整序名稱可以匹配。舉例說明:

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         |          |       0 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       0 |
| latin1_danish_ci  | latin1  | 15 |         |          |       0 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       0 |
| latin1_general_ci | latin1  | 48 |         |          |       0 |
| latin1_general_cs | latin1  | 49 |         |          |       0 |
| latin1_spanish_ci | latin1  | 94 |         |          |       0 |
+-------------------+---------+----+---------+----------+---------+

Default列指示對於其字符集,整序值是否是默認值。Compiled指示字符集是否被編輯到服務器中。Sortlen與對字符串(在字符集中表達)分類所需的存儲器的數量有關。

13.5.4.3. SHOW COLUMNS語法

SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']

SHOW COLUMNS顯示在一個給定表中的各列的信息。對於試圖,本語句也起作用。

如果列類型與根據您的CREATE TABLE語句所預期的列類型不同,則需注意,當您創建或更改表時,MySQL有時會更改列類型。出現這種情況的條件在13.1.5.1節,“沉寂的列規格變更”中進行了描述。

FULL關鍵詞會使得輸出中包含您擁有的權限,幷包含對每一列各自的評註。

您可以使用db_name.tbl_name作爲tbl_name FROM db_name語法的另一種形式。換句話說,這兩個語句是等價的:

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

SHOW FIELDSSHOW COLUMNS的同義詞。您也可以使用mysqlshow db_name tbl_name命令列舉表的各列。

DESCRIBE語句提供與SHOW COLUMNS相近的信息。請參見13.3.1節,“DESCRIBE語法(獲取關於列的信息)”

13.5.4.4. SHOW CREATE DATABASE語法

SHOW CREATE {DATABASE | SCHEMA} db_name

顯示用於創建給定數據庫CREATE DATABASE語句。也可以使用SHOW CREATE SCHEMA

mysql> SHOW CREATE DATABASE test\G
*************************** 1. row ***************************
       Database: test
Create Database: CREATE DATABASE `test`
                 /*!40100 DEFAULT CHARACTER SET latin1 */
 
mysql> SHOW CREATE SCHEMA test\G
*************************** 1. row ***************************
       Database: test
Create Database: CREATE DATABASE `test` 
                 /*!40100 DEFAULT CHARACTER SET latin1 */

13.5.4.5. SHOW CREATE TABLE語法

SHOW CREATE TABLE tbl_name

顯示用於創建給定表的CREATE TABLE語句。本語句對視圖也起作用。

mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE t (
  id INT(11) default NULL auto_increment,
  s char(60) default NULL,
  PRIMARY KEY (id)
) ENGINE=MyISAM
 

根據SQL_QUOTE_SHOW_CREATE選項,SHOW CREATE TABLE會對錶名稱和列名稱加引號。請參見13.5.3節,“SET語法”

13.5.4.6. SHOW DATABASES語法

SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']

SHOW DATABASES可以在MySQL服務器主機上列舉數據庫。您也可以使用mysqlshow命令得到此清單。您只能看到您擁有某些權限的數據庫,除非您擁有全局SHOW DATABASES權限。

如果服務器以--skip-show-database選項爲起始,則您根本不能使用本語句,除非您擁有SHOW DATABASES權限。

也可以使用SHOW SCHEMAS

13.5.4.7. SHOW ENGINE語法

SHOW ENGINE engine_name {LOGS | STATUS }

SHOW ENGINE顯示存儲引擎的日誌或狀態信息。目前支持以下語句:

SHOW ENGINE BDB LOGS
SHOW ENGINE INNODB STATUS

SHOW ENGINE BDB LOGS顯示原有BDB日誌文件的狀態信息。它會返回以下字段:

·         File

通向日誌文件的完整路徑。

·         Type

日誌文件類型(用於Berkeley DB日誌文件的BDB)。

·         Status

日誌文件的狀態(如果文件可以被取消,則爲FREE。如果文件被事務子系統需要,則爲IN USE

SHOW ENGINE INNODB STATUS顯示InnoDB存儲引擎狀態的全面信息。

這些語句的舊的同義詞(現在不贊成使用)是SHOW [BDB] LOGSSHOW INNODB STATUS

SHOW ENGINE可以從MySQL 4.1.2起使用。

13.5.4.8. SHOW ENGINES語法

SHOW [STORAGE] ENGINES

SHOW ENGINES顯示存儲引擎的狀態信息。對於檢查一個存儲引擎是否被支持,或者對於查看默認引擎是什麼,本語句十分有用。SHOW TABLE TYPES是同義詞,但不贊成使用。

mysql> SHOW ENGINES\G
*************************** 1. row ***************************
 Engine: MyISAM
Support: DEFAULT
Comment: Default engine as of MySQL 3.23 with great performance
*************************** 2. row ***************************
 Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
*************************** 3. row ***************************
 Engine: HEAP
Support: YES
Comment: Alias for MEMORY
*************************** 4. row ***************************
 Engine: MERGE
Support: YES
Comment: Collection of identical MyISAM tables
*************************** 5. row ***************************
 Engine: MRG_MYISAM
Support: YES
Comment: Alias for MERGE
*************************** 6. row ***************************
 Engine: ISAM
Support: NO
Comment: Obsolete storage engine, now replaced by MyISAM
*************************** 7. row ***************************
 Engine: MRG_ISAM
Support: NO
Comment: Obsolete storage engine, now replaced by MERGE
*************************** 8. row ***************************
 Engine: InnoDB
Support: YES
Comment: Supports transactions, row-level locking, and foreign keys
*************************** 9. row ***************************
 Engine: INNOBASE
Support: YES
Comment: Alias for INNODB
*************************** 10. row ***************************
 Engine: BDB
Support: NO
Comment: Supports transactions and page-level locking
*************************** 11. row ***************************
 Engine: BERKELEYDB
Support: NO
Comment: Alias for BDB
*************************** 12. row ***************************
 Engine: NDBCLUSTER
Support: DISABLED
Comment: Clustered, fault-tolerant, memory-based tables
*************************** 13. row ***************************
 Engine: NDB
Support: DISABLED
Comment: Alias for NDBCLUSTER
*************************** 14. row ***************************
 Engine: EXAMPLE
Support: NO
Comment: Example storage engine
*************************** 15. row ***************************
 Engine: ARCHIVE
Support: YES
Comment: Archive storage engine
*************************** 16. row ***************************
 Engine: CSV
Support: YES
Comment: CSV storage engine
*************************** 17. row ***************************
 Engine: FEDERATED
Support: NO
Comment: Federated MySQL storage engine
*************************** 18. row ***************************
 Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)

Support值指示某個存儲引擎是否被支持,並指示哪個是默認引擎。例如,如果服務器以--default-table-type=InnoDB選項爲起始,則InnoDB行的Support值爲DEFAULT值。請參見第15章:存儲引擎和表類型

13.5.4.9. SHOW ERRORS語法

SHOW ERRORS [LIMIT [offset,] row_count]
SHOW COUNT(*) ERRORS

本語句與SHOW WARNINGS接近,不過該語句只顯示錯誤,不同時顯示錯誤、警告和注意。

LIMIT子句與SELECT語句具有相同的語法,請參見13.2.7節,“SELECT語法”

SHOW COUNT(*) ERRORS語句顯示錯誤的數目。您也可以從error_count變量中找回此數目:

SHOW COUNT(*) ERRORS;
SELECT @@error_count;

要了解更多信息,請參見13.5.4.22節,“SHOW WARNINGS語法”

13.5.4.10. SHOW GRANTS語法

SHOW GRANTS FOR user

本語句列出了在爲MySQL用戶賬戶複製權限時必須發佈的GRANT語句。

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

要對當前的會話列出權限,您可以使用以下語句之一:

SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER;
SHOW GRANTS FOR CURRENT_USER();

13.5.4.11. SHOW INDEX語法

SHOW INDEX FROM tbl_name [FROM db_name]

SHOW INDEX會返回表索引信息。其格式與ODBC中的SQLStatistics調用相似。

SHOW INDEX會返回以下字段:

·         Table

表的名稱。

·         Non_unique

如果索引不能包括重複詞,則爲0。如果可以,則爲1

·         Key_name

索引的名稱。

·         Seq_in_index

索引中的列序列號,從1開始。

·         Column_name

列名稱。

·         Collation

列以什麼方式存儲在索引中。在MySQL中,有值‘A’(升序)或NULL(無分類)。

·         Cardinality

索引中唯一值的數目的估計值。通過運行ANALYZE TABLEmyisamchk -a可以更新。基數根據被存儲爲整數的統計數據來計數,所以即使對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL使用該索引的機會就越大。

·         Sub_part

如果列只是被部分地編入索引,則爲被編入索引的字符的數目。如果整列被編入索引,則爲NULL

·         Packed

指示關鍵字如何被壓縮。如果沒有被壓縮,則爲NULL

·         Null

如果列含有NULL,則含有YES。如果沒有,則該列含有NO

·         Index_type

用過的索引方法(BTREE, FULLTEXT, HASH, RTREE)。

·         Comment

多種評註。

您可以使用db_name.tbl_name作爲tbl_name FROM db_name語法的另一種形式。這兩個語句是等價的:

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

SHOW KEYSSHOW INDEX的同義詞。您也可以使用mysqlshow -k db_name tbl_name命令列舉一個表的索引。

13.5.4.12. SHOW INNODB STATUS語法

SHOW INNODB STATUS

MySQL 5.1中,這是SHOW ENGINE INNODB STATUS的同義詞,但不贊成使用。請參見13.5.4.7節,“SHOW ENGINE語法”

13.5.4.13. SHOW LOGS語法

SHOW [BDB] LOGS

MySQL 5.1中,這是SHOW ENGINE BDB LOGS的同義詞,但是不贊成使用。請參見13.5.4.7節,“SHOW ENGINE語法”

13.5.4.14. SHOW OPEN TABLES語法

SHOW OPEN TABLES [FROM db_name] [LIKE 'pattern']

SHOW OPEN TABLES列舉在表緩存中當前被打開的非TEMPORARY表。請參見7.4.9節,“MySQL如何打開和關閉表”

SHOW OPEN TABLES會返回以下字段:

·         Database

含有該表的數據庫。

·         Table

表名稱。

·         In_use

表當前被查詢使用的次數。如果該數爲零,則表是打開的,但是當前沒有被使用。

·         Name_locked

表名稱是否被鎖定。名稱鎖定用於取消表或對錶進行重命名等操作。

13.5.4.15. SHOW PRIVILEGES語法

SHOW PRIVILEGES

SHOW PRIVILEGES顯示MySQL服務器支持的系統權限清單。確切的輸出根據您的服務器的版本而定。

mysql> SHOW PRIVILEGES\G
*************************** 1. row ***************************
Privilege: Alter
Context: Tables
Comment: To alter the table
*************************** 2. row ***************************
Privilege: Alter routine
Context: Functions,Procedures
Comment: To alter or drop stored functions/procedures
*************************** 3. row ***************************
Privilege: Create
Context: Databases,Tables,Indexes
Comment: To create new databases and tables
*************************** 4. row ***************************
Privilege: Create routine
Context: Functions,Procedures
Comment: To use CREATE FUNCTION/PROCEDURE
*************************** 5. row ***************************
Privilege: Create temporary tables
Context: Databases
Comment: To use CREATE TEMPORARY TABLE
*************************** 6. row ***************************
Privilege: Create view
Context: Tables
Comment: To create new views
*************************** 7. row ***************************
Privilege: Create user
Context: Server Admin
Comment: To create new users
*************************** 8. row ***************************
Privilege: Delete
Context: Tables
Comment: To delete existing rows
*************************** 9. row ***************************
Privilege: Drop
Context: Databases,Tables
Comment: To drop databases, tables, and views
*************************** 10. row ***************************
Privilege: Execute
Context: Functions,Procedures
Comment: To execute stored routines
*************************** 11. row ***************************
Privilege: File
Context: File access on server
Comment: To read and write files on the server
*************************** 12. row ***************************
Privilege: Grant option
Context: Databases,Tables,Functions,Procedures
Comment: To give to other users those privileges you possess
*************************** 13. row ***************************
Privilege: Index
Context: Tables
Comment: To create or drop indexes
*************************** 14. row ***************************
Privilege: Insert
Context: Tables
Comment: To insert data into tables
*************************** 15. row ***************************
Privilege: Lock tables
Context: Databases
Comment: To use LOCK TABLES (together with SELECT privilege)
*************************** 16. row ***************************
Privilege: Process
Context: Server Admin
Comment: To view the plain text of currently executing queries
*************************** 17. row ***************************
Privilege: References
Context: Databases,Tables
Comment: To have references on tables
*************************** 18. row ***************************
Privilege: Reload
Context: Server Admin
Comment: To reload or refresh tables, logs and privileges
*************************** 19. row ***************************
Privilege: Replication client
Context: Server Admin
Comment: To ask where the slave or master servers are
*************************** 20. row ***************************
Privilege: Replication slave
Context: Server Admin
Comment: To read binary log events from the master
*************************** 21. row ***************************
Privilege: Select
Context: Tables
Comment: To retrieve rows from table
*************************** 22. row ***************************
Privilege: Show databases
Context: Server Admin
Comment: To see all databases with SHOW DATABASES
*************************** 23. row ***************************
Privilege: Show view
Context: Tables
Comment: To see views with SHOW CREATE VIEW
*************************** 24. row ***************************
Privilege: Shutdown
Context: Server Admin
Comment: To shut down the server
*************************** 25. row ***************************
Privilege: Super
Context: Server Admin
Comment: To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
*************************** 26. row ***************************
Privilege: Update
Context: Tables
Comment: To update existing rows
*************************** 27. row ***************************
Privilege: Usage
Context: Server Admin
Comment: No privileges - allow connect only

13.5.4.16. SHOW PROCESSLIST語法

SHOW [FULL] PROCESSLIST

SHOW PROCESSLIST顯示哪些線程正在運行。您也可以使用mysqladmin processlist語句得到此信息。如果您有SUPER權限,您可以看到所有線程。否則,您只能看到您自己的線程(也就是,與您正在使用的MySQL賬戶相關的線程)。請參見13.5.5.3節,“KILL語法”。如果您不使用FULL關鍵詞,則只顯示每個查詢的前100個字符。

本語句報告TCP/IP連接的主機名稱(採用host_name:client_port格式),以方便地判定哪個客戶端正在做什麼。

如果您得到“too many connections”錯誤信息,並且想要了解正在發生的情況,本語句是非常有用的。MySQL保留一個額外的連接,讓擁有SUPER權限的 賬戶使用,以確保管理員能夠隨時連接和檢查系統(假設您沒有把此權限給予所有的用戶)。

在來自SHOW PROCESSLIST的輸出中常見的一些狀態:

·         Checking table

線程正在執行(自動)表格檢查。

·         Closing tables

意味着線程正在刷新更改後的表數據,並正在關閉使用過的表。這應該是一個快速的操作。如果不快,則您應該驗證您的磁盤沒有充滿,並且磁盤沒有被超負荷使用。

·         Connect Out

連接到主服務器上的從屬服務器。

·         Copying to tmp table on disk

臨時結果集合大於tmp_table_size。線程把臨時表從存儲器內部格式改變爲磁盤模式,以節約存儲器。

·         Creating tmp table

線程正在創建一個臨時表,以保持部分結果。

·         deleting from main table

服務器正在執行多表刪除的第一部分,只從第一個表中刪除。

·         deleting from reference tables

服務器正在執行多表刪除的第二部分,從其它表中刪除匹配的行。

·         Flushing tables

線程正在執行FLUSH TABLES,並正在等待所有線程,以關閉表。

·         FULLTEXT initialization

服務器正在準備執行一個自然語言全文本搜索。

·         Killed

有人已經向線程發送了一個KILL命令。在下一次檢查終止標記時,應放棄。該標記在MySQL的每個大循環中都檢查,但是在有些情況下,線程終止只需要較短的時間。如果該線程被其它線程鎖定,則只要其它線程接觸鎖定,終止操作就會生效。

·         Locked

該查詢被其它查詢鎖定。

·         Sending data

線程正在爲SELECT語句處理行,同時正在向客戶端發送數據。

·         Sorting for group

線程正在進行分類,以滿足GROUP BY要求。

·         Sorting for order

線程正在進行分類,以滿足ORDER BY要求。

·         Opening tables

線程正在試圖打開一個表。這應該是非常快的過程,除非打開操作受到阻止。例如,一個ALTER TABLE或一個LOCK TABLE語句可以阻止打開一個表,直到語句完成爲止。

·         Removing duplicates

查詢正在使用SELECT DISTINCT。使用時,在早期階段,MySQL不能優化不同的操作。因此,MySQL要求一個額外的階段,以便在把結果發送給客戶端之前取消所有的複製行。

·         Reopen table

線程得到一個表鎖定,但是在得到鎖定後被通知帶下方的表結構已更改了。它已經釋放了鎖定,關閉了表,並試圖重新打開它。

·         Repair by sorting

修復代碼正在使用一個分類來創建索引。

·         Repair with keycache

修復代碼正在通過關鍵緩存一個接一個地使用創建關鍵字。這比通過分類修復要慢很多。

·         Searching rows for update

線程正在進行第一階段,以在更新之前,查找所有匹配的行。如果UPDATE正在更改用於查找相關行的索引,則必須這麼做。

·         Sleeping

線程正在等待客戶端,以向它發送一個新語句。

·         System lock

線程正在等待得到一個用於表的外部系統鎖定。如果您沒有正在使用多個正在訪問同一個表的mysqld服務器,則您可以使用--skip-external-locking選項禁用系統鎖定。

·         Upgrading lock

INSERT DELAYED管理程序正在試圖得到一個表鎖定,以插入行。

·         Updating

線程正在搜索行,並正在更新這些行。

·         User Lock

線程正在等待GET_LOCK()

·         Waiting for tables

線程得到一個通知,表的底層結構已經改變,需要重新打開表以得到新的結構。但是,爲了能重新打開表,必須等待,直到所有其它的線程已經關閉了正在被質詢的表。

如果其它線程已經對正在被質詢的表使用了FLUSH TABLES或以下語句之一:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLEOPTIMIZE TABLE;則會出現通知。

·         waiting for handler insert

INSERT DELAYED管理程序已經處理了所有處於等待狀態的插入,並正在等待新插入。

多數狀態對應於非常快的操作。如果一個線程在這些狀態下停留了數秒,則可能是有問題,需要進行調查。

有一些其它的狀態,在前面的清單中沒有提及,但是其中有很多狀態對於查找服務器中的程序錯誤是有用的。

13.5.4.17. SHOW STATUS語法

SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']

SHOW STATUS提供服務器狀態信息。此信息也可以使用mysqladmin extended-status命令獲得。

此處顯示了局部的輸出。對於您的服務器,變量和值的清單可以是不同的。在5.3.4節,“服務器狀態變量”中給出了每個變量的意義。

mysql> SHOW STATUS;
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| Aborted_clients          | 0          |
| Aborted_connects         | 0          |
| Bytes_received           | 155372598  |
| Bytes_sent               | 1176560426 |
| Connections              | 30023      |
| Created_tmp_disk_tables  | 0          |
| Created_tmp_tables       | 8340       |
| Created_tmp_files        | 60         |
...                       ...          ...
| Open_tables              | 1          |
| Open_files               | 2          |
| Open_streams             | 0          |
| Opened_tables            | 44600      |
| Questions                | 2026873    |
...                       ...          ...
| Table_locks_immediate    | 1920382    |
| Table_locks_waited       | 0          |
| Threads_cached           | 0          |
| Threads_created          | 30022      |
| Threads_connected        | 1          |
| Threads_running          | 1          |
| Uptime                   | 80380      |
+--------------------------+------------+

使用LIKE子句,該語句只顯示匹配該樣式的那些變量:

mysql> SHOW STATUS LIKE 'Key%';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| Key_blocks_used    | 14955    |
| Key_read_requests  | 96854827 |
| Key_reads          | 162040   |
| Key_write_requests | 7589728  |
| Key_writes         | 3813196  |
+--------------------+----------+

使用GLOBAL選項,您可以得到所有MySQL連接的狀態值。使用SESSION,您可以得到所有當前連接的狀態值。如果您兩個選項都不使用,則默認值爲SESSIONLOCALSESSION的同義詞。

注意,有些狀態變量只有一個全局值。對於這些變量,使用GLOBALSESSION會得到同樣的值。

13.5.4.18. SHOW TABLE STATUS語法

SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']

SHOW TABLE STATUS的性質與SHOW TABLE類似,不過,可以提供每個表的大量信息。您也可以使用mysqlshow --status db_name命令得到此清單。

本語句也顯示視圖信息。

對於NDB Cluster表,本語句的輸出顯示Avg_row_lengthData_length列的適當值,不過BLOB列沒有被考慮進來。另外,複製數量在Comment列中顯示(作爲number_of_replicas)。

SHOW TABLE STATUS會返回以下字段:

·         Name

表的名稱。

·         Engine

表的存儲引擎。在MySQL 4.1.2之前,本值被標記爲Type。請參見第15章:存儲引擎和表類型

·         Version

表的.frm文件的版本號。

·         Row_format

行存儲格式(Fixed, Dynamic, Compressed, Redundant, Compact)。InnoDB表的格式被報告爲RedundantCompact

·         Rows

行的數目。部分存儲引擎,如MyISAM,存儲精確的數目。

對於其它存儲引擎,比如InnoDB,本值是一個大約的數,與實際值相差可達4050%。在這些情況下,使用SELECT COUNT(*)來獲得準確的數目。

對於在INFORMATION_SCHEMA數據庫中的表,Rows值爲NULL

·         Avg_row_length

平均的行長度。

·         Data_length

數據文件的長度。

·         Max_data_length

數據文件的最大長度。如果給定了數據指針的大小,這是可以被存儲在表中的數據的字節總數。

·         Index_length

索引文件的長度。

·         Data_free

被整序,但是未使用的字節的數目。

·         Auto_increment

下一個AUTO_INCREMENT值。

·         Create_time

什麼時候表被創建。

·         Update_time

什麼時候數據文件被最後一次更新。

·         Check_time

什麼時候表被最後一次檢查。不是所有的存儲引擎此時都更新,在此情況下,值爲NULL

·         Collation

表的字符集和整序。

·         Checksum

活性校驗和值。

·         Create_options

CREATE TABLE同時使用的額外選項。

·         Comment

創建表時使用的評註(或者有關爲什麼MySQL可以訪問表信息的說明)。

在表評註中,InnoDB表報告表所屬的表空間的空閒空間。對於一個位於共享表空間中的表,這是共享表空間中的空閒空間。如果您正在使用多個表空間,並且該表有自己的表空間,則空閒空間只用於此表。

對於MEMORY (HEAP)表,Data_length, Max_data_lengthIndex_length值近似於被整序的存儲器的實際值。整序算法預留了大量的存儲器,以減少整序操作的數量。

對於視圖,由SHOW TABLE STATUS顯示的所有字段均爲NULL。例外情況是Name指示爲視圖名稱同時Comment稱爲視圖。

13.5.4.19. SHOW TABLES語法

SHOW [FULL] TABLES [FROM db_name] [LIKE 'pattern']

SHOW TABLES列舉了給定數據庫中的非TEMPORARY表。您也可以使用mysqlshow db_name命令得到此清單。

本命令也列舉數據庫中的其它視圖。支持FULL修改符,這樣SHOW FULL TABLES就可以顯示第二個輸出列。對於一個表,第二列的值爲BASE TABLE;對於一個視圖,第二列的值爲VIEW

註釋:如果您對於一個表沒有權限,則該表不會在來自SHOW TABLES或的mysqlshow db_name輸出中顯示。

13.5.4.20. SHOW TRIGGERS語法

SHOW TRIGGERS [FROM db_name] [LIKE expr]

SHOW TRIGGERS列出了目前被MySQL服務器定義的觸發程序。

對於在21.3節,“使用觸發程序”中定義的觸發程序ins_sum,本語句的輸出顯示如下:

mysql> SHOW TRIGGERS LIKE 'acc%';
+---------+--------+---------+-------------------------------+--------+---------+
| Trigger | Event  | Table   | Statement                     | Timing | Created |
+---------+--------+---------+-------------------------------+--------+---------+
| ins_sum | INSERT | account |  SET @sum = @sum + NEW.amount | BEFORE | NULL    |
+---------+--------+---------+-------------------------------+--------+---------+

註釋:當使用一個含有SHOW TRIGGERSLIKE子句時,待匹配的表達式(expr)會與觸發程序定義時所在的表的名稱相比較,而不與觸發程序的名稱相比較:

mysql> SHOW TRIGGERS LIKE 'ins%';
Empty set (0.01 sec)

對本語句輸出中的各列的簡要解釋如下:

·         Trigger: 觸發程序的名稱。

·         Event: 調用觸發程序的時間。必須爲'INSERT', 'UPDATE''DELETE'.之一。

·         Table: 觸發程序定義時對應的表。

·         Statement: 當觸發程序被調用時執行的語句。這與在INFORMATION_SCHEMA.TRIGGERSACTION_STATEMENT列中顯示的文本一樣。

·         Timing: 'BEFORE''AFTER'兩個值之一。

·         Created: 目前,本列的值爲NULL

爲了執行SHOW TRIGGERS,您必須擁有SUPER權限。

同時也見23.1.16節,“INFORMATION_SCHEMA TRIGGERS表”

13.5.4.21. SHOW VARIABLES語法

SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']

SHOW VARIABLES顯示了部門MySQL系統變量的值。本信息也可以使用mysqladmin variables命令獲得。

使用GLOBAL選項,您可以獲得被用於MySQL新連接的值。使用SESSION,您可以得到對於當前連接起效的值。如果您兩個選項都不使用,默認值爲SESSION

LOCALSESSION的同義詞。

如果默認值不合適,當mysqld啓動時或在SET語句運行過程中,您可以使用命令行選項設置多數的這類變量。請參見5.3.1節,“mysqld命令行選項”13.5.3節,“SET語法

此處顯示了部分的輸出。對於您的服務器,變量和值的清單會有所不同。在5.3.3節,“服務器系統變量”中給出了每個變量的意義。在7.5.2節,“調節服務器參數”中提供了有關調整變量的信息。

mysql> SHOW VARIABLES;
+---------------------------------+-----------------------------------------------+
| Variable_name                   | Value                                         |
+---------------------------------+-----------------------------------------------+
| auto_increment_increment        | 1                                             |
| auto_increment_offset           | 1                                             |
| automatic_sp_privileges         | ON                                            |
| back_log                        | 50                                            |
| basedir                         | /home/jon/bin/mysql-5.1/                      |
| binlog_cache_size               | 32768                                         |
| bulk_insert_buffer_size         | 8388608                                       |
| character_set_client            | latin1                                        |
| character_set_connection        | latin1                                        |
...                               ...                                              
| max_user_connections            | 0                                             |
| max_write_lock_count            | 4294967295                                    |
| multi_range_count               | 256                                           |
| myisam_data_pointer_size        | 6                                             |
| myisam_max_sort_file_size       | 2147483647                                    |
| myisam_recover_options          | OFF                                           |
| myisam_repair_threads           | 1                                             |
| myisam_sort_buffer_size         | 8388608                                       |
| ndb_autoincrement_prefetch_sz   | 32                                            |
| ndb_cache_check_time            | 0                                             |
| ndb_force_send                  | ON                                            |
...                               ...                                                       ...    
| time_zone                       | SYSTEM                                        |
| timed_mutexes                   | OFF                                           |
| tmp_table_size                  | 33554432                                      |
| tmpdir                          |                                               |
| transaction_alloc_block_size    | 8192                                          |
| transaction_prealloc_size       | 4096                                          |
| tx_isolation                    | REPEATABLE-READ                               |
| updatable_views_with_limit      | YES                                           |
| version                         | 5.1.2-alpha-log                               |
| version_comment                 | Source distribution                           |
| version_compile_machine         | i686                                          |
| version_compile_os              | suse-linux                                    |
| wait_timeout                    | 28800                                         |
+---------------------------------+-----------------------------------------------+

使用LIKE子句,本語句只顯示與樣式相匹配的變量:

mysql> SHOW VARIABLES LIKE 'have%';
+-----------------------+----------+
| Variable_name         | Value    |
+-----------------------+----------+
| have_archive          | YES      |
| have_bdb              | NO       |
| have_blackhole_engine | YES      |
| have_compress         | YES      |
| have_crypt            | YES      |
| have_csv              | YES      |
| have_example_engine   | NO       |
| have_federated_engine | NO       |
| have_geometry         | YES      |
| have_innodb           | YES      |
| have_isam             | NO       |
| have_ndbcluster       | DISABLED |
| have_openssl          | NO       |
| have_partition_engine | YES      |
| have_query_cache      | YES      |
| have_raid             | NO       |
| have_rtree_keys       | YES      |
| have_symlink          | YES      |
+-----------------------+----------+

13.5.4.22. SHOW WARNINGS語法

SHOW WARNINGS [LIMIT [offset,] row_count]
SHOW COUNT(*) WARNINGS

SHOW WARNINGS顯示由上一個生成消息的語句導致的錯誤、警告和注意消息。如果上一個使用表的語句未生成消息,則什麼也不顯示。SHOW ERRORS是其相關語句,只顯示錯誤。請參見13.5.4.9節,“SHOW ERRORS語法”

對於使用一個表的每個新語句,消息清單均重新設置。

SHOW COUNT(*) WARNINGS語句顯示錯誤、警告和注意的總數。您也可以從warning_count變量中找回此數目。

SHOW COUNT(*) WARNINGS;
SELECT @@warning_count;

如果max_error_count系統變量設置得過低,以致於有的消息沒有被存儲,則warning_count值可能比由SHOW WARNINGS顯示的消息數目要大。本節後部顯示的例子展示了這類情況是如何發生的。

LIMIT子句具有與SELECT語句相同的語法。請參見13.2.7節,“SELECT語法”

MySQL服務器會發回由上一個語句引起的錯誤、警告和注意的總數。如果您正在使用C API,則此值可以通過調用mysql_warning_count()來獲得。請參見25.2.3.69節,“mysql_warning_count()”

對於如LOAD DATA INFILE等語句和如INSERT, UPDATE, CREATE TABLEALTER TABLEDML語句,會生成警告。

以下DROP TABLE語句會導致一個注意:

mysql> DROP TABLE IF EXISTS no_such_table;
mysql> SHOW WARNINGS;
+-------+------+-------------------------------+
| Level | Code | Message                       |
+-------+------+-------------------------------+
| Note  | 1051 | Unknown table 'no_such_table' |
+-------+------+-------------------------------+

以下是一個簡單的例子,顯示了對於CREATE TABLE的一個語法警告,和對於INSERT的轉換警告:

mysql> CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4)) TYPE=MyISAM;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1287
Message: 'TYPE=storage_engine' is deprecated, use
         'ENGINE=storage_engine' instead
1 row in set (0.00 sec)
 
mysql> INSERT INTO t1 VALUES(10,'mysql'),(NULL,'test'),
    -> (300,'Open Source');
Query OK, 3 rows affected, 4 warnings (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 4
 
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1265
Message: Data truncated for column 'b' at row 1
*************************** 2. row ***************************
  Level: Warning
   Code: 1263
Message: Data truncated, NULL supplied to NOT NULL column 'a' at row 2
*************************** 3. row ***************************
  Level: Warning
   Code: 1264
Message: Data truncated, out of range for column 'a' at row 3
*************************** 4. row ***************************
  Level: Warning
   Code: 1265
Message: Data truncated for column 'b' at row 3
4 rows in set (0.00 sec)

要存儲的錯誤、警告和注意消息的最大數目由max_error_count系統變量控制。默認情況下,該值爲64。要更改您想要存儲的信息的數目,需更改max_error_count值。在下面的例子中,ALTER TABLE語句會產生三個警告消息,但是隻有一個被存儲,因爲max_error_count被設置爲1

mysql> SHOW VARIABLES LIKE 'max_error_count';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_error_count | 64    |
+-----------------+-------+
1 row in set (0.00 sec)
 
mysql> SET max_error_count=1;
Query OK, 0 rows affected (0.00 sec)
 
mysql> ALTER TABLE t1 MODIFY b CHAR;
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 3
 
mysql> SELECT @@warning_count;
+-----------------+
| @@warning_count |
+-----------------+
|               3 |
+-----------------+
1 row in set (0.01 sec)
 
mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1263 | Data truncated for column 'b' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)

要禁用警告,需把max_error_count設置爲0。在此情況下,warning_count仍然指示有多少警告已經發生,但是這些消息不被存儲。

您可以把SQL_NOTES會話變量設置爲0,使“注意”級別的警告不被記錄。

13.5.5. 其它管理語句

13.5.5.1. CACHE INDEX語法

CACHE INDEX
  tbl_index_list [, tbl_index_list] ...
  IN key_cache_name
 
tbl_index_list:
  tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]

CACHE INDEX語句把表索引分配給某個關鍵緩存。該語句只用於MyISAM表。

下列語句把索引從表t1, t2t3分配到名爲hot_cache的關鍵緩存:

mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table   | Op                 | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status   | OK       |
| test.t2 | assign_to_keycache | status   | OK       |
| test.t3 | assign_to_keycache | status   | OK       |
+---------+--------------------+----------+----------+

CACHE INDEX語法允許您指定,只有來自表的特定索引應被分配給緩存。但是,當前的實施會把所有的表索引分配給緩存,所以必須指定表名稱,不能指定其它的。

被引用到CACHE INDEX語句中的關鍵緩存可以這樣創建,即通過使用一個參數設置語句或在服務器參數設置中設置其大小。舉例說明:

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;

關鍵緩存參數可以被作爲一個結構化系統變量的成分進行訪問。請參見9.4.1節,“結構式系統變量”

在您可以把索引分配給一個關鍵緩存以前,緩存必須存在:

mysql> CACHE INDEX t1 IN non_existent_cache;
ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'

默認情況下,表索引被分配給在服務器啓動時被創建的主(默認)鍵緩存。當一個鍵高速緩衝被破壞時,所有被分配到此緩存中的索引會再次被分配給默認的 鍵高速緩衝。

索引的分配會對服務器產生全局性影響:如果一個客戶端把一個索引分配給一個給定的緩存,則不論什麼客戶端發佈查詢,本緩存都被用於所有涉及索引的查詢。

13.5.5.2. FLUSH語法

FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ...

如果您想要清除MySQL使用的部分內部緩存,您應該使用FLUSH語句。要執行FLUSH,您必須擁有RELOAD權限。

flush_option可以爲以下的任何一個:

·         HOSTS

用於清空主機緩存表。如果有的主機更改了IP號或如果您得到了錯誤信息Host host_name is blocked,則您應該刷新主機表。當在連接到MySQL服務器時,如果對於一個給定的主機,接連出現錯誤“多於max_connect_errors”,此時,MySQL會假定出現了錯誤,並阻止主機後續的連接申請。刷新主機表允許主機嘗試再次連接。請參見A.2.5節,“主機的host_name被屏蔽。您可以使用max_connect_errors=999999999啓動mysqld,以避免此錯誤信息。

·         DES_KEY_FILE

用於在服務器啓動時,從採用--des-key-file選項指定的文件重新載入DES關鍵字。

·         LOGS

用於關閉並重新打開所有的日誌文件。如果您已經指定了一個更新日誌文件或一個二進制日誌文件,同時沒有擴展,則相對於前一個文件,日誌文件的擴展號增加1。如果您在文件名稱中使用了一個擴展,則MySQL會關閉並重新打開日誌文件。在Unix中,當相mysqld服務器發送一個SIGHUP信號時,也會如此(例外情況是部分Mac OS X 10.3版本。在這些版本中,mysqld忽略SIGHUPSIGQUIT)。

如果服務器使用--log-error選項,則FLUSH LOGS會導致錯誤日誌被重命名(使用後綴-old),同時mysqld會創建一個新的空日誌文件。如果沒有給定--log-error選項,則不會進行重命名。

·         PRIVILEGES

用於從mysql數據庫中的授權表重新載入權限。

·         QUERY CACHE

對查詢緩存進行整理碎片,以更好得利用存儲器。與RESET QUERY CACHE不同,本語句不會從緩存中取消任何查詢。

·         STATUS

用於把多數狀態變量重新設置爲零。只在當調試查詢時,您才應該使用此項。請參見1.7.1.3節,“如何通報缺陷和問題”

·         {TABLE | TABLES} [tbl_name [, tbl_name] ...]

當沒有表被命名時,關閉所有打開的表,並迫使所有正在使用的表關閉。這也會刷新查詢緩存。此項含有一個或多個表名稱,只刷新給定的表。和RESET QUERY CACHE語句一樣,FLUSH TABLES還會取消來自查詢緩存的所有查詢結果。

·         TABLES WITH READ LOCK

對於所有帶讀取鎖定的數據庫,關閉所有打開的表,並鎖定所有的表,直到您執行UNLOCK TABLES爲止。如果您擁有一個可以及時進行快照的文件系統,比如Veritas,則這是進行備份的非常方便的方法。

·         USER_RESOURCES

用於把所有每小時用戶資源重新設置爲零。這可以使已經達到了每小時連接、查詢或更新限值的客戶端立刻重新恢復活性。FLUSH USER_RESOURCES不適用於同時連接的最大限值。請參見13.5.1.3節,“GRANT和REVOKE語法”

FLUSH語句被寫入二進制日誌,除非使用了自選的NO_WRITE_TO_BINLOG關鍵字(或其別名LOCAL)。 註釋:在任何情況下,FLUSH LOGS, FLUSH MASTER, FLUSH SLAVEFLUSH TABLES WITH READ LOCK都不會被記入日誌,因爲如果它們被複制到一個從屬服務器上,會導致出現問題。

您也可以使用flush-hosts, flush-logs, flush-privileges, flush-statusflush-tables命令訪問含有mysqladmin應用程序的語句。

註釋:在MySQL 5.1.2-alpha中,不可能在已存儲的函數或觸發程序中發佈FLUSH語句。不過,您可以在已存儲的過程中使用FLUSH,只要它們不會從已存儲的函數或觸發程序中被調用。請參見I.1節,“對存儲子程序和觸發程序的限制”

要了解有關RESET語句與複製同時使用的信息,也可以見13.5.5.5節,“RESET語法”

13.5.5.3. KILL語法

KILL [CONNECTION | QUERY] thread_id

每個與mysqld的連接都在一個獨立的線程裏運行,您可以使用SHOW PROCESSLIST語句查看哪些線程正在運行,並使用KILL thread_id語句終止一個線程。

KILL允許自選的CONNECTIONQUERY修改符:

·         KILL CONNECTION與不含修改符的KILL一樣:它會終止與給定的thread_id有關的連接。

·         KILL QUERY會終止連接當前正在執行的語句,但是會保持連接的原狀。

如果您擁有PROCESS權限,則您可以查看所有線程。如果您擁有SUPER權限,您可以終止所有線程和語句。否則,您只能查看和終止您自己的線程和語句。

您也可以使用mysqladmin processlistmysqladmin kill命令來檢查和終止線程。

註釋:您不能同時使用KILLEmbedded MySQL Server庫,因爲內植的服務器只運行主機應用程序的線程。它不能創建任何自身的連接線程。

當您進行一個KILL時,對線程設置一個特有的終止標記。在多數情況下,線程終止可能要花一些時間,這是因爲終止標記只會在在特定的間隔被檢查:

·         SELECT, ORDER BYGROUP BY循環中,在讀取一組行後檢查標記。如果設置了終止標記,則該語句被放棄。

·         ALTER TABLE過程中,在每組行從原來的表中被讀取前,檢查終止標記。如果設置了終止標記,則語句被放棄,臨時表被刪除。

·         UPDATEDELETE運行期間,在每個組讀取之後以及每個已更行或已刪除的行之後,檢查終止標記。如果終止標記被設置,則該語句被放棄。注意,如果您正在使用事務,則變更不會被 回滾。

·         GET_LOCK()會放棄和返回NULL

·         INSERT DELAYED線程會快速地刷新(插入)它在存儲器中的所有的行,然後終止。

·         如果線程在表鎖定管理程序中(狀態:鎖定),則表鎖定被快速地放棄。

·         如果在寫入調用中,線程正在等待空閒的磁盤空間,則寫入被放棄,並伴隨"disk full"錯誤消息。

·         警告:對MyISAM表終止一個REPAIR TABLEOPTIMIZE TABLE操作會導致出現一個被損壞的沒有用的表。對這樣的表的任何讀取或寫入都會失敗,直到您再次優化或修復它(不中斷)。

13.5.5.4. LOAD INDEX INTO CACHE語法

LOAD INDEX INTO CACHE
  tbl_index_list [, tbl_index_list] ...
 
tbl_index_list:
  tbl_name
    [[INDEX|KEY] (index_name[, index_name] ...)]
    [IGNORE LEAVES]

LOAD INDEX INTO CACHE語句會把一個表索引預載入到某個關鍵緩存中。它已經被一個明確的CACHE INDEX語句分配到此關鍵緩存中。或者,表索引被預載入到默認的關鍵緩存中。LOAD INDEX INTO CACHE只用於MyISAM表。

IGNORE LEAVES修改符只會導致索引的非葉子節點被預載入。

對於表t1t2,以下語句會預載入索引的節點(索引組):

mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table   | Op           | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status   | OK       |
| test.t2 | preload_keys | status   | OK       |
+---------+--------------+----------+----------+

本語句會預載入所有來自t1的索引組。它只預載入來自t2的非葉子節點的組。

LOAD INDEX INTO CACHE語法允許您指定,只有來自表的特定的索引應被預載入。但是,當前實施會把所有的表索引預載入緩存中,所以一定要指定表名稱,不能指定其它的。

13.5.5.5. RESET語法

RESET reset_option [, reset_option] ...

RESET語句被用於清除不同的服務器操作的狀態。它也作爲FLUSH語句的更強大的版本。請參見13.5.5.2節,“FLUSH語法”

爲了執行RESET,您必須擁有RELOAD權限。

reset_option可以爲以下的任何一項:

·         MASTER

可以刪除列於索引文件中的所有二進制日誌,把二進制日誌索引文件重新設置爲空,並創建一個新的二進制日誌文件。(在以前版本的MySQL中,被稱爲FLUSH MASTER。)見13.6.1節,“用於控制主服務器的SQL語句”

·         QUERY CACHE

從查詢緩存中取消所有的查詢結果。

·         SLAVE

可以使從屬服務器忘記其在主服務器二進制日誌中的複製位置,另外,也可以通過刪除原有的中繼日誌文件和開始一個新文件來重新設置中繼日誌。請參見13.6.2節,“用於控制從服務器的SQL語句”

13.6. 複製語句

本節敘述了與複製有關的SQL語句。一組語句被用於控制主服務器。其它的被用於控制從屬服務器。

13.6.1. 用於控制主服務器的SQL語句

可以通過SQL界面控制複製。本節討論了用於管理主複製服務器的語句。13.6.2節,“用於控制從服務器的SQL語句”討論了用於管理從屬服務器的語句。

13.6.1.1. PURGE MASTER LOGS語法

PURGE {MASTER | BINARY} LOGS TO 'log_name'
PURGE {MASTER | BINARY} LOGS BEFORE 'date'

用於刪除列於在指定的日誌或日期之前的日誌索引中的所有二進制日誌。這些日誌也會從記錄在日誌索引文件中的清單中被刪除,這樣被給定的日誌成爲第一個。

例如:

PURGE MASTER LOGS TO 'mysql-bin.010';
PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';

BEFORE變量的date自變量可以爲'YYYY-MM-DD hh:mm:ss'格式。MASTERBINARY是同義詞。

如果您有一個活性的從屬服務器,該服務器當前正在讀取您正在試圖刪除的日誌之一,則本語句不會起作用,而是會失敗,並伴隨一個錯誤。不過,如果從屬服務器是休止的,並且您碰巧清理了其想要讀取的日誌之一,則從屬服務器啓動後不能複製。當從屬服務器正在複製時,本語句可以安全運行。您不需要停止它們。

要清理日誌,需按照以下步驟:

1.    在每個從屬服務器上,使用SHOW SLAVE STATUS來檢查它正在讀取哪個日誌。

2.    使用SHOW MASTER LOGS獲得主服務器上的一系列日誌。

3.    在所有的從屬服務器中判定最早的日誌。這個是目標日誌。如果所有的從屬服務器是更新的,這是清單上的最後一個日誌。

4.    製作您將要刪除的所有日誌的備份。(這個步驟是自選的,但是建議採用。)

5.    清理所有的日誌,但是不包括目標日誌。

13.6.1.2. RESET MASTER語法

RESET MASTER

可以刪除列於索引文件中的所有二進制日誌,把二進制日誌索引文件重新設置爲空,並創建一個新的二進制日誌文件。

13.6.1.3. SET SQL_LOG_BIN語法

SET SQL_LOG_BIN = {0|1}

如果客戶端使用一個有SUPER權限的賬戶連接,則可以禁用或啓用當前連接的二進制日誌記錄。如果客戶端沒有此權限,則語句被拒絕,並伴隨有錯誤。

13.6.1.4. SHOW BINLOG EVENTS語法

SHOW BINLOG EVENTS
   [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]

用於在二進制日誌中顯示事件。如果您不指定'log_name',則顯示第一個二進制日誌。

LIMIT子句和SELECT語句具有相同的語法。請參見13.2.7節,“SELECT語法”

註釋:當服務器把二進制日誌的完整內容(該日誌包括多數的由MySQL執行的查詢)轉儲到stdout時,發佈一個不含LIMIT子句的SHOW BINLOG EVENTS可以啓動一個過程,該過程非常消耗時間並消耗資源。要把二進制日誌保存到一個文本文件中,用於以後的檢查和分析,需使用mysqlbinlog應用程序。請參見8.6節,“mysqlbinlog:用於處理二進制日誌文件的實用工具”

13.6.1.5. SHOW MASTER LOGS語法

SHOW MASTER LOGS
SHOW BINARY LOGS

用於列出服務器中的二進制日誌文件。本語句被用作13.6.1.1節,“PURGE MASTER LOGS語法”中所述的過程的一部分,用於確定哪些日誌可以被清理。

mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name      | File_size |
+---------------+-----------+
| binlog.000015 |    724935 |
| binlog.000016 |    733481 |
+---------------+-----------+

SHOW BINARY LOGSSHOW MASTER LOGS相當。

13.6.1.6. SHOW MASTER STATUS語法

SHOW MASTER STATUS

用於提供主服務器二進制日誌文件的狀態信息。例如:

mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73       | test         | manual,mysql     |
+---------------+----------+--------------+------------------+

13.6.1.7. SHOW SLAVE HOSTS語法

SHOW SLAVE HOSTS

用於顯示當前使用主服務器註冊的複製從屬服務器的清單。不以--report-host=slave_name選項爲開頭的從屬服務器不會顯示在本清單中。

13.6.2. 用於控制從服務器的SQL語句

複製操作可以通過SQL界面控制。本節討論了用於管理從屬複製服務器的語句。13.6.1節,“用於控制主服務器的SQL語句”討論了用於管理主服務器的語句。

13.6.2.1. CHANGE MASTER TO語法

  CHANGE MASTER TO master_def [, master_def] ...
 
master_def:
      MASTER_HOST = 'host_name'
    | MASTER_USER = 'user_name'
    | MASTER_PASSWORD = 'password'
    | MASTER_PORT = port_num
    | MASTER_CONNECT_RETRY = count
    | MASTER_LOG_FILE = 'master_log_name'
    | MASTER_LOG_POS = master_log_pos
    | RELAY_LOG_FILE = 'relay_log_name'
    | RELAY_LOG_POS = relay_log_pos
    | MASTER_SSL = {0|1}
    | MASTER_SSL_CA = 'ca_file_name'
    | MASTER_SSL_CAPATH = 'ca_directory_name'
    | MASTER_SSL_CERT = 'cert_file_name'
    | MASTER_SSL_KEY = 'key_file_name'
    | MASTER_SSL_CIPHER = 'cipher_list'

可以更改從屬服務器用於與主服務器進行連接和通訊的參數。

MASTER_USER, MASTER_PASSWORD, MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEYMASTER_SSL_CIPHER用於向從屬服務器提供有關如何與主服務器連接的信息。

即使對於在編譯時沒有SSL支持的從屬服務器,SSL選項(MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEYMASTER_SSL_CIPHER)也可以被更改。它們被保存到master.info文件中,但是會被忽略,直到您使用一個SSL支持已啓用的服務器。

如果您不指定一個給定的參數,則它會保持其原有的值。例外情況在後面的討論中進行了說明。舉例說明,如果用於連接到您的MySQL主服務器的 密碼被更改了,您只需發佈這些語句,就可以告知從屬服務器新的密碼:

mysql> STOP SLAVE; -- if replication was running
mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret';
mysql> START SLAVE; -- if you want to restart replication

沒有必要指定沒有改變的參數(主機、接口、用戶等)。

MASTER_HOSTMASTER_PORT是主服務器主機和其TCP/IP接口的主機名(或IP地址)。注意,如果MASTER_HOSTlocalhost相等,那麼,和MySQL的其它部分一樣,接口可以被忽略(例如,如果可以使用Unix插槽文件)。

如果您指定了MASTER_HOSTMASTER_PORT,則從屬服務器會假定主服務器與以前不一樣(即使您指定的主機或接口值與當前值是一樣的。)在此情況下,主服務器二進制日誌的名稱和位置的原有值不再適用,因此,如果您不指定語句中的MASTER_LOG_FILEMASTER_LOG_POSMASTER_LOG_FILE=''MASTER_LOG_POS=4會被靜默地添加。

MASTER_LOG_FILEMASTER_LOG_POS座標點,從屬服務器I/O線程在啓動之後從主服務器讀取。如果您只指定了其中一個,則從屬服務器不能指定RELAY_LOG_FILERELAY_LOG_POS。如果MSATER_LOG_FILEMASTER_LOG_POS都沒有被指定,則從屬服務器會使用在CHANGE MASTER被髮布前的最後一個slave SQL thread座標。當您只想改變要使用的 密碼時,這可以確保複製的連續性。即使從屬服務器SQL線程落後於從屬服務器I/O線程,也可以確保複製的連續性。

CHANGE MASTER會刪除所有的中繼日誌文件並啓動一個新的日誌,除非您指定了RELAY_LOG_FILERELAY_LOG_POS。在此情況下,中繼日誌被保持;relay_log_purge全局變量被靜默地設置爲0

CHANGE MASTER TO可以更新master.inforelay-log.info文件的內容。

當您擁有主服務器快照並擁有日誌和對應的偏移量時,CHANGE MASTER對於設置從屬服務器是有用的。在把快照載入從屬服務器之後,您可以在從屬服務器上運行CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master', MASTER_LOG_POS=log_offset_on_master

舉例說明:

mysql> CHANGE MASTER TO
    ->     MASTER_HOST='master2.mycompany.com',
    ->     MASTER_USER='replication',
    ->     MASTER_PASSWORD='bigs3cret',
    ->     MASTER_PORT=3306,
    ->     MASTER_LOG_FILE='master2-bin.001',
    ->     MASTER_LOG_POS=4,
    ->     MASTER_CONNECT_RETRY=10;
 
mysql> CHANGE MASTER TO
    ->     RELAY_LOG_FILE='slave-relay-bin.006',
    ->     RELAY_LOG_POS=4025;

第一個例子可以更改主服務器及其二進制日誌座標。當想要設置從屬服務器來複制主服務器時使用。

第二個例子顯示了較少被使用的一個操作。當從屬服務器含有中繼日誌,並且您出於某種原因想要執行此日誌時使用。要這麼做時,不需要連接主服務器。您只需要使用CHANGE MASTER TO並啓動SQL線程(START SLAVE SQL_THREAD)。

您甚至可以在一個用於獨立非從屬服務器的非複製型設置中使用第二種操作,在崩潰之後進行復原。假設您的服務器已崩潰,同時您已恢復了備份。您想要重新播放服務器自己的二進制日誌(不是中繼日誌,而是正規的二進制文件),例如名爲myhost-bin.*。首先,應在安全的地方製作這些二進制日誌的備份,以防您沒有完全遵守以下步驟,意外地讓服務器清理了二進制文件。使用SET GLOBAL relay_log_purge=0,進一步增加安全性。然後啓動不含--log-bin選項的服務器。使用--replicate-same-server-id, --relay-log=myhost-bin(讓服務器相信,這些正規的二進制日誌是中繼日誌)和--skip-slave-start options選項。當服務器啓動後,發佈以下語句:

mysql> CHANGE MASTER TO
    ->     RELAY_LOG_FILE='myhost-bin.153',
    ->     RELAY_LOG_POS=410,
    ->     MASTER_HOST='some_dummy_string';
mysql> START SLAVE SQL_THREAD;

服務器會讀取並執行自己的二進制日誌,完成崩潰復原。當復原完成後,運行STOP SLAVE,關閉服務器,刪除master.inforelay-log.info,並使用原來的選項重新啓動服務器。

要讓服務器認爲它是一個從屬服務器,需要指定MASTER_HOST(甚至使用假值)。

13.6.2.2. LOAD DATA FROM MASTER語法

LOAD DATA FROM MASTER

本命令用於對主服務器進行快照,並拷貝到從屬服務器上。它可以更新MASTER_LOG_FILEMASTER_LOG_POS的值,這樣,從屬服務器就可以從正確的位置開始進行復制。使用--replicate-*-do-*--replicate-*-ignore-*選項指定的表和數據庫排除規則均被兌現。--replicate-rewrite-db沒有被考慮。這是因爲使用本選項,用戶就可以設置一個例如--replicate-rewrite-db=db1->db3--replicate-rewrite-db=db2->db3的非唯一映射。當從主服務器載入表時,該映射會使從屬服務器發生混淆。

本語句的使用受以下條件的制約:

·         只對MyISAM表起作用。如果試圖載入一個非MyISAM表,會導致以下錯誤:

·                ERROR 1189 (08S01): Net error reading from master

·         當拍攝快照時,會獲得對主服務器的全局讀取鎖定。在載入操作期間,該鎖定會阻止對主服務器的更新。

如果您正在載入大表,您可能必須對主服務器和從屬服務器均增加net_read_timeoutnet_write_timeout值。請參見5.3.3節,“服務器系統變量”

注意,LOAD DATA FROM MASTER不從mysql數據庫拷貝任何表。這可以更容易地讓主服務器和從屬服務器擁有不同的用戶和權限。

LOAD DATA FROM MASTER語句要求用於連接主服務器的複製帳戶,以便讓主服務器擁有RELOADSUPER權限,並讓所有您想要載入的主服務器表擁有SELECT權限。所有的用戶不擁有SELECT權限的主服務器表均被LOAD DATA FROM MASTER忽略。這是因爲主服務器會對用戶隱藏它們:LOAD DATA FROM MASTER會調用SHOW DATABASES以瞭解要載入的主服務器數據庫,但是SHOW DATABASES只會返回用戶有部分權限的數據庫。請參見13.5.4.6節,“SHOW DATABASES語法”。在從屬服務器方面,發佈LOAD DATA FROM MASTER的用戶應擁有授權,以取消或創建被複制的數據庫和表。

13.6.2.3. LOAD TABLE tbl_name FROM MASTER語法

LOAD TABLE tbl_name FROM MASTER

用於把表的拷貝從主服務器轉移到從屬服務器。本語句的主要作用是調試LOAD DATA FROM MASTER。它要求用於連接主服務器的帳戶擁有對主服務器的RELOADSUPER權限,並擁有對要載入的主服務器表的SELECT權限。在從屬服務器方面,發佈LOAD TABLE FROM MASTER的用戶應擁有取消和創建表的權限。

用於LOAD DATA FROM MASTER的條件也適用於這裏。舉例說明,LOAD TABLE FROM MASTER僅對於MyISAM表起作用。對LOAD DATA FROM MASTER的暫停注意也適用。

13.6.2.4. MASTER_POS_WAIT()語法

SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)
這實際上是一個函數,而不是一個語句。它被用於確認,從屬服務器已讀取並執行了到達主服務器二進制日誌的給定位置。要了解完整的描述,請參見12.9.4節,“其他函數”

13.6.2.5. RESET SLAVE語法

RESET SLAVE

用於讓從屬服務器忘記其在主服務器的二進制日誌中的複製位置。本語句被用於進行一個明確的啓動:它會刪除master.inforelay-log.info文件,以及所有的中繼日誌,並啓動一個新的中繼日誌。

註釋:所有的中繼日誌被刪除,即使它們沒有被從屬服務器SQL線程完全的執行。(如果您已經發布了一個SLAVE語句或如果從屬服務器的載入量很大,則這對於一個複製從屬服務器是一個很可能出現的情況。)

存儲在master.info文件中的連接信息通過使用在對應的啓動選項中指定的值,被立即重新設置了。此信息包括主服務器主機、主服務器接口、主服務器用戶和主服務器 密碼等值。當從屬服務器SQL線程被中止時,它位於正在複製的臨時表的中間,並且發佈了RESET SLAVE,則已被複制的臨時表在從屬服務器中被刪除。

13.6.2.6. SET GLOBAL SQL_SLAVE_SKIP_COUNTER語法

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n

從主服務器中跳過後面的n個事件。要復原由語句導致的複製中止,這是有用的。

僅當從屬線程沒有正在運行時,本語句時有效的。否則,會產生一個錯誤。

13.6.2.7. SHOW SLAVE STATUS語法

SHOW SLAVE STATUS

用於提供有關從屬服務器線程的關鍵參數的信息。如果您使用mysql客戶端發佈此語句,則您可以使用一個\G語句終止符來獲得更便於閱讀的豎向版面,而不是使用分號:

mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
       Slave_IO_State: Waiting for master to send event
          Master_Host: localhost
          Master_User: root
          Master_Port: 3306
        Connect_Retry: 3
      Master_Log_File: gbichot-bin.005
  Read_Master_Log_Pos: 79
       Relay_Log_File: gbichot-relay-bin.005
        Relay_Log_Pos: 548
Relay_Master_Log_File: gbichot-bin.005
     Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
      Replicate_Do_DB:
  Replicate_Ignore_DB:
           Last_Errno: 0
           Last_Error:
         Skip_Counter: 0
  Exec_Master_Log_Pos: 79
      Relay_Log_Space: 552
      Until_Condition: None
       Until_Log_File:
        Until_Log_Pos: 0
   Master_SSL_Allowed: No
   Master_SSL_CA_File:
   Master_SSL_CA_Path:
      Master_SSL_Cert:
    Master_SSL_Cipher:
       Master_SSL_Key:
Seconds_Behind_Master: 8

SHOW SLAVE STATUS會返回以下字段:

·         Slave_IO_State

SHOW PROCESSLIST輸出的State字段的拷貝。SHOW PROCESSLIST用於從屬I/O線程。如果線程正在試圖連接到主服務器,正在等待來自主服務器的時間或正在連接到主服務器等,本語句會通知您。在6.3節,“複製實施細節”中列出了可能的狀態。舊版本的MySQL在連接主服務器不成功時,允許線程繼續運行。對於舊版本的MySQL,觀看此字段是必須的。如果它正在運行,則無問題;如果它沒有運行,則您會在Last_Error字段中發現錯誤(後面有說明)。

·         Master_Host

當前的主服務器主機。

·         Master_User

被用於連接主服務器的當前用戶。

·         Master_Port

當前的主服務器接口。

·         Connect_Retry

--master-connect-retry選項的當前值

·         Master_Log_File

I/O線程當前正在讀取的主服務器二進制日誌文件的名稱。

·         Read_Master_Log_Pos

在當前的主服務器二進制日誌中,I/O線程已經讀取的位置。

·         Relay_Log_File

SQL線程當前正在讀取和執行的中繼日誌文件的名稱。

·         Relay_Log_Pos

在當前的中繼日誌中,SQL線程已讀取和執行的位置。

·         Relay_Master_Log_File

SQL線程執行的包含多數近期事件的主服務器二進制日誌文件的名稱。

·         Slave_IO_Running

I/O線程是否被啓動併成功地連接到主服務器上。對於舊版本的MySQL(在4.1.145.0.12之前),如果I/O線程已被啓動,即使從屬服務器仍沒有連接到主服務器上,Slave_IO_Running也將被設置到YES

·         Slave_SQL_Running

SQL線程是否被啓動。

·         Replicate_Do_DB, Replicate_Ignore_DB

使用--replicate-do-db--replicate-ignore-db選項指定的數據庫清單。

·         Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table

使用--replicate-do-table, --replicate-ignore-table, --replicate-wild-do-table--replicate-wild-ignore_table選項指定的表清單。

·         Last_Errno, Last_Error

被多數最近被執行的查詢返回的錯誤數量和錯誤消息。錯誤數量爲0並且消息爲空字符串意味着“沒有錯誤”。如果Last_Error值不是空值,它也會在從屬服務器的錯誤日誌中作爲消息顯示。

舉例說明:

Last_Errno: 1051
Last_Error: error 'Unknown table 'z'' on query 'drop table z'

該消息指示,表z曾經存在於在主服務器中並已被取消了,但是它沒有在從屬服務器中存在過,因此對於從屬服務器,DROP TABLE失敗。(舉例說明,在設置複製時,如果您忘記了把此表拷貝到從屬服務器中,則這有可能發生。)

·         Skip_Counter

最近被使用的用於SQL_SLAVE_SKIP_COUNTER的值。

·         Exec_Master_Log_Pos

來自主服務器的二進制日誌的由SQL線程執行的上一個時間的位置(Relay_Master_Log_File)。在主服務器的二進制日誌中的(Relay_Master_Log_File, Exec_Master_Log_Pos)對應於在中繼日誌中的(Relay_Log_File, Relay_Log_Pos)

·         Relay_Log_Space

所有原有的中繼日誌結合起來的總大小。

·         Until_Condition, Until_Log_File, Until_Log_Pos

START SLAVE語句的UNTIL子句中指定的值。

Until_Condition具有以下值:

o        如果沒有指定UNTIL子句,則沒有值

o        如果從屬服務器正在讀取,直到達到主服務器的二進制日誌的給定位置爲止,則值爲Master

o        如果從屬服務器正在讀取,直到達到其中繼日誌的給定位置爲止,則值爲Relay

Until_Log_FileUntil_Log_Pos用於指示日誌文件名和位置值。日誌文件名和位置值定義了SQL線程在哪個點中止執行。

·         Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key

這些字段顯示了被從屬服務器使用的參數。這些參數用於連接主服務器。

Master_SSL_Allowed具有以下值:

o        如果允許對主服務器進行SSL連接,則值爲Yes

o        如果不允許對主服務器進行SSL連接,則值爲No

o        如果允許SSL連接,但是從屬服務器沒有讓SSL支持被啓用,則值爲Ignored

SSL有關的字段的值對應於--master-ca, --master-capath, --master-cert, --master-cipher--master-key選項的值。

·         Seconds_Behind_Master

本字段是從屬服務器“落後”多少的一個指示。當從屬SQL線程正在運行時(處理更新),本字段爲在主服務器上由此線程執行的最近的一個事件的時間標記開始,已經過的秒數。當此線程被從屬服務器I/O線程趕上,並進入閒置狀態,等待來自I/O線程的更多的事件時,本字段爲零。總之,本字段測量從屬服務器SQL線程和從屬服務器I/O線程之間的時間差距,單位以秒計。

如果主服務器和從屬服務器之間的網絡連接較快,則從屬服務器I/O線程會非常接近主服務器,所以本字段能夠十分近似地指示,從屬服務器SQL線程比主服務器落後多少。如果網絡較慢,則這種指示不準確;從屬SQL線程經常會趕上讀取速度較慢地從屬服務器I/O線程,因此,Seconds_Behind_Master經常顯示值爲0。即使I/O線程落後於主服務器時,也是如此。換句話說,本列只對速度快的網絡有用。

即使主服務器和從屬服務器不具有相同的時鐘,時間差計算也會起作用(當從屬服務器I/O線程啓動時,計算時間差。並假定從此時以後,時間差保持不變)。如果從屬SQL線程不運行,或者如果從屬服務器I/O線程不運行或未與主服務器連接,則Seconds_Behind_MasterNULL(意義爲“未知”)。舉例說明,如果在重新連接之前,從屬服務器I/O線程休眠了master-connect-retry秒,則顯示NULL,因爲從屬服務器不知道主服務器正在做什麼,也不能有把握地說落後多少。

本字段有一個限制。時間標記通過複製被保留,這意味着,如果一個主服務器M1本身是一個從屬服務器M0,則來自M1binlog的任何事件(通過複製來自M0binlog的事件而產生),與原事件具有相同的時間標記。這可以使MySQL成功地複製TIMESTAMP。但是,Seconds_Behind_Master的缺點是,如果M1也收到來自客戶端的直接更新,則值會隨機變化,因爲有時最近的M1時間來自M0,有時來自直接更新,最近的時間標記也是如此。

13.6.2.8. START SLAVE語法

START SLAVE [thread_type [, thread_type] ... ]
START SLAVE [SQL_THREAD] UNTIL
    MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
START SLAVE [SQL_THREAD] UNTIL
    RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos
 
thread_type: IO_THREAD | SQL_THREAD

不含選項的START SLAVE會同時啓動兩個從屬服務器線程。I/O線程從主服務器中讀取查詢,並把它們存儲在中繼日誌中。SQL線程讀取中繼日誌並執行查詢。START SLAVE要求SUPER權限。

如果START SLAVE成功地啓動了從屬服務器線程,則會返回,不會出現錯誤。但是,即使在此情況下,也有可能出現這樣的現象——服務器線程啓動了,然後又停止了(例如,因爲它們沒有成功地連接到主服務器上,或者沒有能讀取二進制日誌,或者出現了其它問題)。START SLAVE對此不會發出警告。您必須檢查從屬服務器的錯誤日誌,查看是否有由從屬服務器線程產生的錯誤消息,或者使用SHOW SLAVE STATUS檢查它們是否運行正常。

您可以把IO_THREADSQL_THREAD選項添加到語句中,指明哪些線程將要啓動。

可以添加一個UNTIL子句,指定從屬服務器應啓動並運行,直到SQL線程達到主服務器二進制日誌中的一個給定點爲止。當SQL線程達到此點時,它會停止。如果在該語句中指定了SQL_THREAD選項,則它只會啓動SQL線程。否則,它會同時啓動兩個從屬服務器線程。如果SQL線程正在運行,則UNTIL子句被忽略,併發佈一個警告。

對於一個UNTIL子句,您必須同時指定一個日誌文件名和位置。不要把主服務器和中繼日誌選項混合在一起。

UNTIL條件由一個後續的STOP SLAVE語句,或一個不包括UNTIL子句的START SLAVE語句,或一個服務器重啓命令重新設置。

UNTIL子句對於調試複製操作是有用的,或者可用於促使複製操作繼續,直到接近一個特定的點時爲止,在此點,您想要避免讓從屬服務器複製一個語句。舉例說明,如果在主服務上執行了一個不明智的DROP TABLE語句,您可以使用UNTIL來告知從屬服務器,執行到此點就停止,不要再繼續了。要查找該事件是什麼,需對主服務器日誌或從屬中繼日誌使用mysqlbinlog,或通過使用SHOW BINLOG EVENTS語句。

如果您正在使用UNTIL,讓從屬服務器成段地處理已複製的查詢,則建議您使用--skip-slave-start選項來啓動從屬服務器,以防止當從屬服務器啓動時,SQL線程運行。最好在一個選項文件中使用此選項,而不是在命令行中使用,這樣,如果發生了意料外的服務器重新啓動,它也不會被忘記。

SHOW SLAVE STATUS語句包括了輸出字段。這些字段顯示了UNTIL條件的當前值。

在以前版本的MySQL中,本語句被稱爲SLAVE START。在MySQL 5.1中仍然接受這種用法,以便與以前版本兼容。但現在不贊成使用。

13.6.2.9. STOP SLAVE語法
 

STOP SLAVE [thread_type [, thread_type] ... ]
 
thread_type: IO_THREAD | SQL_THREAD

用於中止從屬服務器線程。STOP SLAVE要求SUPER權限。

START SLAVE相似,本語句在使用時可以加IO_THREADSQL_THREAD選項,指明將被中止的線程。

在以前版本的MySQL中,本語句被稱爲SLAVE STOP。在MySQL 5.1中仍然接受這種用法,以便與以前版本兼容。但是現在不贊成使用。

13.7. 用於預處理語句的SQL語法

MySQL 5.1對服務器一方的預製語句提供支持。如果您使用合適的客戶端編程界面,則這種支持可以發揮在MySQL 4.1中實施的高效客戶端/服務器二進制協議的優勢。候選界面包括MySQL C API客戶端庫(用於C程序)、MySQL Connector/J(用於Java程序)和MySQL Connector/NET。例如,C API可以提供一套能組成預製語句API的函數調用。請參見25.2.4節,“C API預處理語句”。其它語言界面可以對使用了二進制協議(通過在C客戶端庫中鏈接)的預製語句提供支持。有一個例子是PHP 5.0中的mysqli擴展

對預製語句,還有一個SQL界面可以利用。與在整個預製語句API中使用二進制協議相比,本界面效率沒有那麼高,但是它不要求編程,因爲在SQL層級,可以直接利用本界面:

·         當您無法利用編程界面時,您可以使用本界面。

·         有些程序允許您發送SQL語句到將被執行的服務器中,比如mysql客戶端程序。您可以從這些程序中使用本界面。

·         即使客戶端正在使用舊版本的客戶端庫,您也可以使用本界面。唯一的要求是,您能夠連接到一個支持預製語句SQL語法的服務器上。

預製語句的SQL語法在以下情況下使用:

·         在編代碼前,您想要測試預製語句在您的應用程序中運行得如何。或者也許一個應用程序在執行預製語句時有問題,您想要確定問題是什麼。

·         您想要創建一個測試案例,該案例描述了您使用預製語句時出現的問題,以便您編制程序錯誤報告。

·         您需要使用預製語句,但是您無法使用支持預製語句的編程API

預製語句的SQL語法基於三個SQL語句:

PREPARE stmt_name FROM preparable_stmt;
 
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
 
{DEALLOCATE | DROP} PREPARE stmt_name;

PREPARE語句用於預備一個語句,並賦予它名稱stmt_name,藉此在以後引用該語句。語句名稱對案例不敏感。preparable_stmt可以是一個文字字符串,也可以是一個包含了語句文本的用戶變量。該文本必須展現一個單一的SQL語句,而不是多個語句。使用本語句,‘?’字符可以被用於製作參數,以指示當您執行查詢時,數據值在哪裏與查詢結合在一起。‘?’字符不應加引號,即使您想要把它們與字符串值結合在一起,也不要加引號。參數製作符只能被用於數據值應該出現的地方,不用於SQL關鍵詞和標識符等。

如果帶有此名稱的預製語句已經存在,則在新的語言被預備以前,它會被隱含地解除分配。這意味着,如果新語句包含一個錯誤並且不能被預備,則會返回一個錯誤,並且不存在帶有給定名稱語句。

預製語句的範圍是客戶端會話。在此會話內,語句被創建。其它客戶端看不到它。

在預備了一個語句後,您可使用一個EXECUTE語句(該語句引用了預製語句名稱)來執行它。如果預製語句包含任何參數製造符,則您必須提供一個列舉了用戶變量(其中包含要與參數結合的值)的USING子句。參數值只能有用戶變量提供,USING子句必須準確地指明用戶變量。用戶變量的數目與語句中的參數製造符的數量一樣多。

您可以多次執行一個給定的預製語句,在每次執行前,把不同的變量傳遞給它,或把變量設置爲不同的值。

要對一個預製語句解除分配,需使用DEALLOCATE PREPARE語句。嘗試在解除分配後執行一個預製語句會導致錯誤。

如果您終止了一個客戶端會話,同時沒有對以前已預製的語句解除分配,則服務器會自動解除分配。

以下SQL語句可以被用在預製語句中:CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多數的SHOW語句。目前不支持其它語句。

以下例子顯示了預備一個語句的兩種方法。該語句用於在給定了兩個邊的長度時,計算三角形的斜邊。

第一個例子顯示如何通過使用文字字符串來創建一個預製語句,以提供語句的文本:

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|          5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;

第二個例子是相似的,不同的是提供了語句的文本,作爲一個用戶變量:

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|         10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;

預製語句的SQL語法不能被用於帶嵌套的風格中。也就是說,被傳遞給PREPARE的語句本身不能是一個PREPARE, EXECUTEDEALLOCATE PREPARE語句。

預製語句的SQL語法與使用預製語句API調用不同。例如,您不能使用mysql_stmt_prepare() C API函數來預備一個PREPARE, EXECUTEDEALLOCATE PREPARE語句。

預製語句的SQL語法可以在已存儲的過程中使用,但是不能在已存儲的函數或觸發程序中使用。

當使用預製語句時,可以在LIMIT子句中使用佔位符。請參見13.2.7節,“SELECT語法”


這是MySQL參考手冊的翻譯版本,關於MySQL參考手冊,請訪問dev.mysql.com。 原始參考手冊爲英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章