Documentation Home
MySQL 8.0 参考手册  / 第 13 章 SQL 语句  / 13.2 数据操作语句  / 13.2.6 插入语句  /  13.2.6.1 INSERT ... SELECT 语句

13.2.6.1 INSERT ... SELECT 语句

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;

从 MySQL 8.0.19 开始,您可以使用 TABLE语句代替 SELECT,如下所示:

INSERT INTO ta TABLE tb;

TABLE tb相当于SELECT * FROM tb. 当将源表中的所有列插入到目标表中并且不需要使用 WHERE 进行过滤时,它会很有用。此外, TABLE可以使用 对来自的行按一列或多列进行排序ORDER BY,并且可以使用LIMIT 子句限制插入的行数。有关详细信息,请参阅第 13.2.12 节,“TABLE 语句”

以下条件适用于 INSERT ... SELECT语句,并且,除非另有说明,否则 INSERT ... TABLE适用:

  • 指定IGNORE忽略会导致重复键违规的行。

  • 语句的目标表 INSERT可能出现在查询部分的FROM子句中, 也可能SELECT是 命名的表TABLE。但是,您不能在子查询中插入表并从同一个表中进行选择。

    当从同一个表中进行选择和插入时,MySQL 创建一个内部临时表来保存来自的行SELECT,然后将这些行插入到目标表中。但是,您不能使用 INSERT INTO t ... SELECT ... FROM twhen tis a TEMPORARY table,因为TEMPORARY不能在同一语句中引用两次表。出于同样的原因,您不能使用INSERT INTO t ... TABLE twhent是临时表。请参阅第 8.4.4 节,“MySQL 中的内部临时表使用”第 B.3.6.2 节,“临时表问题”

  • AUTO_INCREMENT专栏照常工作。

  • 为确保二进制日志可用于重新创建原始表,MySQL 不允许并发插入INSERT ... SELECTorINSERT ... TABLE 语句(请参阅第 8.11.3 节,“并发插入”)。

  • 为避免在 SELECTINSERT引用同一个表时出现不明确的列引用问题,请为该部分中使用的每个表提供唯一的别名 SELECT,并使用适当的别名限定该部分中的列名。

    TABLE语句不支持别名。

您可以明确选择源表或目标表(或两者)的哪些分区或子分区(或两者)将与PARTITION表名后面的子句一起使用。当PARTITION与语句部分中的源表名称一起使用时, SELECT仅从分区列表中指定的分区或子分区中选择行。当PARTITION 与语句部分的目标表的名称一起使用时 INSERT,必须能够将所有选定的行插入到选项后面的分区列表中指定的分区或子分区中。否则,INSERT ... SELECT声明失败。有关详细信息和示例,请参阅第 24.5 节,“分区选择”

TABLE不支持 PARTITION子句。

对于INSERT ... SELECT语句,请参阅 第 13.2.6.2 节,“INSERT ... ON DUPLICATE KEY UPDATE 语句”SELECT ,了解可以在ON DUPLICATE KEY UPDATE 子句中引用列的条件。这也适用于INSERT ... TABLE.

没有 子句的SELECTor 语句返回行 的顺序是不确定的。这意味着,当使用复制时,无法保证这样的 返回行在源和副本上以相同的顺序返回,这可能导致它们之间的不一致。为防止发生这种情况,请始终使用在源和副本上生成相同行顺序的子句来编写或 复制要复制的语句。另见第 17.5.1.18 节,“复制和限制”TABLEORDER BYSELECTINSERT ... SELECTINSERT ... TABLEORDER BY

由于这个问题, INSERT ... SELECT ON DUPLICATE KEY UPDATE语句 INSERT IGNORE ... SELECT被标记为对基于语句的复制不安全。使用基于语句的模式时,此类语句会在错误日志中产生警告,并在使用模式时使用基于行的格式写入二进制日志 MIXED。(缺陷 #11758262,缺陷 #50439)

另见第 17.2.1.1 节,“基于语句和基于行的复制的优点和缺点”