Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

15.2.7 插入语句

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] ...

插入 将新行插入到现有表中。该语句的 插入 ... 值插入 ... 值行()插入 ... 设置 形式基于明确指定的值插入行。该语句的 插入 ... 选择 形式从另一个表或多个表中选择行插入。您也可以使用 插入 ... 表 从单个表中插入行。插入 带有 ON DUPLICATE KEY UPDATE 子句可以在插入行时更新现有行,如果插入的行将导致唯一索引或主键中的重复值。使用 ON DUPLICATE KEY UPDATE 时,可以使用行别名和一个或多个可选的列别名来引用要插入的行。

有关 插入 ... 选择插入 ... ON DUPLICATE KEY UPDATE 的更多信息,请参见 第 15.2.7.1 节,“插入 ... 选择语句”第 15.2.7.2 节,“插入 ... ON DUPLICATE KEY UPDATE 语句”

在 MySQL 8.3 中,DELAYED 关键字被服务器接受但忽略。有关此原因的信息,请参见 第 15.2.7.3 节,“插入 DELAYED 语句”

将数据插入表中需要该表的 插入 权限。如果使用 ON DUPLICATE KEY UPDATE 子句并且重复键导致更新操作,而不是插入操作,则该语句需要更新的列的 更新 权限。对于只读取但不修改的列,您只需要 选择 权限(例如,在 ON DUPLICATE KEY UPDATE 子句中右侧的列赋值中使用的列)。

当插入分区表时,可以控制哪些分区和子分区接受新行。PARTITION 子句采用一个或多个分区或子分区(或两者)的逗号分隔名称列表。如果插入语句中的任何行不匹配列表中的分区,则插入语句将失败,错误信息为 Found a row not matching the given partition set。有关更多信息和示例,请参见 第 26.5 节,“Partition Selection”

tbl_name 是要插入行的表。指定语句提供值的列如下所示:

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

  • 如果您不指定INSERT ... VALUESINSERT ... SELECT的列名列表,则必须通过VALUES列表、SELECT语句或TABLE语句提供每个表中的所有列的值。如果您不知道表中的列顺序,可以使用DESCRIBE tbl_name来查找。

  • 一个SET子句通过名称明确指定列,并指定每个列的值。

列值可以通过多种方式提供:

  • 如果严格的 SQL 模式未启用,那么任何未明确指定值的列将设置为其默认值(显式或隐式)。例如,如果您指定了一个不包括所有表列的列名列表,那么未命名的列将设置为其默认值。默认值分配在第 13.6 节,“数据类型默认值”中描述。见 also 第 1.6.3.3 节,“强制约束无效数据”

    如果严格的 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 的值引用了之后分配的 col2

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

    对于包含 AUTO_INCREMENT 值的列,存在一个例外。因为 AUTO_INCREMENT 值是在其他值分配后生成的,因此对 AUTO_INCREMENT 列的任何引用在分配时返回 0

INSERT 语句使用 VALUES 语法可以插入多行。要做到这一点,包括多个以逗号分隔的列值列表,以括号括起来并以逗号分隔。示例:

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

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

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

VALUEVALUES 在此上下文中的同义词。无论是单个值列表还是多个列表,两者都可以使用,不管每个列表中的值数量如何。

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

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

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

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

Records: N1 Duplicates: N2 Warnings: N3

如果您使用 C API,可以通过调用 mysql_info() 函数获取信息字符串。见 mysql_info()

记录 表示语句处理的行数。(这并不一定是实际插入的行数,因为 重复项 可能不为零。) 重复项 表示由于唯一索引值而无法插入的行数。 警告 表示尝试插入列值时出现问题的次数。警告可能在以下情况下出现:

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

  • 将数字列设置为超出该列范围的值。该值将被剪辑到范围的最近端点。

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

  • 将字符串插入到字符串列 (CHAR, VARCHAR, TEXT, 或 BLOB) 超过该列的最大长度。该值将被截断到该列的最大长度。

  • 将值插入到日期或时间列中,该值对于该数据类型是非法的。该列将被设置为该类型的零值。

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

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

    Note

    这两个函数并不总是表现相同。INSERT 语句关于 AUTO_INCREMENT 列的行为在 第 14.15 节,“信息函数”mysql_insert_id() 中进一步讨论。

INSERT 语句支持以下修饰符:

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

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

    Note

    LOW_PRIORITY 通常不应该与 MyISAM 表一起使用,因为这样做会禁用并发插入。见 第 10.11.3 节,“并发插入”

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

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

  • 如果使用 IGNORE 修饰符,在执行 INSERT 语句时忽略错误。例如,without IGNORE,重复的唯一索引或 PRIMARY KEY 值将导致 duplicate-key 错误并中止语句。使用 IGNORE,行将被丢弃,不会发生错误。忽略的错误将生成警告。

    IGNORE 对分区表的插入也具有相似效果,在找不到匹配的分区时。without IGNORE,这样的 INSERT 语句将中止并报错。当使用 INSERT IGNORE 时,对于包含不匹配值的行,插入操作将静默失败,但将插入匹配的行。例如,见 第 26.2.2 节,“LIST 分区”

    数据转换可能会触发错误,中止语句,如果不指定 IGNORE。使用 IGNORE,无效值将被调整为最近的值并插入;警告将被生成,但语句不会中止。你可以使用 mysql_info() C API 函数来确定实际插入到表中的行数。

    更多信息,见 IGNORE 对语句执行的影响

    你可以使用 REPLACE 而不是 INSERT 来覆盖旧行。 REPLACEINSERT IGNORE 的对应项,在处理包含唯一键值的新行时:新行将替换旧行,而不是被丢弃。见 第 15.2.12 节,“REPLACE 语句”

  • 如果你指定 ON DUPLICATE KEY UPDATE,并且插入的行将导致唯一索引或 PRIMARY KEY 的重复值,旧行将被更新。受影响的行数值为 1 如果行被插入为新行,2 如果旧行被更新,0 如果旧行被设置为当前值。如果你在连接到 mysqld 时指定了 CLIENT_FOUND_ROWS 标志到 mysql_real_connect() C API 函数,受影响的行数值为 1(不是 0),如果旧行被设置为当前值。见 第 15.2.7.2 节,“INSERT ... ON DUPLICATE KEY UPDATE 语句”

  • INSERT DELAYED 在 MySQL 5.6 中已弃用,并计划在将来删除。在 MySQL 8.3 中,DELAYED 修饰符将被接受但忽略。使用 INSERT(不带 DELAYED)代替。见 第 15.2.7.3 节,“INSERT DELAYED 语句”