文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  INSERT ... SELECT 语句

15.2.7.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;

TABLE 语句代替 SELECT,如下所示

INSERT INTO ta TABLE tb;

TABLE tb 等效于 SELECT * FROM tb。当将源表中的所有列插入到目标表中,并且不需要使用 WHERE 进行过滤时,这很有用。此外,可以使用 ORDER BY 对 TABLE 中的行进行排序,并且可以使用 LIMIT 子句限制插入的行数。有关更多信息,请参见 第 15.2.16 节,“TABLE 语句”.

以下条件适用于 INSERT ... SELECT 语句,并且除了特别说明外,也适用于 INSERT ... TABLE。

  • 指定 IGNORE 以忽略会导致重复键冲突的行。

  • 在 INSERT 语句中,目标表可以出现在 SELECT 部分的 FROM 子句中,或者作为 TABLE 命名的表。但是,您不能在一个子查询中插入到一个表中并从同一个表中选择数据。

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

  • AUTO_INCREMENT 列按预期工作。

  • 为了确保二进制日志可以用来重新创建原始表,MySQL 不允许对 INSERT ... SELECT 或 INSERT ... TABLE 语句进行并发插入(请参阅 第 10.11.3 节,“并发插入”)。

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

    TABLE 语句不支持别名。

您可以使用 PARTITION 子句,该子句紧随表名,显式选择要使用源表或目标表(或两者)的哪些分区或子分区(或两者)。当 PARTITION 与 SELECT 部分中源表名一起使用时,仅从其分区列表中命名的分区或子分区中选择行。当 PARTITION 与 INSERT 部分中的目标表名一起使用时,必须能够将所有选定的行插入到其分区列表中命名的分区或子分区中。否则,INSERT ... SELECT 语句将失败。有关更多信息和示例,请参阅 第 26.5 节,“分区选择”。

TABLE 不支持 PARTITION 子句。

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

没有 ORDER BY 子句的 SELECT 或 TABLE 语句返回行的顺序是不确定的。这意味着,当使用复制时,不能保证这样的 SELECT 在源和副本上以相同的顺序返回行,这会导致它们之间不一致。为了防止这种情况发生,请始终编写要复制的 INSERT ... SELECT 或 INSERT ... TABLE 语句,使用一个 ORDER BY 子句,该子句在源和副本上产生相同的行顺序。另请参阅 第 19.5.1.18 节,“复制和 LIMIT”。

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

另请参阅 第 19.2.1.1 节,“基于语句的复制和基于行的复制的优缺点”。