文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
資訊 (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  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;

這會建立一個具有三個資料行 abcInnoDB 資料表。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 部分中命名的資料行則會排在其後。SELECT 資料行的資料類型也可以透過在 CREATE TABLE 部分中同時指定該資料行來覆寫。

對於同時支援原子 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 節「原子資料定義語句支援」

您不能將 FOR UPDATE 作為 SELECT 的一部分用於類似 CREATE TABLE new_table SELECT ... FROM old_table ... 之類的語句中。如果您嘗試這樣做,語句將會失敗。

CREATE TABLE ... SELECT 作業僅將 ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值套用至資料行。除非明確指定,否則資料表和索引 ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值不會套用至新的資料表。