15.2.7.1 插入...选择语句
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
{ SELECT ...
| TABLE table_name
| VALUES row_constructor_list
}
[ON DUPLICATE KEY UPDATE assignment_list]
value:
{expr | DEFAULT}
value_list:
value [, value] ...
row_constructor_list:
ROW(value_list)[, ROW(value_list)][, ...]
assignment:
col_name =
value
| [row_alias.]col_name
| [tbl_name.]col_name
| [row_alias.]col_alias
assignment_list:
assignment [, assignment] ...
使用INSERT ... SELECT
,可以快速将多行插入到表中,从SELECT
语句的结果中,该语句可以从一个或多个表中选择。例如:
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
INSERT INTO ta TABLE tb;
TABLE tb
等同于 SELECT * FROM tb
。它可以在不需要 WHERE 子句进行过滤时,插入源表中的所有列到目标表中。此外,来自TABLE
的行可以使用 ORDER BY
子句对其进行排序,并且可以使用 LIMIT
子句来限制插入的行数。更多信息,请见第15.2.16节,“TABLE 语句”。
以下条件适用于INSERT ... SELECT
语句,以及,除非特别注明外,对于INSERT ... TABLE
也适用:
-
指定
IGNORE
忽略将导致重复键违规的行。 -
INSERT 语句的目标表可能出现在查询中的
FROM
子句中,或者作为由TABLE
指定的表名。然而,您不能在子查询中插入到一个表并从同一个表中选择数据。当您从同一个表中选择数据并将其插入到目标表时,MySQL 会创建一个内部临时表来存储来自
SELECT
的行,然后将这些行插入到目标表中。然而,您不能使用INSERT INTO t ... SELECT ... FROM t
当t
是一个临时表,因为临时表不能在同一语句中被引用两次。同样,您也不能使用INSERT INTO t ... TABLE t
当t
是一个临时表。请参阅第10.4.4节,“MySQL内部临时表使用”和第B.3.6.2节,“TEMPORARY表问题”。 -
AUTO_INCREMENT
列工作正常。 -
为了确保可以使用二进制日志来重建原始表,MySQL 不允许对
INSERT ... SELECT
或INSERT ... TABLE
语句进行并发插入(见第10.11.3节,“并发插入”)。 -
为了避免在SELECT和INSERT语句中出现ambiguous column reference问题,当SELECT和INSERT语句引用同一表时,提供每个表在SELECT部分的唯一别名,并在该部分使用适当别名来限定列名。
TABLE语句不支持别名。
您可以使用 PARTITION
子句,明确选择源或目标表(或两者)的某些分区或子分区。对于在 SELECT
语句中使用 PARTITION
的源表名,仅选择来自于其分区列表中的分区或子分区。对于在 INSERT
语句中使用 PARTITION
的目标表名,必须能够将所有选择的行插入到分区列表中的分区或子分区中。否则,INSERT ... SELECT
语句失败。更多信息和示例,请见 第26.5节,“分区选择”。
TABLE
不支持 PARTITION
子句。
对于 INSERT ... SELECT
语句,请见 第15.2.7.2节,“INSERT ... ON DUPLICATE KEY UPDATE Statement”,了解在何种情况下可以在 ON DUPLICATE KEY UPDATE
子句中引用 SELECT
列。同样适用于 INSERT ... TABLE
。
没有使用ORDER BY
子句的SELECT
或TABLE
语句的执行顺序是非确定性的。这意味着,在使用复制时,没有保证在源服务器和副本服务器上该语句返回行的相同顺序,这可能会导致它们之间的不一致。为了防止这种情况发生,总是使用ORDER BY
子句来生产源服务器和副本服务器上的行顺序相同的INSERT ... SELECT
或INSERT ... TABLE
语句。请参见第19.5.1.18节,“复制和LIMIT”.
由于这个问题,INSERT ... SELECT ON DUPLICATE KEY UPDATE
和INSERT IGNORE ... SELECT
语句被标记为不安全的语句,用于语句-基于复制。这些语句在使用语句-基于模式时会在错误日志中产生警告,并且在使用MIXED
模式时将其写入到二进制日志中,以行-基于格式。(Bug #11758262, Bug #50439)