You can create one table from another by adding a 通过在SELECT
statement at the end of the CREATE TABLE
statement:CREATE TABLE
语句末尾添加SELECT
语句,可以根据一个表创建另一个表:
CREATE TABLEnew_tbl
[AS] SELECT * FROMorig_tbl
;
MySQL creates new columns for all elements in the MySQL为SELECT
. SELECT
中的所有元素创建新列。For example:例如:
mysql>CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
->PRIMARY KEY (a), KEY(b))
->ENGINE=InnoDB SELECT b,c FROM test2;
This creates an 这将创建一个包含三列(InnoDB
table with three columns, a
, b
, and c
. a
、b
和c
)的InnoDB
表。The ENGINE
option is part of the CREATE TABLE
statement, and should not be used following the SELECT
; this would result in a syntax error. ENGINE
选项是CREATE TABLE
语句的一部分,不应在SELECT
之后使用;这将导致语法错误。The same is true for other 其他CREATE TABLE
options such as CHARSET
.CREATE TABLE
选项(如CHARSET
)也是如此。
Notice that the columns from the 请注意,SELECT
statement are appended to the right side of the table, not overlapped onto it. SELECT
语句中的列被追加到表的右侧,而不是重叠到表的右侧。Take the following example:以以下为例:
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)
For each row in table 对于表foo
, a row is inserted in bar
with the values from foo
and default values for the new columns.foo
中的每一行,将在bar
中插入一行,其中包含来自foo
的值和新列的默认值。
In a table resulting from 在根据CREATE TABLE ... SELECT
, columns named only in the CREATE TABLE
part come first. CREATE TABLE ... SELECT
产生的表中,仅在CREATE TABLE
部分中命名的列优先。Columns named in both parts or only in the 在这两个部分中命名的列或仅在SELECT
part come after that. SELECT
部分中命名的列位于该部分之后。The data type of 还可以通过在SELECT
columns can be overridden by also specifying the column in the CREATE TABLE
part.CREATE TABLE
部分中指定列来覆盖SELECT
列的数据类型。
If errors occur while copying data to the table, the table is automatically dropped and not created. 如果将数据复制到表时出错,则会自动删除该表,而不会创建该表。However, prior to MySQL 8.0.21, when row-based replication is in use, a 然而,在MySQL 8.0.21之前,当使用基于行的复制时,CREATE TABLE ... SELECT
statement is recorded in the binary log as two transactions, one to create the table, and the other to insert data. CREATE TABLE ... SELECT
语句作为两个事务记录在二进制日志中,一个用于创建表,另一个用于插入数据。When the statement applied from the binary log, a failure between the two transactions or while copying data can result in replication of an empty table. 当从二进制日志应用该语句时,两个事务之间的故障或复制数据时的故障可能会导致复制空表。That limitation is removed in MySQL 8.0.21. MySQL 8.0.21中删除了该限制。On storage engines that support atomic DDL, 在支持原子DDL的存储引擎上,现在在使用基于行的复制时,CREATE TABLE ... SELECT
is now recorded and applied as one transaction when row-based replication is in use. CREATE TABLE ... SELECT
被记录并作为一个事务应用。For more information, see Section 13.1.1, “Atomic Data Definition Statement Support”.有关更多信息,请参阅第13.1.1节,“原子数据定义语句支持”。
As of MySQL 8.0.21, on storage engines that support both atomic DDL and foreign key constraints, creation of foreign keys is not permitted in 从MySQL 8.0.21开始,在支持原子DDL和外键约束的存储引擎上,在使用基于行的复制时,CREATE TABLE ... SELECT
statements when row-based replication is in use. CREATE TABLE ... SELECT
语句中不允许创建外键。Foreign key constraints can be added later using 以后可以使用ALTER TABLE
.ALTER TABLE
添加外键约束。
You can precede the 可以在SELECT
by IGNORE
or REPLACE
to indicate how to handle rows that duplicate unique key values. SELECT
之前加IGNORE
或REPLACE
以指示如何处理重复唯一键值的行。With 使用IGNORE
, rows that duplicate an existing row on a unique key value are discarded. IGNORE
,将丢弃在唯一键值上与现有行重复的行。With 使用REPLACE
, new rows replace rows that have the same unique key value. REPLACE
,新行替换具有相同唯一键值的行。If neither 如果未指定IGNORE
nor REPLACE
is specified, duplicate unique key values result in an error. IGNORE
或REPLACE
,则重复的唯一键值将导致错误。For more information, see The Effect of IGNORE on Statement Execution.有关更多信息,请参阅IGNORE对语句执行的影响。
In MySQL 8.0.19 and later, you can also use a 在MySQL 8.0.19及更高版本中,还可以在VALUES
statement in the SELECT
part of CREATE TABLE ... SELECT
; the VALUES
portion of the statement must include a table alias using an AS
clause. CREATE TABLE ... SELECT
的SELECT
部分使用VALUES
语句;语句的VALUES
部分必须包含使用AS
子句的表别名。To name the columns coming from 要命名来自VALUES
, supply column aliases with the table alias; otherwise, the default column names column_0
, column_1
, column_2
, ..., are used.VALUES
的列,请提供带有表别名的列别名;否则,将使用默认列名column_0
、column_1
、column_2
……
Otherwise, naming of columns in the table thus created follows the same rules as described previously in this section. 否则,在这样创建的表中,列的命名将遵循本节前面描述的相同规则。Examples:示例:
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 | column_0 | column_1 | column_2 | +------+------+------+----------+----------+----------+ | 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 | +------+------+------+
When selecting all columns and using the default column names, you can omit 选择所有列并使用默认列名时,可以省略SELECT *
, so the statement just used to create table tv1
can also be written as shown here: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 | +----------+----------+----------+
When using 当使用VALUES
as the source of the SELECT
, all columns are always selected into the new table, and individual columns cannot be selected as they can be when selecting from a named table; each of the following statements produces an error (ER_OPERAND_COLUMNS
):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);
Similarly, you can use a 类似地,您可以使用TABLE
statement in place of the SELECT
. TABLE
语句代替SELECT
。This follows the same rules as with 这遵循与VALUES
; all columns of the source table and their names in the source table are always inserted into the new table. VALUES
相同的规则;源表的所有列及其在源表中的名称始终插入到新表中。Examples:
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 | +------+----+----+
Because the ordering of the rows in the underlying 由于无法始终确定基础SELECT
statements cannot always be determined, CREATE TABLE ... IGNORE SELECT
and CREATE TABLE ... REPLACE SELECT
statements are flagged as unsafe for statement-based replication. SELECT
语句中行的顺序,CREATE TABLE ... IGNORE SELECT
和CREATE TABLE ... REPLACE SELECT
语句对于基于语句的复制被标记为不安全。Such statements produce a warning in the error log when using statement-based mode and are written to the binary log using the row-based format when using 使用基于语句的模式时,此类语句会在错误日志中生成警告,使用MIXED
mode. MIXED
模式时,此类语句会使用基于行的格式写入二进制日志。See also Section 17.2.1.1, “Advantages and Disadvantages of Statement-Based and Row-Based Replication”.另请参阅第17.2.1.1节,“基于语句和基于行的复制的优缺点”。
CREATE TABLE ... SELECT
does not automatically create any indexes for you. CREATE TABLE ... SELECT
不会自动为您创建任何索引。This is done intentionally to make the statement as flexible as possible. 这样做是为了使声明尽可能灵活。If you want to have indexes in the created table, you should specify these before the 如果希望在创建的表中具有索引,则应在SELECT
statement:SELECT
语句之前指定这些索引:
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
For 对于CREATE TABLE ... SELECT
, the destination table does not preserve information about whether columns in the selected-from table are generated columns. CREATE TABLE ... SELECT
,目标表不会保留有关“从中选择”表中的列是否为生成列的信息。The 语句的SELECT
part of the statement cannot assign values to generated columns in the destination table.SELECT
部分无法为目标表中生成的列赋值。
For 对于CREATE TABLE ... SELECT
, the destination table does preserve expression default values from the original table.CREATE TABLE ... SELECT
,目标表将保留原始表中的表达式默认值。
Some conversion of data types might occur. 可能会发生某些数据类型转换。For example, the 例如,AUTO_INCREMENT
attribute is not preserved, and VARCHAR
columns can become CHAR
columns. AUTO_INCREMENT
属性不保留,VARCHAR
列可以变成CHAR
列。Retrained attributes are 重新训练的属性为NULL
(or NOT NULL
) and, for those columns that have them, CHARACTER SET
, COLLATION
, COMMENT
, and the DEFAULT
clause.NULL
(或NOT NULL
),对于包含这些属性的列,包括CHARACTER SET
、COLLATION
、COMMENT
和DEFAULT
子句。
When creating a table with 使用CREATE TABLE ... SELECT
, make sure to alias any function calls or expressions in the query. CREATE TABLE ... SELECT
创建表时,请确保为查询中的任何函数调用或表达式添加别名。If you do not, the 否则,CREATE
statement might fail or result in undesirable column names.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;
You can also explicitly specify the data type for a column in the created table:还可以在创建的表中显式指定列的数据类型:
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
For 对于CREATE TABLE ... SELECT
, if IF NOT EXISTS
is given and the target table exists, nothing is inserted into the destination table, and the statement is not logged.CREATE TABLE ... SELECT
,如果给定IF NOT EXISTS
且目标表存在,则不向目标表中插入任何内容,并且不记录该语句。
To ensure that the binary log can be used to re-create the original tables, MySQL does not permit concurrent inserts during 为了确保二进制日志可以用于重新创建原始表,MySQL不允许在CREATE TABLE ... SELECT
. CREATE TABLE ... SELECT
期间并发插入。However, prior to MySQL 8.0.21, when a 但是,在MySQL 8.0.21之前,当从二进制日志中应用CREATE TABLE ... SELECT
operation is applied from the binary log when row-based replication is in use, concurrent inserts are permitted on the replicated table while copying data. CREATE TABLE ... SELECT
操作时,当使用基于行的复制时,复制数据时允许在复制的表上进行并发插入。That limitation is removed in MySQL 8.0.21 on storage engines that support atomic DDL. MySQL 8.0.21在支持原子DDL的存储引擎上消除了这一限制。For more information, see Section 13.1.1, “Atomic Data Definition Statement Support”.有关更多信息,请参阅第13.1.1节,“原子数据定义语句支持”。
You cannot use 在诸如FOR UPDATE
as part of the SELECT
in a statement such as CREATE TABLE
. new_table
SELECT ... FROM old_table
...CREATE TABLE
这样的语句中,你不能将new_table
SELECT ... FROM old_table
...FOR UPDATE
用作SELECT
的一部分。If you attempt to do so, the statement fails.如果尝试执行此操作,则语句将失败。
CREATE TABLE ... SELECT
operations apply ENGINE_ATTRIBUTE
and SECONDARY_ENGINE_ATTRIBUTE
values to columns only. CREATE TABLE ... SELECT
操作只将ENGINE_ATTRIBUTE
值和SECONDARY_ENGINE_ATTRIBUTE
值应用于列。Table and index 表和索引ENGINE_ATTRIBUTE
and SECONDARY_ENGINE_ATTRIBUTE
values are not applied to the new table unless specified explicitly.ENGINE_ATTRIBUTE
值和SECONDARY_ENGINE_ATTRIBUTE
值没有应用于新表,除非显式指定。