INSERT ON DUPLICATE KEY UPDATE

更新时间:

通过INSERT ON DUPLICATE KEY UPDATE更新数据时,AnalyticDB for MySQL会首先尝试在表中插入新行,如果新数据与已有数据的主键重复,则将更新同主键的数据。

AnalyticDB for MySQL会根据待写入行是否存在选择对应的执行语句,规则如下:

  • 待写入行不存在,则执行INSERT插入新行,受影响的行数为1。

  • 待写入行存在,则执行UPDATE更新现有行,受影响的行数也为1。

注意事项

  • INSERT INTO ... ON DUPLICATE KEY UPDATE...只支持等值更新,不支持复杂表达式(包括算术表达式、条件表达式等)。

  • 在更新数据量较大或数据更新频率高(超过100 QPS)的场景下,使用INSERT ON DUPLICATE KEY UPDATE更新数据会导致CPU使用率显著升高。建议您使用REPLACE INTO批量更新数据。详情请参见REPLACE INTO

语法

INSERT INTO table_name[(column_name[, …])]
[VALUES]
[(value_list[, …])]
ON DUPLICATE KEY UPDATE
   c1 = v1, 
   c2 = v2,
   ...;

示例

本文所有示例均基于student_course表,建表语句如下:

CREATE TABLE student_course(
    id bigint,
    user_id bigint,
    nc_id varchar,
    nc_user_id varchar,
    nc_commodity_id varchar,
    course_no varchar,
    course_name varchar,
    business_id varchar,
    PRIMARY KEY(user_id)
) DISTRIBUTED BY HASH(user_id);

使用如下语句插入一行数据:

INSERT INTO student_course (`id`, `user_id`, `nc_id`, `nc_user_id`, `nc_commodity_id`, `course_no`, `course_name`, `business_id`)
VALUES(277941, 11056941, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--55', 'kuaiji')
ON DUPLICATE KEY UPDATE
course_name = '工业会计实战V9.0--55',
business_id = 'kuaiji';

执行SELECT * FROM student_course;语句,返回如下结果说明数据插入成功:

+-------+----------+---------------------+---------------------+---------------------+-----------+---------------------+------------+
| id    | user_id  | nc_id               | nc_user_id          | nc_commodity_id     | course_no | course_name         |business_id |
+-------+----------+---------------------+---------------------+---------------------+-----------+---------------------+------------+
|277941 | 11056941 | 1001EE1000000043G2T5|1001EE1000000043G2TO | 1001A5100000003YABO2|   kckm303 | 工业会计实战V9.0--55|   kuaiji   |
+-------+----------+---------------------+---------------------+---------------------+-----------+---------------------+------------+

此时,需要再往student_course表中入一行新数据:

INSERT INTO student_course(`id`, `user_id`, `nc_id`, `nc_user_id`, `nc_commodity_id`, `course_no`, `course_name`, `business_id`)
VALUES(277942, 11056941, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--66', 'kuaiji')
ON DUPLICATE KEY UPDATE
course_name = '工业会计实战V9.0--66',
business_id = 'kuaiji';

但由于新插入的数据中存在重复主键(即user_id与第一次插入的数据重复,均为11056941),因此执行上述语句后只会更新ON DUPLICATE KEY UPDATE子句中的course_name = '工业会计实战V9.0--66',business_id = 'kuaiji'值,您可以执行SELECT * FROM student_course;语句来查看更新后的数据,返回结果如下:

+-------+----------+---------------------+---------------------+---------------------+-----------+---------------------+------------+
| id    | user_id  | nc_id               | nc_user_id          | nc_commodity_id     | course_no | course_name         |business_id |
+-------+----------+---------------------+---------------------+---------------------+-----------+---------------------+------------+
|277941 | 11056941 | 1001EE1000000043G2T5|1001EE1000000043G2TO | 1001A5100000003YABO2|   kckm303 | 工业会计实战V9.0--66|   kuaiji   |
+-------+----------+---------------------+---------------------+---------------------+-----------+---------------------+------------+

常见问题

怎么解决报错`insert on duplicate key update` statement only support 'primitive value' and values() expr.

报错原因:INSERT INTO ... ON DUPLICATE KEY UPDATE...只支持基本值赋值(下文例1)或VALUES()赋值(下文例2),不支持复杂表达式(例如算术表达式、条件表达式)和函数。当ON DUPLICATE KEY UPDATE中使用了复杂表达式或函数时,会出现该报错。

解决办法:修改SQL语句,在ON DUPLICATE KEY UPDATE中使用基本值赋值或VALUES()赋值。

1:基本值赋值。

INSERT INTO student_course (`id`, `user_id`, `nc_id`, `nc_user_id`, `nc_commodity_id`, `course_no`, `course_name`, `business_id`)
VALUES(277941, 11056941, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--55', 'kuaiji')
ON DUPLICATE KEY UPDATE
course_name = '工业会计实战V9.0--55',
business_id = 'kuaiji';

2:VALUES()赋值。

INSERT INTO student_course (`id`, `user_id`, `nc_id`, `nc_user_id`, `nc_commodity_id`, `course_no`, `course_name`, `business_id`)
VALUES(277941, 11056941, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--55', 'kuaiji')
ON DUPLICATE KEY UPDATE
course_name = VALUES(course_name),
business_id = VALUES(business_id);

INSERT ON DUPLICATE KEY UPDATE是否支持批量插入数据?

支持。使用INSERT ON DUPLICATE KEY UPDATE批量插入数据时,您可以使用 VALUES 子句提供多组值,并在 ON DUPLICATE KEY UPDATE 子句指定如何处理冲突。

例如,在student_course表中批量插入3条数据:

INSERT INTO student_course(`id`, `user_id`, `nc_id`, `nc_user_id`, `nc_commodity_id`, `course_no`, `course_name`, `business_id`)
VALUES(277943, 11056941, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--77', 'kuaiji'),
(277944, 11056943, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--88', 'kuaiji'),
(277945, 11056944, '1001EE1000000043G2T5', '1001EE1000000043G2TO', '1001A5100000003YABO2', 'kckm303', '工业会计实战V9.0--99', 'kuaiji')
ON DUPLICATE KEY UPDATE
course_name = VALUES(course_name),
business_id = VALUES(business_id);