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 ... VALUES
或INSERT ... 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'
插入到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
的值引用了之后分配的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);
VALUE
是 VALUES
在此上下文中的同义词。无论是单个值列表还是多个列表,两者都可以使用,不管每个列表中的值数量如何。
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 ... VALUES
或 INSERT ... VALUES ROW()
多个值列表,或者 INSERT ... SELECT
或 INSERT ... 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
,当插入NULL
到NOT 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
只影响使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。NoteLOW_PRIORITY
通常不应该与MyISAM
表一起使用,因为这样做会禁用并发插入。见 第 10.11.3 节,“并发插入”。 -
如果指定
HIGH_PRIORITY
,它将覆盖--low-priority-updates
选项的效果,如果服务器以该选项启动。它还会导致并发插入不被使用。见 第 10.11.3 节,“并发插入”。HIGH_PRIORITY
只影响使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。 -
如果使用
IGNORE
修饰符,在执行INSERT
语句时忽略错误。例如,withoutIGNORE
,重复的唯一索引或PRIMARY KEY
值将导致 duplicate-key 错误并中止语句。使用IGNORE
,行将被丢弃,不会发生错误。忽略的错误将生成警告。IGNORE
对分区表的插入也具有相似效果,在找不到匹配的分区时。withoutIGNORE
,这样的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
,并且插入的行将导致唯一索引或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 语句”。