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)] ... |VALUES row_constructor_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] ...)] [AS row_alias[(col_alias [, col_alias] ...)]]SET assignment_list [ON DUPLICATE KEY UPDATE assignment_list]INSERT [LOW_PRIORITY |HIGH_PRIORITY ] [IGNORE ] [INTO ] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] [AS row_alias[(col_alias [, col_alias] ...)]] {SELECT ... |TABLE table_name} [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 = [row_alias.]value assignment_list: assignment [, assignment] ...
INSERT
将新行插入到现有表中。的INSERT ... VALUES
,INSERT ... VALUES ROW()
和INSERT ... SET
形式的语句插入基于明确指定的值的行。该INSERT ... SELECT
表单将插入从另一个表或多个表中选择的行。您还可以INSERT ... TABLE
在MySQL 8.0.19和更高版本中使用它来插入单个表中的行。如果要插入的行会导致索引或中的值重复INSERT
,则带有ON DUPLICATE KEY UPDATE
子句的子句可以更新现有行。在MySQL 8.0.19及更高版本中,具有一个或多个可选列别名的行别名可用于引用要插入的行。UNIQUE
PRIMARY KEY
ON DUPLICATE KEY UPDATE
有关更多信息INSERT ... SELECT
,并INSERT ... ON DUPLICATE KEY UPDATE
请参见第13.2.6.1,“INSERT ... SELECT语句”和第13.2.6.2,“INSERT ... ON DUPLICATE KEY UPDATE语句”。
在MySQL 8.0中,DELAYED
关键字被服务器接受但被服务器忽略。因此,请参见“ INSERT DELAYED语句”。
插入表需要该表的INSERT
特权。如果使用了该ON DUPLICATE KEY UPDATE
子句,而是使用重复的键导致UPDATE
执行,则该语句要求UPDATE
特权以更新列。对于已读取但未修改的列,您仅需要SELECT
特权(例如,仅在子句中col_name
=expr
赋值的右侧引用的列ON DUPLICATE KEY UPDATE
)。
当插入分区表时,您可以控制哪些分区和子分区接受新行。该PARTITION
选项采用表的一个或多个分区或子分区(或两者)的逗号分隔名称列表。如果给定INSERT
语句要插入的任何行与列出的分区之一都不匹配,则该INSERT
语句将失败,并显示错误“找到与给定分区集不匹配的行”。有关更多信息和示例,请参见“分区选择”。
您可以使用REPLACE
而不是INSERT
覆盖旧行。在处理包含重复的旧行的唯一键值的新行时,REPLACE
是与之相对应INSERT IGNORE
的:新行替换了旧行,而不是被丢弃。请参见“ REPLACE语句”。
tbl_name
是应在其中插入行的表。指定该语句为其提供值的列,如下所示:
- 在表名后提供一个用逗号分隔的列名的带括号的列表。在这种情况下,
VALUES
列表,VALUES ROW()
列表或SELECT
语句必须为每个命名列提供一个值。对于INSERT TABLE
表单,源表中的列数必须与要插入的列数匹配。 - 如果您没有为
INSERT ... VALUES
或指定列名列表,INSERT ... SELECT
则VALUES
表,SELECT
语句或TABLE
语句必须提供表中每列的值。如果您不知道表中各列的顺序,请使用查找。DESCRIBE tbl_name
SET
子句表示列明确地通过名称,与分配每一个的值一起。
列值可以通过几种方式给出:
如果未启用严格SQL模式,则任何未明确指定值的列都将设置为其默认值(显式或隐式)。例如,如果指定的列列表未命名表中的所有列,则未命名的列将设置为其默认值。“数据类型默认值”中介绍了默认值分配。另请参见“对无效数据的强制约束”。
如果启用了严格的SQL模式,则如果
INSERT
语句没有为没有默认值的每个列指定一个显式值,则该语句将生成错误。请参见“服务器SQL模式”。如果列列表和
VALUES
列表都为空,则INSERT
创建一行并将每列设置为其默认值:INSERT INTO tbl_name ()VALUES ();如果未启用严格模式,则MySQL对任何没有明确定义默认值的列都使用隐式默认值。如果启用了严格模式,则任何列都没有默认值都会发生错误。
- 使用关键字
DEFAULT
将列明确设置为其默认值。这使编写INSERT
为少数几个列分配值的语句更加容易,因为它使您避免编写不完整的VALUES
列表,该列表不包含表中每个列的值。否则,您必须提供与列表中每个值相对应的列名VALUES
列表。 - 如果将生成的列显式插入,则唯一允许的值为
DEFAULT
。有关生成的列的信息,请参见“创建表和生成的列”。 - 在表达式中,您可以用来生成column的默认值。
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);但是以下内容是不合法的,因为for的值
col1
是col2
,是在之后分配的col1
:INSERT INTO tbl_name (col1,col2)VALUES (col2*2,15);包含
AUTO_INCREMENT
值的列会发生异常。由于AUTO_INCREMENT
值是在其他值分配之后生成的AUTO_INCREMENT
,因此对分配中列的任何引用都将返回a0
。
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函数获得的受影响行值。请参见“信息函数”和“ 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
),其超过了列的最大长度。该值将被截断为该列的最大长度。 - 在数据类型非法的日期或时间列中插入一个值。该列设置为该类型的适当零值。
有关
INSERT
涉及AUTO_INCREMET
列值的示例,请参见“使用AUTO_INCREMENT”。如果
INSERT
将行插入到具有AUTO_INCREMENT
列的表中,则可以使用LAST_INSERT_ID()
SQL函数或mysql_insert_id()
C API函数查找用于该列的值。注意
这两个功能的行为并不总是相同的。“信息功能”和“ mysql_insert_id()”中进一步讨论
INSERT
了关于AUTO_INCREMENT
列的语句行为。
该INSERT
语句支持以下修饰符:
如果使用
LOW_PRIORITY
修饰符,则将INSERT
延迟执行,直到没有其他客户端从表中读取为止。这包括在现有客户端正在阅读以及INSERT LOW_PRIORITY
语句正在等待时开始阅读的其他客户端。因此,发出INSERT LOW_PRIORITY
声明的客户可能要等待很长时间。LOW_PRIORITY
影响使用仅表级锁定仅存储引擎(如MyISAM
,MEMORY
,和MERGE
)。注意
LOW_PRIORITY
通常不应与MyISAM
表一起使用,因为这样做会禁用并发插入。请参见“并发插入”。如果指定
HIGH_PRIORITY
,则--low-priority-updates
使用该选项启动服务器时它将覆盖该选项的效果。这还会导致不使用并发插入。请参见“并发插入”。HIGH_PRIORITY
影响使用仅表级锁定仅存储引擎(如MyISAM
,MEMORY
,和MERGE
)。如果使用
IGNORE
修饰符,则执行INSERT
语句时发生的错误将被忽略。例如,如果不IGNORE
使用,则复制表中现有UNIQUE
索引或PRIMARY KEY
值的行将导致重复键错误,并且该语句将中止。使用IGNORE
,该行将被丢弃,并且不会发生错误。被忽略的错误会生成警告。IGNORE
对没有找到与给定值匹配的分区的分区表中的插入有类似的效果。如果不使用IGNORE
,则此类INSERT
语句会因错误而中止。当INSERT IGNORE
被使用时,插入操作默默地失效含有不匹配的值的行,但是行插入被匹配。有关示例,请参见“列表分区”。如果
IGNORE
未指定,将触发错误的数据转换将中止该语句。使用IGNORE
,将无效值调整为最接近的值并插入;产生警告,但该语句不会中止。您可以使用mysql_info()
C API函数确定实际向表中插入了多少行。有关更多信息,请参见 IGNORE关键字和严格SQL模式的比较。
- 如果指定
ON DUPLICATE KEY UPDATE
,行插入,将在导致重复值UNIQUE
索引或者PRIMARY KEY
,一个UPDATE
旧行的发生。如果将行作为新行插入,则每行的受影响行值为1;如果更新了现有行,则为2;如果将现有行设置为其当前值,则为0。如果在连接到mysqld时CLIENT_FOUND_ROWS
为mysql_real_connect()
C API函数指定了标志,并且将现有行设置为当前值,则受影响的行值为1(而不是0)。请参见“在双重密钥更新语句中插入......”。 INSERT DELAYED
在MySQL 5.6中已弃用,并计划最终删除。在MySQL 8.0中,DELAYED
修饰符被接受但被忽略。使用INSERT
(不带DELAYED
)代替。请参见“ INSERT DELAYED语句”。