文档主页
MySQL 9.0 参考手册
相关文档 下载本手册

MySQL 9.0 参考手册  /  ...  /  INSERT 语句

15.2.7 INSERT 语句

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [(col_name [, col_name] ...)]
    { {VALUES | VALUE} (value_list) [, (value_list)] ... }
    [AS row_alias[(col_alias [, col_alias] ...)]]
    [ON DUPLICATE KEY UPDATE assignment_list]

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    SET assignment_list
    [AS row_alias[(col_alias [, col_alias] ...)]]
    [ON DUPLICATE KEY UPDATE assignment_list]

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 将新行插入到现有表中。INSERT ... VALUESINSERT ... VALUES ROW()INSERT ... SET 形式的语句根据显式指定的值插入行。INSERT ... SELECT 形式插入从另一个或多个表中选择的行。您还可以使用 INSERT ... TABLE 从单个表中插入行。带有 ON DUPLICATE KEY UPDATE 子句的 INSERT 可以在要插入的行会导致 UNIQUE 索引或 PRIMARY KEY 中出现重复值时更新现有行。可以使用带有 ON DUPLICATE KEY UPDATE 的行别名以及一个或多个可选的列别名来引用要插入的行。

有关 INSERT ... SELECTINSERT ... ON DUPLICATE KEY UPDATE 的更多信息,请参阅 第 15.2.7.1 节 “INSERT ... SELECT 语句”第 15.2.7.2 节 “INSERT ... ON DUPLICATE KEY UPDATE 语句”

在 MySQL 9.0 中,服务器接受但会忽略 DELAYED 关键字。有关其原因,请参阅 第 15.2.7.3 节 “INSERT DELAYED 语句”

插入表需要对该表的 INSERT 权限。如果使用 ON DUPLICATE KEY UPDATE 子句,并且重复键导致执行 UPDATE 操作,则该语句需要对要更新的列具有 UPDATE 权限。对于读取但未修改的列,您只需要 SELECT 权限(例如,对于仅在 ON DUPLICATE KEY UPDATE 子句中的 col_name=expr 赋值的右侧引用的列)。

将数据插入分区表时,您可以控制哪些分区和子分区接受新行。PARTITION 子句采用表的逗号分隔的一个或多个分区或子分区(或两者)的名称列表。如果任何要由给定 INSERT 语句插入的行与列出的分区不匹配,则 INSERT 语句将失败,并显示错误消息 找到与给定分区集不匹配的行。有关更多信息和示例,请参阅 第 26.5 节 “分区选择”

tbl_name 是要将行插入其中的表。指定语句为其提供值的列,如下所示

  • 在表名后面提供用括号括起来的逗号分隔的列名列表。在这种情况下,必须由 VALUES 列表、VALUES ROW() 列表或 SELECT 语句为每个命名的列提供一个值。对于 INSERT TABLE 形式,源表中的列数必须与要插入的列数匹配。

  • 如果未为 INSERT ... VALUESINSERT ... SELECT 指定列名列表,则必须由 VALUES 列表、SELECT 语句或 TABLE 语句为表中的每个列提供值。如果不知道表中列的顺序,请使用 DESCRIBE tbl_name 查找。

  • SET 子句通过名称显式地指示列,以及要分配给每个列的值。

列值可以通过以下几种方式给出

  • 如果未启用严格 SQL 模式,则任何未显式赋予值的列都将设置为其默认值(显式或隐式)。例如,如果指定的列列表未命名表中的所有列,则未命名的列将设置为其默认值。默认值赋值在 第 13.6 节 “数据类型默认值” 中进行了描述。

    如果启用了严格 SQL 模式,则如果 INSERT 语句没有为每个没有默认值的列指定显式值,则会生成错误。请参阅 第 7.1.11 节 “服务器 SQL 模式”

  • 如果列列表和 VALUES 列表都为空,则 INSERT 将创建一行,其中每列都设置为其默认值

    INSERT INTO tbl_name () VALUES();

    如果未启用严格模式,则 MySQL 会为任何没有显式定义默认值的列使用隐式默认值。如果启用了严格模式,则如果任何列没有默认值,则会发生错误。

  • 使用关键字 DEFAULT 将列显式设置为其默认值。这使得编写 INSERT 语句更容易,这些语句为除少数列之外的所有列赋值,因为它使您能够避免编写不完整的 VALUES 列表,该列表不包含表中每个列的值。否则,您必须提供与 VALUES 列表中的每个值相对应的列名列表。

  • 如果显式插入生成列,则唯一允许的值是 DEFAULT。有关生成列的信息,请参阅 第 15.1.20.8 节 “CREATE TABLE 和生成列”

  • 在表达式中,可以使用 DEFAULT(col_name) 生成列 col_name 的默认值。

  • 如果表达式数据类型与列数据类型不匹配,则可能会发生提供列值的表达式 expr 的类型转换。根据列类型的不同,给定值的转换可能会导致不同的插入值。例如,将字符串 '1999.0e-2' 插入 INTFLOATDECIMAL(10,6)YEAR 列将分别插入值 199919.992119.9921001999。存储在 INTYEAR 列中的值是 1999,因为字符串到数字的转换只查看字符串初始部分中可以被视为有效整数或年份的部分。对于 FLOATDECIMAL 列,字符串到数字的转换将整个字符串视为有效的数值。

  • 表达式 expr 可以引用值列表中先前设置的任何列。例如,您可以这样做,因为 col2 的值引用了先前已分配的 col1

    INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);

    但以下内容不合法,因为 col1 的值引用了在 col1 之后分配的 col2

    INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);

    包含 AUTO_INCREMENT 值的列会出现异常。因为 AUTO_INCREMENT 值是在其他值赋值之后生成的,所以对赋值中 AUTO_INCREMENT 列的任何引用都会返回 0

使用 VALUES 语法的 INSERT 语句可以插入多行。为此,请包含多个逗号分隔的列值列表,每个列表用括号括起来,并用逗号分隔。示例:

INSERT INTO tbl_name (a,b,c)
    VALUES(1,2,3), (4,5,6), (7,8,9);

每个值列表必须包含与每行要插入的值完全相同数量的值。以下语句无效,因为它包含一个 9 个值的列表,而不是三个 3 个值的列表

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3,4,5,6,7,8,9);

在这种情况下,VALUEVALUES 的同义词。两者都不暗示值列表的数量,也不暗示每个列表的值的数量。无论是一个值列表还是多个值列表,也无论每个列表的值的数量是多少,都可以使用它们。

使用 VALUES ROW() 语法的 INSERT 语句也可以插入多行。在这种情况下,每个值列表都必须包含在 ROW()(行构造函数)中,如下所示

INSERT INTO tbl_name (a,b,c)
    VALUES ROW(1,2,3), ROW(4,5,6), ROW(7,8,9);

可以使用 ROW_COUNT() SQL 函数或 mysql_affected_rows() C API 函数获取 INSERT 的受影响行数。请参阅 第 14.15 节 “信息函数”mysql_affected_rows()

如果对多个值列表使用 INSERT ... VALUESINSERT ... VALUES ROW(),或者使用 INSERT ... SELECTINSERT ... TABLE,则该语句将返回以下格式的信息字符串

Records: N1 Duplicates: N2 Warnings: N3

如果使用的是 C API,则可以通过调用 mysql_info() 函数来获取信息字符串。请参阅 mysql_info()

Records 指示语句处理的行数。(这不一定是实际插入的行数,因为 Duplicates 可能不为零。)Duplicates 指示由于会重复某些现有唯一索引值而无法插入的行数。Warnings 指示尝试插入在某种程度上存在问题的列值的次数。警告可能在以下任何情况下发生

  • NULL 插入已声明为 NOT NULL 的列中。对于多行 INSERT 语句或 INSERT INTO ... SELECT 语句,该列将设置为列数据类型的隐式默认值。对于数字类型,该值为 0;对于字符串类型,该值为 ''(空字符串);对于日期和时间类型,该值为 值。INSERT INTO ... SELECT 语句的处理方式与多行插入相同,因为服务器不会检查 SELECT 的结果集,以查看它是否返回单行。(对于单行 INSERT,当将 NULL 插入 NOT NULL 列时,不会发生警告。相反,该语句将失败并显示错误消息。)

  • 将数字列设置为超出列范围的值。该值将被截断为该范围最接近的端点。

  • 将诸如 '10.34 a' 的值分配给数值列。尾随的非数字文本将被删除,并插入剩余的数字部分。如果字符串值没有前导数字部分,则该列将设置为 0

  • 将字符串插入到字符串列(CHARVARCHARTEXTBLOB)中,该字符串的长度超过了列的最大长度。该值将被截断为列的最大长度。

  • 将对于数据类型非法的日期或时间值插入日期或时间列。该列将设置为该类型的相应零值。

  • 有关涉及 AUTO_INCREMENT 列值的 INSERT 示例,请参阅 “第 5.6.9 节“使用 AUTO_INCREMENT””

    如果 INSERT 将一行插入到具有 AUTO_INCREMENT 列的表中,则可以使用 LAST_INSERT_ID() SQL 函数或 mysql_insert_id() C API 函数查找用于该列的值。

    注意

    这两个函数的行为并不总是相同的。有关 INSERT 语句相对于 AUTO_INCREMENT 列的行为的更多讨论,请参阅 “第 14.15 节“信息函数””mysql_insert_id()

INSERT 语句支持以下修饰符

  • 如果使用 LOW_PRIORITY 修饰符,则 INSERT 的执行将被延迟,直到没有其他客户端从表中读取数据为止。这包括在现有客户端读取数据时以及在 INSERT LOW_PRIORITY 语句等待时开始读取数据的其他客户端。因此,发出 INSERT LOW_PRIORITY 语句的客户端可能会等待很长时间。

    LOW_PRIORITY 仅影响使用表级锁定的存储引擎(例如 MyISAMMEMORYMERGE)。

    注意

    通常不应将 LOW_PRIORITYMyISAM 表一起使用,因为这样做会禁用并发插入。请参阅 “第 10.11.3 节“并发插入””

  • 如果指定 HIGH_PRIORITY,则如果服务器是在 --low-priority-updates 选项下启动的,它将覆盖该选项的效果。它还会导致不使用并发插入。请参阅 “第 10.11.3 节“并发插入””

    HIGH_PRIORITY 仅影响使用表级锁定的存储引擎(例如 MyISAMMEMORYMERGE)。

  • 如果使用 IGNORE 修饰符,则在执行 INSERT 语句时发生的可以忽略的错误将被忽略。例如,如果没有 IGNORE,则与表中现有的 UNIQUE 索引或 PRIMARY KEY 值重复的行会导致重复键错误,并且该语句将被中止。使用 IGNORE 时,该行将被丢弃,并且不会发生错误。被忽略的错误会生成警告。

    IGNORE 对插入到找不到与给定值匹配的分区的已分区表中具有类似的效果。如果没有 IGNORE,则此类 INSERT 语句将被中止并显示错误。使用 INSERT IGNORE 时,对于包含不匹配值的行,插入操作将静默失败,但会插入匹配的行。有关示例,请参阅 “第 26.2.2 节“LIST 分区””

    如果未指定 IGNORE,则会导致错误的数据转换将中止该语句。使用 IGNORE 时,无效值将调整为最接近的值并插入;会生成警告,但该语句不会中止。您可以使用 mysql_info() C API 函数确定实际插入到表中的行数。

    有关更多信息,请参阅 “IGNORE 对语句执行的影响”

    可以使用 REPLACE 代替 INSERT 来覆盖旧行。REPLACE 在处理包含与旧行重复的唯一键值的新行方面与 INSERT IGNORE 相对应:新行将替换旧行,而不是被丢弃。请参阅 “第 15.2.12 节“REPLACE 语句””

  • 如果指定 ON DUPLICATE KEY UPDATE,并且插入的行会在 UNIQUE 索引或 PRIMARY KEY 中导致重复值,则会对旧行执行 UPDATE。如果该行作为新行插入,则每行的 affected-rows 值为 1;如果更新了现有行,则为 2;如果将现有行设置为其当前值,则为 0。如果在连接到 mysqld 时为 mysql_real_connect() C API 函数指定 CLIENT_FOUND_ROWS 标志,则如果将现有行设置为其当前值,则 affected-rows 值为 1(而不是 0)。请参阅 “第 15.2.7.2 节“INSERT ... ON DUPLICATE KEY UPDATE 语句””

  • INSERT DELAYED 在 MySQL 5.6 中已弃用,并计划最终删除。在 MySQL 9.0 中,DELAYED 修饰符被接受但被忽略。请改用 INSERT(不带 DELAYED)。请参阅 “第 15.2.7.3 节“INSERT DELAYED 语句””