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 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 ... 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 9.0 中,DELAYED
修饰符被接受但被忽略。请改用INSERT
(不带DELAYED
)。请参阅 “第 15.2.7.3 节“INSERT DELAYED 语句””。