文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  CREATE TABLE ... SELECT 語法

15.1.20.4 CREATE TABLE ... SELECT 語法

您可以使用在 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;

這會建立一個具有三個欄位(abc)的 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 前面加上 IGNOREREPLACE 來指示如何處理重複唯一鍵值的列。使用 IGNORE 時,會捨棄唯一鍵值與現有列重複的列。使用 REPLACE 時,新的列會取代具有相同唯一鍵值的列。如果未指定 IGNOREREPLACE,重複的唯一鍵值將會導致錯誤。有關更多資訊,請參閱 「IGNORE 對語句執行的影響」

您也可以在 CREATE TABLE ... SELECTSELECT 部分中使用 VALUES 語句;語句的 VALUES 部分必須使用 AS 子句包含表格別名。若要命名來自 VALUES 的欄位,請使用表格別名提供欄位別名;否則,會使用預設欄位名稱 column_0column_1column_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 SELECTCREATE 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 SETCOLLATIONCOMMENTDEFAULT 子句。

當使用 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_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值套用至欄位。除非明確指定,否則表格和索引的 ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值不會套用至新表格。