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 ... VALUES
、INSERT ... VALUES ROW()
和 INSERT ... SET
形式的语句根据显式指定的值插入行。INSERT ... SELECT
形式插入从另一个表或多个表中选择的行。您还可以使用 INSERT ... TABLE
从单个表中插入行。带有 ON DUPLICATE KEY UPDATE
子句的 INSERT
可以在要插入的行会导致 UNIQUE
索引或 PRIMARY KEY
中出现重复值时更新现有行。可以使用带有 ON DUPLICATE KEY UPDATE
的一个或多个可选列别名的行别名来引用要插入的行。
有关 INSERT ... SELECT
和 INSERT ... 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 ... VALUES
或INSERT ... 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'
插入INT
、FLOAT
、DECIMAL(10,6)
或YEAR
列分别插入值1999
、19.9921
、19.992100
或1999
。存储在INT
和YEAR
列中的值为1999
,因为字符串到数字的转换只查看字符串初始部分中可能被视为有效整数或年份的部分。对于FLOAT
和DECIMAL
列,字符串到数字的转换将整个字符串视为有效的数值。表达式
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);
在这种情况下,VALUE
是 VALUES
的同义词。两者都没有暗示值列表的数量,也没有暗示每个列表中的值的数量。无论是一个值列表还是多个值列表,也无论每个列表中有多少个值,都可以使用其中任何一个。
使用 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 ... VALUES
或 INSERT ... VALUES ROW()
,或使用 INSERT ... SELECT
或 INSERT ... 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
。将字符串插入到字符串列(
CHAR
、VARCHAR
、TEXT
或BLOB
)中,该字符串超过了列的最大长度。该值将被截断为列的最大长度。将一个对于数据类型非法的日期或时间值插入到日期或时间列中。该列将被设置为该类型的相应零值。
有关涉及
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
仅影响使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。注意通常不应将
LOW_PRIORITY
与MyISAM
表一起使用,因为这样做会禁用并发插入。请参阅 第 10.11.3 节 “并发插入”。如果指定
HIGH_PRIORITY
,则如果服务器使用--low-priority-updates
选项启动,它将覆盖该选项的效果。它还会导致不使用并发插入。请参阅 第 10.11.3 节 “并发插入”。HIGH_PRIORITY
仅影响使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。如果使用
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 语句”。