翻譯:MariaDB ALTER TABLE語句

本文是MariaDB官方ALTER TABLE手冊的翻譯,99%的內容是按照手冊給的內容進行翻譯的。javascript

原文地址:https://mariadb.com/kb/en/library/alter-table/php

我提交到MariaDB官方手冊的譯文:https://mariadb.com/kb/zh-cn/library/alter-table/css

Syntax

ALTER [ONLINE] [IGNORE] TABLE tbl_name [WAIT n | NOWAIT] alter_specification [, alter_specification] ... alter_specification: table_option ... | ADD [COLUMN] col_name column_definition [FIRST | AFTER col_name ] | ADD [COLUMN] (col_name column_definition,...) | ADD {INDEX|KEY} [index_name] [index_type] (index_col_name,...) [index_option] ... | ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...) [index_option] ... | ADD [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name] [index_type] (index_col_name,...) [index_option] ... | ADD FULLTEXT [INDEX|KEY] [index_name] (index_col_name,...) [index_option] ... | ADD SPATIAL [INDEX|KEY] [index_name] (index_col_name,...) [index_option] ... | ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...) reference_definition | ALTER [COLUMN] col_name SET DEFAULT literal | (expression) | ALTER [COLUMN] col_name DROP DEFAULT | CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST|AFTER col_name] | MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name] | DROP [COLUMN] [IF EXISTS] col_name [RESTRICT|CASCADE] | DROP PRIMARY KEY | DROP {INDEX|KEY} index_name | DROP FOREIGN KEY fk_symbol | DROP CONSTRAINT constraint_name | DISABLE KEYS | ENABLE KEYS | RENAME [TO] new_tbl_name | ORDER BY col_name [, col_name] ... | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name] | [DEFAULT] CHARACTER SET [=] charset_name | [DEFAULT] COLLATE [=] collation_name | DISCARD TABLESPACE | IMPORT TABLESPACE | ALGORITHM [=] {DEFAULT|INPLACE|COPY} | LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE} | FORCE | 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 | EXCHANGE PARTITION partition_name WITH TABLE tbl_name | REMOVE PARTITIONING column_definition: data_type [NOT NULL | NULL] [DEFAULT default_value | (expression)] [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string'] [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}] [STORAGE {DISK|MEMORY|DEFAULT}] | data_type [GENERATED ALWAYS] AS ( <expression> ) {VIRTUAL | PERSISTENT} [UNIQUE] [UNIQUE KEY] [COMMENT 'string'] index_col_name: col_name [(length)] [ASC | DESC] index_type: USING {BTREE | HASH | RTREE} index_option: KEY_BLOCK_SIZE [=] value | index_type | WITH PARSER parser_name | COMMENT 'string' | CLUSTERING={YES| NO} table_options: table_option [[,] table_option] ... (see CREATE TABLE options)

從MariaDB 10.0.2開始,ALTER TABLE還支持IF EXISTS和IF NOT EXISTS字句。包括如下幾種狀況:html

ADD COLUMN       [IF NOT EXISTS]
ADD INDEX        [IF NOT EXISTS]
ADD FOREIGN KEY  [IF NOT EXISTS]
ADD PARTITION    [IF NOT EXISTS]
CREATE INDEX [IF NOT EXISTS] DROP COLUMN [IF EXISTS] DROP INDEX [IF EXISTS] DROP FOREIGN KEY [IF EXISTS] DROP PARTITION [IF EXISTS] CHANGE COLUMN [IF EXISTS] MODIFY COLUMN [IF EXISTS] DROP INDEX [IF EXISTS]

當使用了IF EXISTS或IF NOT EXISTS時,當知足存在或不存在的條件時,查詢將不會產生任何錯誤。java

基本描述

ALTER TABLE語句能夠改變已存在表的結構。例如,能夠增減字段、建立或銷燬索引、修改字段類型、重命名字段或重命名錶自身。還能夠改變表的註釋以及表的存儲引擎。mysql

若是有某個鏈接正在使用表,將會激活一個元數據鎖,這使得ALTER語句會一直等待直到該鎖被釋放。這也適用於非事務表nginx

當在已存在重複值的某字段(或某幾個字段)上創建UNIQUE索引時,將生成一個錯誤信息,而後alter語句終止。能夠指定IGNORE選項忽略字段中的重複值,以禁止該錯誤並強制建立UNIQUE索引。但它將沒法控制已存在的行。還須要注意,alter table ... exchange partition語句雖然接受IGNORE選項,但會忽略它。git

ALTER TABLE能夠重命名錶,詳細信息見個人另外一篇譯文RENAME TABLEgithub

當建立索引時,存儲引擎將在處理過程當中使用可配置的buffer。增大buffer能夠加速索引的建立。Aria和MyISAM存儲引擎分別根據aria_sort_buffer_sizemyisam_sort_buffer_size指定的值大小來分配buffer,在REPAIR TABLE時也一樣會使用其值來分配buffer空間。InnoDB/XtraDB存儲引擎使用innodb_sort_buffer_size的值來分配3個具備該值大小的buffer空間。web

注:innodb sort buffer的大小影響索引建立速度,還影響online DDL操做時記錄併發寫的臨時日誌文件數量。在MariaDB 10.0之前,innodb_sort_buffer_size的大小是固定不可配置的,其值爲1M。設置的值越大,在排序時合併結果的次數和階段就越少,速度就越快。當CREATE TABLE或ALTER TABLE建立新的索引時,將分配3個具備該值大小的buffer空間,還包括緩衝區中的行的指針。該變量爲全局變量,單位爲字節,默認值爲1048576(即1M),有效範圍爲65536-67108864(即64k-64M)。

索引類型Index Type

存儲引擎容許的索引類型以下:

Storage Engine Permitted Indexes
Aria BTREE, RTREE
MyISAM BTREE, RTREE
InnoDB BTREE
MEMORY/HEAP HASH, BTREE
NDB BTREE, HASH

CLUSTERING={YES|NO}僅對Tokudb有效。

CREATE INDEXDROP INDEX一樣也能夠添加或刪除索引。

字符集和排序規則Character Sets and Collations

CONVERT TO CHARACTER SET charset_name [COLLATE collation_name] [DEFAULT] CHARACTER SET [=] charset_name [DEFAULT] COLLATE [=] collation_name

WAIT/NOWAIT

從MariaDB 10.3.0開始引入WAIT和NOWAIT選項,用於設置某些語句的鎖等待超時時長。詳細信息見個人另外一篇譯文:MariaDB wait/nowait

ADD COLUMN [IF NOT EXISTS] (col_name column_definition,...)

向表中添加一個字段。語法同CREATE TABLE。若是使用了IF NOT EXISTS,則待添加的列已存在時不會被建立。這在腳本中想要修改表時很是有用。

FIRST和AFTER字句會影響數據文件datafile中字段的物理順序。使用FIRST以將字段添加到表的最左邊的位置,即做爲第一列。或者使用AFTER使得新建的列在指定的字段以後。注意,直到目前爲止,字段的物理位置順序一般是可有可無的。

DROP COLUMN [IF EXISTS] col_name [CASCADE|RESTRICT]

從表中刪除字段。若是使用IF EXISTS,那麼在字段不存在時不會產生錯誤信息。若是字段是某個或某些索引的一部分,刪除字段將會從索引中將其刪除,除非你在同一時刻建立一個同名的新字段(例如修改字段類型時會隱式重建字段)。若是索引中的全部字段都被刪除了,則索引會自動被刪除。若是在視圖或觸發器中引用了某個字段,將在下次訪問視圖或觸發器時產生一個錯誤信息。

從MariaDB 10.2.8開始,從多列複合的UNIQUE約束中刪除某個字段是不被容許的,例如:

CREATE TABLE a ( a int, b int, primary key (a,b) );

ALTER TABLE x DROP COLUMN a;
[42000][1072] Key column 'A' doesn't exist in table

刪除字段a的過程當中將致使新的約束(刪除字段a就變成了新約束)要求字段b中的全部值都是惟一的。要刪除UNIQUE索引中的字段,須要顯式指定drop primary key以及add primary key。而MariaDB 10.2.7版本及之前的版本,均可以直接刪除字段並應用新的約束,以下:

ALTER TABLE x DROP COLUMN a;
Query OK, 0 rows affected (0.46 sec)

DESC x;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| b     | int(11) | NO   | PRI | NULL    |       |
+-------+---------+------+-----+---------+-------+

RESTRICT和CASCADE使得從其餘數據庫系統移植數據更加容易,但在MariaDB中,它們沒有任何做用。

MODIFY COLUMN

能夠用來修改字段類型。modify操做不會改變字段順序,也不會影響索引中的字段元素。注意,當modifiy字段時,必須從新指定新字段的全部屬性,但由於不會影響索引中的內容,因此無需再指定約束類屬性。

CREATE TABLE t1 (a INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY((a));
ALTER TABLE t1 MODIFY a BIGINT UNSIGNED AUTO_INCREMENT;

CHANGE COLUMN

change和modify工做方式基本相同,除了change能夠改變字段名稱。一樣不會改變字段順序和索引中的字段元素。

CREATE TABLE t1 (a INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(a));
ALTER TABLE t1 CHANGE a b BIGINT UNSIGNED AUTO_INCREMENT;

ENABLE/ DISABLE KEYS

DISABLE KEYS將無視表中存儲引擎(至少是MyISAM和Aria)支持的全部非unique索引。這能夠加速向空表插入數據。

ENABLE KEYS用來啓用全部被DISABLE的KEYS。

ENGINE/FORCE For Re-building a Table

ALTER TABLE能夠強制MariaDB重建(rebuild)表。在MariaDB 10.0之前,只能經過設置表的ENGINE爲原值來實現。從MariaDB 10.0開始,還可使用FORCE選項來實現。例以下面的InnoDB表,能夠:

ALTER TABLE tab_name ENGINE = InnoDB;

從MariaDB 10.0開始,這等價於:

ALTER TABLE tab_name FORCE;

對於InnoDB存儲引擎,ALTER TABLE將在innodb_file_per_table設置爲ON時回收未使用的空間(例如,以前刪除行後遺留下來的空間)。若是該變量的值爲OFF,在ALTER TABLE後將不會回收未使用的空間,但新插入數據時能夠從新使用這些空間。

IMPORT TABLESPACE

用於導入由flush tables for export建立的InnoDB表。

導入的過程大體以下:

CREATE TABLE t…; /* using the output from SHOW CREATE TABLE */
ALTER TABLE t DISCARD TABLESPACE; /* effectively corrupts the database! */
/* copy the file t.ibd to the file system */
ALTER TABLE t IMPORT TABLESPACE;

其餘存儲引擎無需使用alter table ...import。這些數據被拷貝後能夠馬上被成功訪問。

ALGORITHM子句/ALTER TABLE什麼時候會拷貝全表數據?

在MariaDB 10.0以前,ALTER TABLE操做表時會建立該表的臨時副本,這使得操做大表時速度較慢。從MariaDB 10.0開始,ALTER TABLE的許多操做均可以直接在原地操做,再也不須要建立表的臨時副本。

隨着時間的推移,可能愈來愈多的操做都再也不須要拷貝全表數據。如下是目前不須要表拷貝的動做的alter table行爲:

  • 修改字段名稱。
  • 擴大整型數據類型的顯示寬度,例如INT(2)-->INT(3)。
  • 修改表註釋。
  • 向enum的列表尾部添加值。
  • 重命名錶。

若是要執行多個操做,而且其中可能有一個或多個操做要求重建表,那麼能夠很方便地將這些操做組合在單個ALTER TABLE語句中,以便只執行一次重建操做。

從MariaDB 10.0開始,ALTER TABLE開始支持ALGORITHM字句,該字句有3種值:

  • ALGORITHM=DEFAULT (未指定ALGORITHM子句時的默認值)
  • ALGORITHM=COPY
  • ALGORITHM=INPLACE

設置ALGORITHM=COPY時,即便是那些不必拷貝表數據的操做也會進行copy。這會致使大量表數據的拷貝。

設置ALGORITHM=INPLACE時,將採用in-place技術(原地執行操做),它會禁止表數據拷貝。若是某操做要求拷貝表數據,那麼會返回相似以下的錯誤:

CREATE TABLE t1 (a INT, e ENUM ('red','green'));
ALTER TABLE t1 MODIFY e EMUM('red','green','blue'), ALGORITHM=INPLACE;
-> Query OK, 0 rows affected (0.11 sec) -> Records: 0 Duplicates: 0 Warnings: 0 ALTER TABLE t1 ADD c INT, ALGORITHM=INPLACE;
-> ERROR 1845 (0A000): ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.

默認的行爲(ALGORITHM=DEFAULT,或未設置ALGORITHM子句)一般僅在須要拷貝時進行表數據拷貝。能夠經過設置系統變量old_alter_table的值爲ON(默認爲OFF)來改變它的行爲,這種狀況下將使用pre-MySQL 5.0的拷貝算法進行表拷貝。

當設置ALGORITHM=INPLACE算法時,某些狀況下會須要一些臨時文件,這些臨時文件建立在tmpdir系統變量指定的臨時目錄內。

注意,若是使用了COPY算法,那麼innodb_file_per_tableinnodb_file_format變量的當前值會在InnoDB表重建時被提交。

LOCK子句

不一樣的操做、不一樣的存儲引擎,ALTER TABLE採用的鎖策略也不一樣。在某些狀況下徹底不須要任何鎖,某些狀況下僅須要讀鎖,某些狀況下又須要寫鎖。LOCK子句能夠指定一個固定的鎖策略。它會強制使用該鎖策略(即便指定的鎖策略可能比操做正常需求的鎖策略更嚴格),但若是存儲引擎上的某個操做要求比指定的策略更嚴格的策略,將生成錯誤信息。LOCK接受的值包括:

  • DEFAULT: 採用所容許的最高併發級別的鎖。
  • NONE: 不採用任何鎖,這可能會常常性地產生錯誤信息。
  • SHARED: 採用讀鎖。
  • EXCLUSIVE: 採用寫鎖。
  • 不指定LOCK子句時,默認LOCK=DEFAULT。

此外,可使用ALTER ONLINE TABLE確保ALTER TABLE子句不會阻塞任何正在併發的操做(不使用任何鎖),這等價於LOCK=NONE。

顯示進度

從MariaDB 5.3開始,能夠在支持進度報告協議的客戶端上獲取ALTER TABLE的處理進度。例如,從mysql客戶端:

ALTER TABLE test ENGINE=Aria;
Stage: 1 of 2 'copy to tmp table'    46% of stage

show processlist以及information_schema.processlist表一樣也能夠顯示處理進度。

權限需求

ALTER TABLE要求至少有ALTER權限。重命名錶還須要DROP, CREATE以及INSERT權限(由於重命名錶是重建表的過程,須要拷貝整個表數據到臨時副本,並使用副本填充新表)。

示例

添加一個字段:

ALTER TABLE t1 ADD x INT;

刪除一個字段:

ALTER TABLE t1 DROP x;

修改字段類型:

ALTER TABLE t1 MODIFY x bigint unsigned;

修改字段名稱以及字段類型:

ALTER TABLE t1 CHANGE a b bigint unsigned auto_increment;

整合多個子句到單個ALTER TABLE語句中,使用逗號分隔:

ALTER TABLE t1 DROP x, ADD x2 INT, CHANGE y y2 INT;

更換存儲引擎:

ALTER TABLE t1 ENGINE = InnoDB;

強制重建表(若是上面的例子中存儲引擎已是InnoDB,也將會重建表):

ALTER TABLE t1 FORCE;
相關文章
相關標籤/搜索