您可以使用在 CREATE TABLE
語句結尾加上 SELECT
語句的方式,從另一個表格建立新表格。
CREATE TABLE new_tbl [AS] SELECT * FROM orig_tbl;
MySQL 會為 SELECT
中的所有元素建立新的欄位。例如:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
-> PRIMARY KEY (a), KEY(b))
-> ENGINE=InnoDB SELECT b,c FROM test2;
這會建立一個具有三個欄位(a
、b
和 c
)的 InnoDB
表格。ENGINE
選項是 CREATE TABLE
語句的一部分,不應在 SELECT
之後使用;否則會導致語法錯誤。其他 CREATE TABLE
選項(例如 CHARSET
)也是如此。
請注意,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
欄位的資料類型。
對於同時支援原子 DDL 和外鍵約束的儲存引擎,當使用以列為基礎的複製時,不允許在 CREATE TABLE ... SELECT
語句中建立外鍵。可以使用 ALTER TABLE
在稍後添加外鍵約束。
您可以在 SELECT
前面加上 IGNORE
或 REPLACE
來指示如何處理重複唯一鍵值的列。使用 IGNORE
時,會捨棄唯一鍵值與現有列重複的列。使用 REPLACE
時,新的列會取代具有相同唯一鍵值的列。如果未指定 IGNORE
或 REPLACE
,重複的唯一鍵值將會導致錯誤。有關更多資訊,請參閱 「IGNORE 對語句執行的影響」。
您也可以在 CREATE TABLE ... SELECT
的 SELECT
部分中使用 VALUES
語句;語句的 VALUES
部分必須使用 AS
子句包含表格別名。若要命名來自 VALUES
的欄位,請使用表格別名提供欄位別名;否則,會使用預設欄位名稱 column_0
、column_1
、column_2
、...。
否則,如此建立的表格中欄位的命名將遵循本節先前所述的相同規則。範例如下:
mysql> CREATE TABLE tv1
> SELECT * FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v;
mysql> TABLE tv1;
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 1 | 3 | 5 |
| 2 | 4 | 6 |
+----------+----------+----------+
mysql> CREATE TABLE tv2
> SELECT * FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v(x,y,z);
mysql> TABLE tv2;
+---+---+---+
| x | y | z |
+---+---+---+
| 1 | 3 | 5 |
| 2 | 4 | 6 |
+---+---+---+
mysql> CREATE TABLE tv3 (a INT, b INT, c INT)
> SELECT * FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v(x,y,z);
mysql> TABLE tv3;
+------+------+------+----------+----------+----------+
| a | b | c | x | y | z |
+------+------+------+----------+----------+----------+
| NULL | NULL | NULL | 1 | 3 | 5 |
| NULL | NULL | NULL | 2 | 4 | 6 |
+------+------+------+----------+----------+----------+
mysql> CREATE TABLE tv4 (a INT, b INT, c INT)
> SELECT * FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v(x,y,z);
mysql> TABLE tv4;
+------+------+------+---+---+---+
| a | b | c | x | y | z |
+------+------+------+---+---+---+
| NULL | NULL | NULL | 1 | 3 | 5 |
| NULL | NULL | NULL | 2 | 4 | 6 |
+------+------+------+---+---+---+
mysql> CREATE TABLE tv5 (a INT, b INT, c INT)
> SELECT * FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v(a,b,c);
mysql> TABLE tv5;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 3 | 5 |
| 2 | 4 | 6 |
+------+------+------+
在選取所有欄位並使用預設欄位名稱時,您可以省略 SELECT *
,因此剛才用來建立表格 tv1
的語句也可以寫成如下所示:
mysql> CREATE TABLE tv1 VALUES ROW(1,3,5), ROW(2,4,6);
mysql> TABLE tv1;
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 1 | 3 | 5 |
| 2 | 4 | 6 |
+----------+----------+----------+
當使用 VALUES
作為 SELECT
的來源時,所有欄位都會一律選取到新表格中,而且無法像從具名表格選取時一樣選取個別欄位;以下每個語句都會產生錯誤 (ER_OPERAND_COLUMNS
)
CREATE TABLE tvx
SELECT (x,z) FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v(x,y,z);
CREATE TABLE tvx (a INT, c INT)
SELECT (x,z) FROM (VALUES ROW(1,3,5), ROW(2,4,6)) AS v(x,y,z);
類似地,您可以使用 TABLE
語句來代替 SELECT
。這遵循與 VALUES
相同的規則;來源表格的所有欄位及其在來源表格中的名稱都會一律插入到新表格中。範例如下:
mysql> TABLE t1;
+----+----+
| a | b |
+----+----+
| 1 | 2 |
| 6 | 7 |
| 10 | -4 |
| 14 | 6 |
+----+----+
mysql> CREATE TABLE tt1 TABLE t1;
mysql> TABLE tt1;
+----+----+
| a | b |
+----+----+
| 1 | 2 |
| 6 | 7 |
| 10 | -4 |
| 14 | 6 |
+----+----+
mysql> CREATE TABLE tt2 (x INT) TABLE t1;
mysql> TABLE tt2;
+------+----+----+
| x | a | b |
+------+----+----+
| NULL | 1 | 2 |
| NULL | 6 | 7 |
| NULL | 10 | -4 |
| NULL | 14 | 6 |
+------+----+----+
由於無法總是確定基礎 SELECT
語句中列的排序,因此 CREATE TABLE ... IGNORE SELECT
和 CREATE TABLE ... REPLACE SELECT
語句會被標記為不安全,無法用於以語句為基礎的複製。當使用以語句為基礎的模式時,此類語句會在錯誤記錄中產生警告,而且當使用 MIXED
模式時,會使用以列為基礎的格式寫入二進位日誌。另請參閱 第 19.2.1.1 節,「以語句為基礎和以列為基礎的複製的優點和缺點」。
CREATE TABLE ... SELECT
不會自動為您建立任何索引。這是故意這樣做,以便讓語句盡可能彈性。如果您想要在建立的表格中建立索引,您應該在 SELECT
語句之前指定這些索引:
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
對於 CREATE TABLE ... SELECT
,目標表格不會保留有關選取表格中的欄位是否為產生欄位的資訊。語句的 SELECT
部分無法將值指派給目標表格中的產生欄位。
對於 CREATE TABLE ... SELECT
,目標表格會保留原始表格中的運算式預設值。
可能會發生某些資料類型轉換。例如,不會保留 AUTO_INCREMENT
屬性,而且 VARCHAR
欄位可能會變成 CHAR
欄位。保留的屬性為 NULL
(或 NOT NULL
),以及對於具有這些屬性的欄位,保留 CHARACTER SET
、COLLATION
、COMMENT
和 DEFAULT
子句。
當使用 CREATE TABLE ... 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;
對於 CREATE TABLE ... SELECT
,如果提供 IF NOT EXISTS
且目標表格存在,則不會將任何內容插入到目標表格中,而且不會記錄該語句。
為了確保二進位日誌可用於重新建立原始表格,MySQL 不允許在 CREATE TABLE ... SELECT
期間進行並行插入。有關更多資訊,請參閱 第 15.1.1 節,「原子資料定義語句支援」。
您不能在 CREATE TABLE
等語句中,將 new_table
SELECT ... FROM old_table
...FOR UPDATE
作為 SELECT
的一部分。如果您嘗試這樣做,該語句將會失敗。
CREATE TABLE ... SELECT
操作僅將 ENGINE_ATTRIBUTE
和 SECONDARY_ENGINE_ATTRIBUTE
值套用至欄位。除非明確指定,否則表格和索引的 ENGINE_ATTRIBUTE
和 SECONDARY_ENGINE_ATTRIBUTE
值不會套用至新表格。