翻譯:MariaDB ALTER TABLE語句


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

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

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

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字句。包括以下幾種情況:

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時,當滿足存在或不存在的條件時,查詢將不會產生任何錯誤。

基本描述

ALTER TABLE語句可以改變已存在表的結構。例如,可以增減字段、創建或銷毀索引、修改字段類型、重命名字段或重命名表自身。還可以改變表的注釋以及表的存儲引擎。

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

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

ALTER TABLE可以重命名表,詳細信息見我的另一篇譯文RENAME TABLE

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

注: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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM