13.2.5.1 INSERT ... SELECT 语句
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
SELECT ...
[ON DUPLICATE KEY UPDATE assignment_list]
value:
{expr | DEFAULT}
assignment:
col_name = value
assignment_list:
assignment [, assignment] ...
使用插入...选择,您可以根据SELECT语句的结果快速向 table 中插入许多行,该语句可以从一个或多个 table 中进行选择。例如:
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
以下条件适用于插入...选择条语句:
-
指定
IGNORE
可忽略将导致重复键冲突的行。 -
INSERT语句的目标 table 可能出现在查询的SELECT部分的
FROM
子句中。但是,您不能插入 table 并在子查询中从同一 table 中选择。
从同一 table 中选择并插入到同一 table 中时,MySQL 创建一个内部临时 table 来保存SELECT中的行,然后将这些行插入目标 table 中。但是,当t
是TEMPORARY
table 时,不能使用INSERT INTO t ... SELECT ... FROM t
,因为TEMPORARY
table 不能在同一语句中被两次引用。参见第 8.4.4 节“ MySQL 中的内部临时 table 使用”和第 B.4.6.2 节,“临时 table 问题”。
-
AUTO_INCREMENT
列照常工作。 -
为了确保二进制日志可用于重新创建原始 table,MySQL 不允许并发插入插入...选择语句(请参见第 8.11.3 节“并发插入”)。
-
为了避免当SELECT和INSERT引用同一 table 时列引用存在歧义,请为SELECT部分中使用的每个 table 提供唯一的别名,并使用适当的别名来限定该部分中的列名。
您可以通过 table 名后面的PARTITION
选项显式选择要使用源 table 或目标 table(或两者)的分区或子分区(或两者)。在语句的SELECT部分中将PARTITION
与源 table 的名称一起使用时,仅从其分区列 table 中命名的分区或子分区中选择行。如果在语句的INSERT部分中将PARTITION
与目标 table 的名称一起使用,则必须可以将所有选择的行插入到该选项之后的分区列 table 中命名的分区或子分区中。否则,INSERT ... SELECT
语句将失败。有关更多信息和示例,请参见第 22.5 节“分区选择”。
对于插入...选择语句,请参见第 13.2.5.2 节“在重复密钥更新语句上插入...”以了解在ON DUPLICATE KEY UPDATE
子句中可以引用SELECT列的条件。
没有ORDER BY
子句的SELECT语句返回行的 Sequences 是不确定的。这意味着,在使用复制时,无法保证这样的SELECT返回主服务器和从服务器上的行的 Sequences 相同,这可能导致它们之间的不一致。为了防止这种情况的发生,请始终使用要在主服务器和从属服务器上产生相同行 Sequences 的ORDER BY
子句编写要复制的INSERT ... SELECT
语句。另请参见第 16.4.1.17 节,“复制和限制”。
由于此问题,对于基于语句的复制,插入...选择重复的密钥更新和插入忽略...选择语句被标记为不安全。当使用基于语句的模式时,此类语句在错误日志中产生警告,而在使用MIXED
模式时,则使用基于行的格式将其写入二进制日志。 (缺陷#11758262,缺陷#50439)
另请参见第 16.2.1.1 节,“基于语句的复制和基于行的复制的优缺点”。
INSERT ... SELECT
语句使用诸如 table 级锁之类的存储引擎来影响分区 table,该存储引擎采用 table 级锁来锁定目标 table 的所有分区。但是,只有那些实际从源 table 读取的分区才被锁定。 (对于使用诸如InnoDB之类的存储引擎并采用行级锁定的 table,不会发生这种情况。)有关更多信息,请参见第 22.6.4 节“分区和锁定”。