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


MySQL 8.4 参考手册  /  ...  /  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 8.4 中,服务器接受但会忽略 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 8.4 中,DELAYED 修饰符会被接受,但会被忽略。请改用 INSERT(不带 DELAYED)。请参阅 第 15.2.7.3 节 “INSERT DELAYED 语句”