top
Loading...
13.1.2.ALTERTABLE語法
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有關的問題”。

作者:mysql.com
來源:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html
北斗有巢氏 有巢氏北斗