### 第13章:SQL語句語法
本章介紹了SQL語句的語法。
### 13.1.?數據定義語句
[13.1.1. ALTER DATABASE語法](#)[13.1.2. ALTER TABLE語法](#)[13.1.3. CREATE DATABASE語法](#)[13.1.4. CREATE INDEX語法](#)[13.1.5. CREATE TABLE語法](#)[13.1.6. DROP DATABASE語法](#)[13.1.7. DROP INDEX語法](#)[13.1.8. DROP TABLE語法](#)[13.1.9. RENAME TABLE語法](#)
### 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章](#):[_字符集支持_](# "Chapter?10.?Character Set Support")中對字符集和整序名稱進行了討論。
數據庫名稱可以忽略,此時,語句對應于默認數據庫。也可以使用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_INCREMENT和AVG_ROW_LENGTH等。請見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax")。
存儲引擎不支持有些操作,如果進行這些操作,會出現警告。使用SHOW WARNINGS可以顯示出這些警告。請參見[13.5.4.22節,“SHOW WARNINGS語法”](# "13.5.4.22.?SHOW WARNINGS Syntax")。
如果您使用ALTER TABLE更改列規約,但是DESCRIBE_tbl_name_提示您列規約并沒有改變,則可能是因為MySQL忽略了您所做的更改。忽略更改的原因見[13.1.5.1節,“沉寂的列規格變更”](# "13.1.5.1.?Silent Column Specification Changes")。例如,如果您試圖把VARCHAR列更改為CHAR列,此時,如果表包含其它長度可變的列,則MySQL仍會使用VARCHAR。
ALTER TABLE運行時會對原表進行臨時復制,在副本上進行更改,然后刪除原表,再對新表進行重命名。在執行ALTER TABLE時,其它用戶可以閱讀原表,但是對表的更新和修改的操作將被延遲,直到新表生成為止。新表生成后,這些更新和修改信息會自動轉移到新表上。
注意,如果您在執行ALTER TABLE時使用除了RENAME以外的選項,則MySQL會創建一個臨時表。即使數據并不需要進行復制(例如當您更改列的名稱時),MySQL也會這么操作。對于MyISAM表,您可以通過把myisam_sort_buffer_size系統變量設置到一個較高的值,來加快重新創建索引(該操作是變更過程中速度最慢的一部分)的速度。
·???????? 要使用ALTER TABLE,您需要獲得表的ALTER, INSERT和CREATE權限。
·???????? IGNORE是MySQL相對于標準SQL的擴展。如果在新表中有重復關鍵字,或者當STRICT模式啟動后出現警告,則使用IGNORE控制ALTER TABLE的運行。如果沒有指定IGNORE,當重復關鍵字錯誤發生時,復制操作被放棄,返回前一步驟。如果指定了IGNORE,則對于有重復關鍵字的行,只使用第一行,其它有沖突的行被刪除。并且,對錯誤值進行修正,使之盡量接近正確值。
·???????? 您可以在一個ALTER TABLE語句里寫入多個ADD, ALTER, DROP和CHANGE子句,中間用逗號分開。這是MySQL相對于標準SQL的擴展。在標準SQL中,每個ALTER TABLE語句中每個子句只允許使用一次。例如,在一個語句中取消多個列:
·??????????????? mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
·???????? CHANGE _col_name_, DROP _col_name_和DROP INDEX是MySQL相對于標準SQL的擴展。
·???????? MODIFY是Oracle對ALTER TABLE的擴展。
·???????? COLUMN只是自選項目,可以忽略。
·???????? 如果您使用ALTER TABLE _tbl_name_ RENAME TO _new_tbl_name_并且沒有其它選項,則MySQL只對與table _tbl_name_相對應的文件進行重命名。不需要創建一個臨時表。(您也可以使用RENAME TABLE語句對表進行重命名。請參見[13.1.9節,“RENAME TABLE語法”](# "13.1.9.?RENAME TABLE Syntax")。)
·???????? _ column_definition_子句使用與CREATE TABLE中的ADD和CHANGE子句相同的語法。注意,此語法包括列名稱,而不只是列類型。請參見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax")。
·???????? 您可以使用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;
·???????? 如果您使用CHANGE或MODITY縮短列長時,列中存在有索引,并且縮短后的列長小于索引長度,則MySQL會自動縮短索引的長度。
·???????? 當您使用CHANGE或MODIFY更改列的類型時,MySQL會盡量把原有的列值轉化為新的類型。
·???????? 您可以使用FIRST或AFTER _col_name_在一個表行中的某個特定位置添加列。默認把列添加到最后。您也可以在CHANGE或MODIFY語句中使用FIRST和AFTER。
·???????? AFTER COLUMN用于指定列的新默認值,或刪除舊的默認值。如果舊的默認值被刪除同時列值為NULL,則新的默認值為NULL。如果列值不能為NULL,MySQL會指定一個默認值,請參見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax")。
·???????? DROP INDEX用于取消索引。這是MySQL相對于標準SQL的擴展。請參見[13.1.7節,“DROP INDEX語法”](# "13.1.7.?DROP INDEX Syntax")。
·???????? 如果列從表中被取消了,則這些列也從相應的索引中被取消。如果組成一個索引的所有列均被取消,則該索引也被取消。
·???????? 如果一個表只包含一列,則此列不能被取消。如果您想要取消表,應使用DROP TABLE。
·???????? DROP PRIMAY DEY用于取消主索引。注釋:在MySQL較早的版本中,如果沒有主索引,則DROP PRIMARY KEY會取消表中的第一個UNIQUE索引。在MySQL 5.1中不會出現這種情況。如果在MySQL 5.1中對沒有主鍵的表使用DROP PRIMARY KEY,則會出現錯誤信息。
如果您向表中添加UNIQUE KEY或PRIMARY KEY,則UNIQUE KEY或PRIMARY KEY會被儲存在非唯一索引之前,這樣MySQL就可以盡早地檢查出重復關鍵字。
·???????? ORDER BY用于在創建新表時,讓各行按一定的順序排列。注意,在插入和刪除后,表不會仍保持此順序。當您知道多數情況下您會按照特定的順序查詢各行時,可以使用這個選項;在對表進行了大的改動后,通過使用此選項,您可以提高查詢效率。在有些情況下,如果表按列排序,對于MySQL來說,排序可能會更簡單。
·???????? 如果您對一個MyISAM表使用ALTER TABLE,則所有非唯一索引會被創建到一個單獨的批里(和REPAIR TABLE相同)。當您有許多索引時,這樣做可以使ALTER TABLE的速度更快。
這項功能可以明確激活。ALTER TABLE...DISABLE KEYS讓MySQL停止更新MyISAM表中的非唯一索引。然后使用ALTER TABLE ... ENABLE KEYS重新創建丟失的索引。進行此操作時,MySQL采用一種特殊的算法,比一個接一個地插入關鍵字要快很多。因此,在進行成批插入操作前先使關鍵字禁用可以大大地加快速度。使用ALTER TABLE ... DISABLE KEYS除了需要獲得以前提到的權限以外,還需要獲得INDEX權限。
·???????? Innodb存儲引擎支持FOREIGN KEY和REFERENCES子句。Innodb存儲引擎執行ADD [CONSTRAINT [_symbol_]] FOREIGN KEY (...) REFERENCES ... (...)。請參見[15.2.6.4節,“FOREIGN KEY約束”](# "15.2.6.4.?FOREIGN KEY Constraints")。對于其它存儲引擎,這些子句會被分析,但是會被忽略。對于所有的存儲引擎,CHECK子句會被分析,但是會被忽略。請參見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax")。接受這些子句但又忽略子句的原因是為了提高兼容性,以便更容易地從其它SQL服務器中導入代碼,并運行應用程序,創建帶參考數據的表。請參見[1.8.5節,“MySQL與標準SQL的差別”](# "1.8.5.?MySQL Differences from Standard SQL")。
·???????? InnoDB支持使用ALTER TABLE來取消外鍵:
·??????????????? ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;
要了解更多信息,請參見[15.2.6.4節,“FOREIGN KEY約束”](# "15.2.6.4.?FOREIGN KEY Constraints")。
·???????? ALTER TABLE忽略DATA DIRECTORY和INDEX 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 SET和ALTER TABLE...CHARACTER SET是等價的,只用于更改默認的表字符集。
·???????? 如果InnoDB表在創建時,使用了.ibd文件中的自己的表空間,則這樣的文件可以被刪除和導入。使用此語句刪除.ibd文件:
·??????????????? ALTER TABLE tbl_name DISCARD TABLESPACE;
此語句用于刪除當前的.ibd文件,所以應首先確認您有一個備份。如果在表空間被刪除后嘗試打開表格,則會出現錯誤。
要把備份的.ibd文件還原到表中,需把此文件復制到數據庫目錄中,然后書寫此語句:
ALTER TABLE tbl_name IMPORT TABLESPACE;
見[15.2.6.6節,“使用按表的表空間”](# "15.2.6.6.?Using Per-Table Tablespaces")。
·???????? 使用mysql_info() C API函數,您可以了解有多少記錄已被復制,以及(當使用IGNORE時)有多少記錄由于重復關鍵字的原因已被刪除。請參見[25.2.3.34節,“mysql_info()”](# "25.2.3.34.?mysql_info()")。
·???????? ALTER TABLE也可以用于對帶分區的表進行重新分區,功能包括添加、取消、合并和拆分各分區,還可以用于進行分區維護。
對帶分區的表使用_partition_options_子句和ALTER TABLE可以對表進行重新分區,使用時依據_partition_options_定義的分區方法。本子句以PARTITION BY為開頭,然后使用與用于CREATE TABLE的_partition_options_子句一樣的語法和規則(要了解詳細信息,請參見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax"))。注釋:MySQL 5.1服務器目前接受此語法,但是不實際執行;等MySQL 5.1開發出來后,將執行此語法。
用于ALTER TABLE ADD PARTITION的_partition_definition_子句支持用于CREATE TABLE語句的_partition_definition_子句的同樣名稱的選項。(要了解語法和介紹,請參見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax")。)例如,假設您有一個按照以下方式創建的帶分區的表:
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用于取消一個或多個RANGE或LIST分區。此命令不能用于HASH或KEY 分區;用于這兩個分區時,應使用COALESCE PARTITION(見后)。如果被取消的分區其名稱列于_partition_names_清單中,則儲存在此分區中的數據也被取消。例如,如果以前已定義的表t1,您可以采用如下方法取消名稱為p0和p1的分區:
ALTER TABLE DROP PARTITION p0, p1;
ADD PARTITION和DROP PARTITION目前不支持IF [NOT] EXISTS。也不可能對一個分區或一個已分區的表進行重命名。如果您希望對一個分區進行重命名,您必須取消分區,再重新建立;如果您希望對一個已分區的表進行重新命名,您必須取消所有分區,然后對表進行重命名,再添加被取消的分區。
COALESCE PARTITION可以用于使用HASH或KEY進行分區的表,以便使用_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個分區中(編號為0、1、2和3的分區)。
如果要更改部分分區,但不更改所有的分區,您可以使用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節,“分區管理”](# "18.3.?Partition Management")。
·???????? 多個附加子句用于提供分區維護和修補功能。這些功能與用于非分區表的功能類似。這些功能由CHECK TABLE和REPAIR TABLE等命令(這些命令不支持用于分區表)執行。這些子句包括ANALYZE PARTITION, CHECK PARTITION, OPTIMIZE PARTITION, REBUILD PARTITION和REPAIR PARTITION.每個選項均為一個_partition_names_子句,包括一個或多個分區名稱。需要更改的表中必須已存在這些分區。多個分區名稱用逗號分隔。要了解更多信息,或要了解舉例說明,請參見[18.3.3節,“分區維護”](# "18.3.3.?Maintenance of Partitions")。
以下例子展示了ALTER TABLE的使用。首先展示表t1。表t1采用如下方法創建:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
把表t1重新命名為t2:
mysql> ALTER TABLE t1 RENAME t2;
把列a從INTERGER更改為TINYINT NOT NULL(名稱保持不變),并把列b從CHAR(10)更改為CHAR(20),同時把列b重新命名為列c:
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
添加一個新的TIMESTAMP列,名稱為d:
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
在列d和列a中添加索引:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD 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列必須編制索引。同時我們定義c為NOT NULL,因為主鍵列不能為NULL。
當您添加一個AUTO_INCREMENT列時,列值被自動地按序號填入。對于MyISAM表,您可以在ALTER TABLE之前執行SET INSERT_ID=_value_來設置第一個序號,也可以使用AUTO_INCREMENT=_value_表選項來設置。請參見[13.5.3節,“SET語法”](# "13.5.3.?SET Syntax")。
如果值大于AUTO_INCREMENT列中的最大值,則您可以使用用于InnoDB表的ALTER TALBE...AUTO_INCREMENT=_value_表選項,來為新行設置序號。如果值小于列中當前的最大值,不會出現錯誤信息,當前的序列值也不改變。
使用MyISAM表時,如果您不更改AUTO_INCREMENT列,則序列號不受影響。如果您取消一個AUTO_INCREMENT列,然后添加另一個AUTO_INCREMENT列,則序號重新排列,從1開始。
見[A.7.1節,“與ALTER TABLE有關的問題”](# "A.7.1.?Problems with 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節,“數據庫、表、索引、列和別名”](# "9.2.?Database, Table, Index, Column, and Alias Names")。如果存在數據庫,并且您沒有指定IF NOT EXISTS,則會出現錯誤。
create_specification選項用于指定數據庫的特性。數據庫特性儲存在數據庫目錄中的db.opt文件中。CHARACTER SET子句用于指定默認的數據庫字符集。COLLATE子句用于指定默認的數據庫整序。字符集和整序名稱在[第10章](#):[_字符集支持_](# "Chapter?10.?Character Set Support")中討論。
有些目錄包含文件,這些文件與數據庫中的表對應。MySQL中的數據庫的執行方法與這些目錄的執行方法相同。因為當數據庫剛剛被創建時,在數據庫中沒有表,所以CREATE DATABASE只創建一個目錄。這個目錄位于MySQL數據目錄和db.opt文件之下。
如果您手動在數據目錄之下創建一個目錄(例如,使用**mkdir**),則服務器會認為這是一個數據庫目錄,并在SHOW DATABASES的輸出中顯示出來。
也可以使用CREATE SCHEMA。
您還可以使用**mysqladmin**程序創建數據庫。請參見[8.5節,“mysqladmin:用于管理MySQL服務器的客戶端”](# "8.5.?mysqladmin — Client for Administering a MySQL Server")。
### 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語法”](# "13.1.2.?ALTER TABLE Syntax")。
通常,當使用CREATE TABLE創建表時,也同時在表中創建了所有的索引。請參見[13.1.5節,“CREATE TABLE語法”](# "13.1.5.?CREATE TABLE Syntax")。CREATE INDEX允許您向已有的表中添加索引。
格式為(col1, col2,...)的一個列清單創建出一個多列索引。通過串接給定列中的值,確定索引值的格式。
對于CHAR和VARCHAR列,只用一列的一部分就可創建索引。創建索引時,使用_col_name_(_length_)語法,對前綴編制索引。前綴包括每列值的前_length_個字符。BLOB和TEXT列也可以編制索引,但是必須給出前綴長度。
此處展示的語句用于創建一個索引,索引使用列名稱的前10個字符。
CREATE INDEX part_of_name ON customer (name(10));
因為多數名稱的前10個字符通常不同,所以此索引不會比使用列的全名創建的索引速度慢很多。另外,使用列的一部分創建索引可以使索引文件大大減小,從而節省了大量的磁盤空間,有可能提高INSERT操作的速度。
前綴最長為255字節。對于MyISAM和InnoDB表,前綴最長為1000字節。注意前綴的限長以字節計,而CREATE INDEX語句中的前綴長度指的是字符的數目。對于使用多字節字符集的列,在指定列的前綴長度時,要考慮這一點。
在MySQL 5.1中:
·???????? 只有當您正在使用MyISAM, InnoDB或BDB表類型時,您可以向有NULL值的列中添加索引。
·???????? 只有當您正在使用MyISAM, BDB或InnoDB表類型時,您可以向BLOB或TEXT列中添加索引。
一個_index_col_name_規約可以以ASC或DESC為結尾。這些關鍵詞將來可以擴展,用于指定遞增或遞減索引值存儲。目前,這些關鍵詞被分析,但是被忽略;索引值均以遞增順序存儲。
部分儲存引擎允許在創建索引時指定索引類型。_index_type_指定語句的語法是USING _type_name_。不同的儲存引擎所支持的_type_name_值已顯示在下表中。如果列有多個索引類型,當沒有指定_index_type_時,第一個類型是默認值。
<table border="1" cellpadding="0" id="table1"><tr><td> <p><strong><span> 存儲引擎</span></strong></p></td> <td> <p><strong><span> 允許的索引類型</span></strong></p></td> </tr><tr><td> <p> <span>MyISAM</span></p></td> <td> <p> <span>BTREE</span></p></td> </tr><tr><td> <p> <span>InnoDB</span></p></td> <td> <p> <span>BTREE</span></p></td> </tr><tr><td> <p> <span>MEMORY</span><span>/<span>HEAP</span></span></p></td> <td> <p> <span>HASH</span><span>, <span>BTREE</span></span></p></td> </tr></table>
示例:
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如何使用索引”](# "7.4.5.?How MySQL Uses Indexes")。
FULLTEXT索引只能對CHAR, VARCHAR和TEXT列編制索引,并且只能在MyISAM表中編制。請參見[12.7節,“全文搜索功能”](# "12.7.?Full-Text Search Functions")。
SPATIAL索引只能對空間列編制索引,并且只能在MyISAM表中編制。空間列類型在[第19章:](#)[_MySQL中的空間擴展_](# "Chapter?19.?Spatial Extensions in MySQL")中進行了描述。
### 13.1.5.?CREATE TABLE語法
[ 13.1.5.1. 沉寂的列規格變更](#)
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節,“數據庫、表、索引、列和別名”](# "9.2.?Database, Table, Index, Column, and Alias Names")中。默認的情況是,表被創建到當前的數據庫中。如果表已存在,或者如果沒有當前數據庫,或者如果數據庫不存在,則會出現錯誤。
表名稱被指定為_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表,存儲引擎可以創建數據和索引文件。因此,對于每個MyISAM表_tbl_name_,有三個磁盤文件:
<table border="1" cellpadding="0" id="table2"><tr><td> <p><strong><span> 文件</span></strong></p></td> <td> <p><strong><span> 作用</span></strong></p></td> </tr><tr><td> <p><span><i> <span>tbl_name</span></i><span>.frm</span></span></p></td> <td> <p>表格式(定義)文件</p></td> </tr><tr><td> <p><span><i> <span>tbl_name</span></i><span>.MYD</span></span></p></td> <td> <p>數據文件</p></td> </tr><tr><td> <p><span><i> <span>tbl_name</span></i><span>.MYI</span></span></p></td> <td> <p>索引文件</p></td> </tr></table>
用于表示表的由存儲引擎創建的文件在[第15章:_存儲引擎和表類型_](# "Chapter?15.?Storage Engines and Table Types")中描述。
要了解有關各種列類型的性質的一般說明,請參見[第11章:列類型](# "Chapter?11.?Column Types")。要了解有關空間列類型的說明,請參見[第19章:](#)[_MySQL中的空間擴展_](# "Chapter?19.?Spatial Extensions in MySQL")。
·???????? 如果沒有指定是NULL或是NOT NULL,則列在創建時假定指定為NULL。
·???????? 一個整數列可以擁有一個附加屬性AUTO_INCREMENT。當您向一個已編入索引的AUTO_INCREMENT列中插入一個NULL值(建議)或0時,此列被設置為下一個序列的值。通常情況下為_value_+1,此處_value_是當前在表中的列的最大值。AUTO_INCREMENT序列從1開始。這樣的列必須被定義為一種整數類型,請參見[11.1.1節,“數值類型概述”](# "11.1.1.?Overview of Numeric Types")中的敘述。(值1.0不是整數)。請參見[25.2.3.36節,“mysql_insert_id()”](# "25.2.3.36.?mysql_insert_id()")。
為--sql-mode服務器選項或sql_mode系統變量指定NO_AUTO_VALUE_ON_ZERO特征位,這樣可以把0存儲到AUTO_INCREMENT列中,同時不生成一個新的序列值。請參見[5.3.1節,“**mysqld**命令行選項”](# "5.3.1.?mysqld Command-Line Options")。
注釋:有時候,每個表只有一個AUTO_INCREMENT列,此列必須編制索引,不能有DEFAULT值。一個AUTO_INCREMENT列只有在只包含正數的情況下,才能運行正常。插入一個負數會被認為是插入了一個非常大的正數。這樣做是為了避免當數字由正數轉為負數時出現精度問題,同時也為了確保AUTO_INCREMENT列中不會包含0。
對于MyISAM和BDB表,您可以在一個多列關鍵字中指定一個AUTO_INCREMENT次級列。請參見[3.6.9節,“使用AUTO_INCREMENT”](# "3.6.9.?Using AUTO_INCREMENT")。
為了讓MySQL與部分ODBC應用軟件相兼容,您可以使用以下查詢方法找到最后一個插入行的AUTO_INCREMENT值:
SELECT * FROM tbl_name WHERE auto_col IS NULL
·???????? 字符列的定義可以包括一個CHARACTER SET屬性,用來指定字符集,也可以指定列的整序。要了解詳細情況,請參見[第10章:_字符集支持_](# "Chapter?10.?Character Set Support")。CHARSET是CHARACTER 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屬性”](# "11.3.1.1.?TIMESTAMP Properties as of MySQL 4.1")。
BLOB和TEXT列不能被賦予默認值。
如果在列定義中沒有明確的DEFAULT值,則MySQL按照如下規則確定默認值:
如果列可以使用NULL作為值,則使用DEFAULT NULL子句對列進行定義。(在MySQL的早期版本中也如此。)
如果列不能使用NULL作為值,則MySQL對列進行定義時不使用DEFAULT子句。輸入數據時,如果INSERT或REPLACE語句不包括列的值,則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服務器模式”](# "5.3.2.?The Server SQL Mode")。
對于一個給定的表,您可以使用SHOW CREATE TABLE語句來查看那些列有明確的DEFAULT子句。
·???????? 對于列的評注可以使用COMMENT選項來進行指定。評注通過SHOW CREATE TABLE和SHOW 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 NULL,MySQL應隱含地定義這些列。一個表只有一個PRIMARY KEY。如果您沒有PRIMARY KEY并且一個應用程序要求在表中使用PRIMARY KEY,則MySQL返回第一個UNIQUE索引,此索引沒有作為PRIMARY KEY的NULL列。
·???????? 在已創建的表中,PRIMARY KEY的位置最靠前,然后是所有的UNIQUE索引,然后是非唯一索引。這可以幫助MySQL優化程序選擇優先使用哪個索引,并且更快速的檢測出重復的UNIQUE關鍵字。
·???????? PRIMARY KEY可以是一個多列索引。但是,在列規約中使用PRIMARY KEY關鍵字屬性無法創建多列索引。這么做只能把一個列標記為主列。您必須使用一個單獨的PRIMARY KEY(index_col_name, ...)子句。
·???????? 如果PRIMARY KEY或UNIQUE索引只包括一個列,并且此列為整數類型,則您也可以在SELECT語句中把此列作為_rowid引用。
·???????? 在MySQL中,PRIMARY KEY的名稱為PRIMARY。對于其它索引,如果您沒有賦予名稱,則索引被賦予的名稱與第一個已編入索引的列的名稱相同,并自選添加后綴(_2, _3,...),使名稱為唯一名稱。您可以使用SHOW INDEX FROM _tbl_name_來查看表的索引名稱。請參見[13.5.4.11節,“SHOW INDEX語法”](# "13.5.4.11.?SHOW INDEX Syntax")。
·???????? 部分存儲引擎允許您在創建索引時指定索引類型。_index_type_指示語句的語法是USING type_name。
示例:
CREATE TABLE lookup
? (id INT, INDEX USING BTREE (id))
? ENGINE = MEMORY;
要了解有關USING的詳細說明,請參見[13.1.4節,“CREATE INDEX語法”](# "13.1.4.?CREATE INDEX Syntax")。
要了解有關MySQL如何使用索引的更多信息,請參見[7.4.5節,“MySQL如何使用索引”](# "7.4.5.?How MySQL Uses Indexes")。
·???????? 在MySQL 5.1中,只有MyISAM,InnoDB, BDB和MEMORY存儲引擎支持在含有NULL值的列中編索引。在其它情況下,您必須定義已編索引的列為NOT NULL,否則會出現錯誤。
·???????? 在一個索引規約中使用_col_name_(_length_)語法,您可以創建一個索引,此索引只使用一個CHAR或VARCHAR列的第一個_length_字符。只對列值的前綴編制索引可以使索引文件大大減小。請參見[7.4.3節,“列索引”](# "7.4.3.?Column Indexes")。
MyISAM和InnoDB存儲引擎也支持對BLOB和TEXT列編索引。當對BLOB或TEXT列編索引時,您必須為索引指定一個前綴長度。例如:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
對于MyISAM和InnoDB表,前綴最長可以為1000字節,對于其它表格類型,最長可以為255字節。注意前綴長度限值以字節為單位,而在CREATE TABLE語句中的前綴長度用字符數目來表述。當為一個使用多字節字符集的列指定前綴長度時,一定要考慮到這一點。
·???????? 一個_index_col_name_規約可以以ASC或DESC結尾。這些關鍵詞可以在將來進行擴展,用于指定升序或降序的索引值存儲。當前,這些關鍵詞被分析但是被忽略;索引值均以升序儲存。
·???????? 當您在SELECT中的TEXT列或BLOB列中使用ORDER BY或GROUP BY時,服務器只使用初始的字節數目對值進行分類。字節數目由max_sort_length系統變量進行指示。請參見[11.4.3節,“BLOB和TEXT類型``”](# "11.4.3.?The BLOB and TEXT Types")。
·???????? 您可以創建特殊的FULLTEXT索引,用于全文搜索。只有MyISAM表類型支持FULLTEXT索引。FULLTEXT索引只可以從CHAR, VARCHAR和TEXT列中創建。整個列都會被編入索引;不支持對部分列編索引。如果已指定,前綴長度會被忽略。要了解運行的詳細說明,請參見[12.7節,“全文搜索功能”](# "12.7.?Full-Text Search Functions")。
·???????? 您可以為空間列類型創建SPATIAL索引。只有MyISAM表支持空間類型,已編索引的列必須聲明為NOT NULL。請參見[第19章:](#)[_MySQL中的空間擴展_](# "Chapter?19.?Spatial Extensions in MySQL")。
·???????? InnoDB表支持對外鍵限制條件進行檢查。請參見[15.2節,“InnoDB存儲引擎”](# "15.2.?The InnoDB Storage Engine")。注意,在InnoDB中,FOREIGN KEY語法比本節開始時介紹的CREATE TABLE語句的語法更嚴格:被引用的表中的列必須有明確的命名。InnoDB支持外鍵的ON DELETE和ON UPDATE兩種操作。有關精確語法的說明,請參見[15.2.6.4節,“FOREIGN KEY約束”](# "15.2.6.4.?FOREIGN KEY Constraints")。
對于其它存儲引擎,MySQL服務器對CREATE TABLE語句中的FOREIGN KEY和REFERENCES語法進行分析,但不采取進一步的行動。所有的存儲引擎均對CHECK子句進行分析,但是忽略CHECK子句。請參見[1.8.5.5節,“外鍵”](# "1.8.5.5.?Foreign Keys")。
·???????? 對于MyISAM表,每個NULL列要多占用一位,進位到距離最近的字節。最大記錄長度(以字節為單位)按照如下方法計算:
·??????????????? row length = 1
·??????????????? ?????????????+ (sum of column lengths)
·??????????????? ?????????????+ (number of NULL columns + delete_flag + 7)/8
·??????????????? ?????????????+ (number of variable-length columns)
對于采用靜態記錄格式的表,_delete_flag_為1。靜態表在行記錄中使用一位用作位標記。位標記指示該行是否已被刪除。對于動態表,_delete_flag_為0,因為在動態行標題中已存儲了位標記。
這些計算方法不適用于InnoDB表。對于InnoDB表,NULL列的存儲量與NOT NULL列的存儲量沒有區別。
ENGINE和TYPE選項用于為表指定存儲引擎。ENGINE是首選的選項名稱。
ENGINE和TYPE選項采用以下值:
<table border="1" cellpadding="0" id="table3"><tr><td> <p><strong><span> 存儲引擎</span></strong></p></td> <td> <p><strong><span> 說明</span></strong></p></td> </tr><tr><td> <p> <span>ARCHIVE</span></p></td> <td> <p>檔案存儲引擎。請參見<a href="storage-engines.html#archive-storage-engine" title="15.8.?The ARCHIVE Storage Engine">15.8節,“ARCHIVE存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>BDB</span></p></td> <td> <p>帶頁面鎖定的事務安全表。也稱為<span>BerkeleyDB</span>。請參見<a href="storage-engines.html#bdb-storage-engine" title="15.5.?The BDB (BerkeleyDB) Storage Engine">15.5節,“BDB (BerkeleyDB)存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>CSV</span></p></td> <td> <p>值之間用逗號隔開的表。請參見<a href="storage-engines.html#csv-storage-engine" title="15.9.?The CSV Storage Engine">15.9節,“CSV存儲引擎</a>。</p></td> </tr><tr><td> <p> <span>EXAMPLE</span></p></td> <td> <p>示例引擎。請參見<a href="storage-engines.html#example-storage-engine" title="15.6.?The EXAMPLE Storage Engine">15.6節,“EXAMPLE存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>FEDERATED</span></p></td> <td> <p>可以訪問遠程表的存儲引擎。請參見<a href="storage-engines.html#federated-storage-engine" title="15.7.?The FEDERATED Storage Engine">15.7節,“FEDERATED存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>HEAP</span></p></td> <td> <p>見<a href="storage-engines.html#memory-storage-engine" title="15.4.?The MEMORY (HEAP) Storage Engine">15.4節,“MEMORY (HEAP)存儲引擎”</a>。</p></td> </tr><tr><td> <p><span>(<em><span>OBSOLETE</span></em>) <span>ISAM</span></span></p></td> <td> <p>在<span>MySQL 5.1</span>中沒有此引擎。如果您要從以前的版本升級到<span>MySQL 5.1</span>,您應該在進行升級前把原有的<span>ISAM</span>表轉換為<span>MyISAM</span>表。請參見<a href="storage-engines.html" title="Chapter?15.?Storage Engines and Table Types">第15章:<i>存儲引擎和表類型</i></a>。</p></td> </tr><tr><td> <p> <span>InnoDB</span></p></td> <td> <p>帶行鎖定和外鍵的事務安全表。請參見<a href="storage-engines.html#innodb" title="15.2.?The InnoDB Storage Engine">15.2節,“InnoDB存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>MEMORY</span></p></td> <td> <p>本表類型的數據只保存在存儲器里。(在早期<span>MySQL</span>版本中被稱為<span>HEAP</span>。)</p></td> </tr><tr><td> <p> <span>MERGE</span></p></td> <td> <p><span>MyISAM</span>表的集合,作為一個表使用。也稱為<span>MRG_MyISAM</span>。請參見<a href="storage-engines.html#merge-storage-engine" title="15.3.?The MERGE Storage Engine">15.3節,“MERGE存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>MyISAM</span></p></td> <td> <p>二進制輕便式存儲引擎,此引擎是<span>MySQL</span>所用的默認存儲引擎。請參見<a href="storage-engines.html#myisam-storage-engine" title="15.1.?The MyISAM Storage Engine">15.1節,“MyISAM存儲引擎”</a>。</p></td> </tr><tr><td> <p> <span>NDBCLUSTER</span></p></td> <td> <p>成簇表,容錯表,以存儲器為基礎的表。也稱為<span>NDB</span>。請參見<a href="ndbcluster.html">第17章:</a><a href="ndbcluster.html" title="Chapter?17.?MySQL Cluster"><i>MySQL簇</i></a>。</p></td> </tr></table>
要了解有關MySQL存儲引擎的更多信息,請參見[第15章:_存儲引擎和表類型_](# "Chapter?15.?Storage Engines and Table Types")。
如果被指定的存儲引擎無法利用,則MySQL使用MyISAM代替。例如,一個表定義包括ENGINE=BDB選項,但是MySQL服務器不支持BDB表,則表被創建為MyISAM表。這樣,如果您在主機上有事務表,但在從屬機上創建的是非交互式表(以加快速度)時,可以進行復制設置。在MySQL 5.1中,如果沒有遵守存儲引擎規約,則會出現警告。
其它表選項用于優化表的性質。在多數情況下,您不必指定表選項。這些選項適用于所有存儲引擎,另有說明除外:
·???????? AUTO_INCREMENT
表的初始AUTO_INCREMENT值。在MySQL 5.1中,本選項只適用于MyISAM和MEMORY表。InnoDB也支持本選項。如果引擎不支持AUTO_INCREMENT表選項,則要設置引擎的第一個auto-increment值,需插入一個“假”行。該行的值比創建表后的值小一,然后刪除該假行。
對于在CREATE TABLE語句中支持AUTO_INCREMENT表選項的引擎,您也可以使用ALTER TABLE _tbl_name_ AUTO_INCREMENT = _n_來重新設置AUTO_INCREMENT值。
·???????? AVG_ROW_LENGTH
表中平均行長度的近似值。只需要對含尺寸可變的記錄的大型表進行此項設置。
當創建一個MyISAM表時,MySQL使用MAX_ROWS和AVG_ROW_LENGTH選項的乘積來確定得出的表有多大。如果有一個選項未指定,則表的最大尺寸為65,536TB數據。(如果操作系統不支持這么大的文件,則表的尺寸被限定在操作系統的限值處。)如果您想縮小指針尺寸使索引更小,速度更快,并且您不需要大文件,則您可以通過設置myisam_data_pointer_size系統變量來減少默認指針的尺寸。(見[5.3.3節,“服務器系統變量”](# "5.3.3.?Server System Variables")。)如果您希望所有的表可以擴大,超過默認限值,并且愿意讓表稍微慢點,并稍微大點,則您可以通過設置此變量增加默認指針的尺寸。
·???????? [DEFAULT] CHARACTER SET
用于為表指定一個默認字符集。CHARSET是CHARACTER 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時,存儲引擎只壓縮長的CHAR或VARCHAR列(僅限于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表。對于靜態行或長度可變行,此選項值可以為FIXED或DYNAMIC。**myisampack**用于把類型設置為COMPRESSED。請參見[15.1.3節,“MyISAM表的存儲格式”](# "15.1.3.?MyISAM Table Storage Formats")。
在默認情況下,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
當您想要把一組相同的表當作一個表使用時,采用UNION。UNION僅適用于MERGE表。請參見[15.3節,“MERGE存儲引擎”](# "15.3.?The MERGE Storage Engine")。
對于您映射到一個MERGE表上的表,您必須擁有SELECT, UPDATE和DELETE權限。(注釋:以前,所有被使用的表必須位于同一個數據庫中,并作為MERGE表。這些限制不再適用。)
·???????? INSERT_METHOD
如果您希望在MERGE表中插入數據,您必須用INSERT_METHOD指定應插入行的表。INSERT_METHOD選項僅用于MERGE表。使用FIRST或LAST把行插入到第一個或最后一個表中;或者使用NO,阻止插入行。請參見[15.3節,“MERGE存儲引擎”](# "15.3.?The MERGE Storage Engine")。
·???????? DATA DIRECTORY, INDEX DIRECTORY
通過使用DATA DIRECTORY='_directory_'或INDEX DIRECTORY='_directory_',您可以指定MyISAM存儲引擎放置表格數據文件和索引文件的位置。注意,目錄應是通向目錄的完整路徑(不是相對路徑)。
僅當您沒有使用--skip-symbolic-links選項時,DATA DIRECTORY, INDEX DIRECTORY才能使用。操作系統必須有一個正在工作的、線程安全的realpath()調用。要了解全面信息,請參見[7.6.1.2節,“在Unix平臺上使用表的符號鏈接](# "7.6.1.2.?Using Symbolic Links for Tables on Unix")”。
·???????? 對于用CREATE TABLE創建的表,可以使用_partition_options_控制分區。如果使用了_partition_options_,則其中必須包含至少一個PARTITION BY子句。本子句包含用于確定分區的函數;該函數會返回一個整值,范圍從1到_num_。此處_num_為分區的數目。此函數中可以使用的選項顯示在下面的清單中。 要點:在本節開始時介紹的用于_partition_options_的語法中顯示的選項,并不是都能用于所有分區類型。要了解各種類型具體的信息 ,請參見以下各類型的清單。要了解有關在MySQL中的分區的操作和使用情況的全面說明,以及要了解表創建的示例和與MySQL分區有關的其它命令,請參見[第18章:](#)[_分區_](# "Chapter?18.?Partitioning")。
o??????? HASH(_expr_):用于混編一個或多個列,創建一個關鍵字,用于放置行,并確定行的位置。_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 THAN或VALUES IN子句不能和PARTITION BY HASH一起使用。
PARTITION BY HASH使用_expr_被分區數目所除后的余數(也就是模數)。要了解示例和其它信息,請參見[18.2.3節,“HASH分區”](# "18.2.3.?HASH Partitioning")。
LENEAR關鍵詞需要一種不同的算法。在這種情況下,通過一次或多次邏輯AND運算得出的結果,計算出存儲記錄的分區的數目。要了解線形混編的討論和示例,請參見[18.2.3.1節,“LINEAR HASH分區”](# "18.2.3.1.?LINEAR HASH Partitioning")。
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.3.1.?LINEAR HASH Partitioning")和[18.2.4節,“KEY分區”](# "18.2.4.?KEY Partitioning"))。本示例采用了關鍵字線形分區,用來在5個分區之間分配數據:
CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
???PARTITION BY LINEAR KEY(col3)
??? PARTITIONS 5;
VALUES LESS THAN或VALUES IN子句不能和PARTITION BY KEY一起使用。
o??????? RANGE:在此情況下,_expr_使用一套VALUES LESS THAN操作符顯示了某一范圍內的值。當使用范圍分區時,您必須使用VALUES LESS THAN定義至少一個分區。VALUES IN不能和范圍分區一起使用。
VALUES LESS THAN可以與一個文字值同時使用,或者與一個可以求算單一值的表達式同時使用。
舉例說明,假設您有一個表,您希望采用以下方法對包含年份值的一列進行分區:
<table border="1" cellpadding="0" id="table4"><tr><td> <p>分區編號:</p></td> <td> <p>年份范圍:</p></td> </tr><tr><td> <p><span>0</span></p></td> <td> <p><span>1990</span>以前</p></td> </tr><tr><td> <p><span>1</span></p></td> <td> <p><span>1991 - 1994</span></p></td> </tr><tr><td> <p><span>2</span></p></td> <td> <p><span>1995 - 1998</span></p></td> </tr><tr><td> <p><span>3</span></p></td> <td> <p><span>1999 - 2002</span></p></td> </tr><tr><td> <p><span>4</span></p></td> <td> <p><span>2003 - 2005</span></p></td> </tr><tr><td> <p><span>5</span></p></td> <td> <p><span>2006</span>年以后</p></td> </tr></table>
采用這種分區方法的表可以通過如下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, Java和PHP也如此)。也就是說,子句必須按照這樣一種方法排列,每一個后續的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 THAN或VALUES 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子句說明的分區的總數相等。
注釋:不論您在創建一個由RANGE或LIST進行分區的表時是否使用了PARTITIONS子句,您必須在表定義中包括至少一個PARTITION VALUES(見后)。
o??????? 一個分區可以自選分隔成多個子分區。使用自選的SUBPARTITION BY子句可以指示。子分區可以由HASH或KEY進行分隔。兩種方法建立的子分區均為LINEAR。分隔子分區時的操作方式與以前描述的分區類型的操作方式一樣。(無法由LIST或RANGE進行子分區分隔。)
使用SUBPARTITIONS關鍵詞,后面接一個整值,可以對子分區的數目進行指示。
·???????? 使用一個_partition_definition_子句可以對每個分區分別進行定義。下面是組成這個子句的各個部分:
o??????? PARTITION _ partition_name_:用于為分區指定一個邏輯名稱。
o??????? VALUE子句:對于范圍分區,每個分區必須包括一個VALUES LESS THAN子句;對于清單分區,您必須為每個分區指定一個VALUES IN子句。本子句用于確定哪些行將被存儲到此分區中。要了解語法示例,請參見[第18章:](#)[_分區_](# "Chapter?18.?Partitioning")中對分區類型的討論。
o??????? 自選的COMMENT子句可以用于描述分區。注釋必須加單引號。舉例說明:
o???????????????????? COMMENT = 'Data for the years previous to 1999'
o??????? DATA DIRECTORY和INDEX DIRECTORY可以被用于指示本分區的數據和索引各自的存儲位置的目錄。_data_dir_和_index_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
- 前言
- 1. 一般信息
- 2. 安裝MySQL
- 3. 教程
- 4. MySQL程序概述
- 5. 數據庫管理
- 6. MySQL中的復制
- 7. 優化
- 8. 客戶端和實用工具程序
- 9. 語言結構
- 10. 字符集支持
- 11. 列類型
- 12. 函數和操作符
- 13. SQL語句語法
- 14. 插件式存儲引擎體系結構
- 15. 存儲引擎和表類型
- 16. 編寫自定義存儲引擎
- 17. MySQL簇
- 18. 分區
- 19. MySQL中的空間擴展
- 20. 存儲程序和函數
- 21. 觸發程序
- 22. 視圖
- 23. INFORMATION_SCHEMA信息數據庫
- 24. 精度數學
- 25. API和庫
- 26. 連接器
- 27. 擴展MySQL
- A. 問題和常見錯誤
- B. 錯誤代碼和消息
- C. 感謝
- D. MySQL變更史
- E. 移植到其他系統
- F. 環境變量
- G. MySQL正則表達式
- H. MySQL中的限制
- I. 特性限制
- J. GNU通用公共許可
- K. MySQL FLOSS許可例外
- 索引