📜  MySQL UPSERT

📅  最后修改于: 2020-11-19 00:50:26             🧑  作者: Mango

MySQL UPSERT

UPSERT是DBMS软件管理数据库的基本功能之一。此操作允许DML用户插入新记录或将现有数据更新到表中。 UPSERT由两个分别称为UPDATE和INSERT的单词组成。前两个字母,即UP代表UPDATE,而SERT代表INSERT。 UPSERT是一个原子操作,这意味着它是一步完成的操作。例如,如果一条记录是新的,它将触发INSERT命令。但是,如果它已经存在于表中,则此操作将执行UPDATE语句。

默认情况下,MySQL向INSERT提供ON DUPLICATE KEY UPDATE选项,以完成此任务。但是,它也包含一些其他满足此目的的语句,例如INSERT IGNORE或REPLACE。我们将详细学习并看到所有这些解决方案。

MySQL UPSERT示例

我们可以主要通过三种方式执行MySQL UPSERT操作,如下所示:

  • 使用INSERT IGNORE的UPSERT
  • 使用REPLACE的UPSERT
  • 使用INSERT ON DUPLICATE KEY UPDATE的UPSERT

使用INSERT IGNORE的UPSERT

INSERT IGNORE语句用于在执行无效行的插入操作时忽略执行错误。例如,主键列不允许我们存储重复值。如果尝试使用表中已存在的相同主键插入新记录,则会收到错误消息。但是,如果我们使用INSERT IGNORE命令执行此操作,它将生成警告而不是错误。

句法

以下是在MySQL中使用INSERT IGNORE语句的语法:

INSERT IGNORE INTO table_name (column_names)
VALUES ( value_list), ( value_list) .....;

MySQL INSERT IGNORE示例

让我们了解MySQL中INSERT IGNORE语句的工作方式。首先,我们需要使用以下语句创建一个名为“ Student”的表:

CREATE TABLE Student (
  Stud_ID int AUTO_INCREMENT PRIMARY KEY,
  Name varchar(45) DEFAULT NULL,
  Email varchar(45) NOT NULL UNIQUE,
  City varchar(25) DEFAULT NULL
);

UNIQUE约束确保我们不能将重复的值保留在email列中。接下来,需要将记录插入表中。以下语句用于将数据添加到表中:

INSERT INTO Student(Stud_ID, Name, Email, City) 
VALUES (1,'Stephen', 'stephen@javatpoint.com', 'Texas'), 
(2, 'Joseph', 'Joseph@javatpoint.com', 'Alaska'), 
(3, 'Peter', 'Peter@javatpoint.com', 'California');

现在,我们可以使用SELECT语句验证插入操作:

mysql> SELECT * FROM Student;

我们将获得以下输出,其中表中有三行:

现在,我们将执行以下语句以将两个记录添加到表中:

INSERT INTO Student(Stud_ID, Name, Email, City) 
VALUES (4,'Donald', 'donald@javatpoint.com', 'New York'), 
(5, 'Joseph', 'Joseph@javatpoint.com', 'Chicago');

执行上述语句后,我们将看到错误:ERROR 1062(23000):由于电子邮件紫罗兰色UNIQUE约束,因此重复了项'student.Email'的条目'Joseph@javatpoint.com'。

但是,当我们使用INSERT IGNORE命令执行相同的语句时,我们没有收到任何错误。相反,我们只会收到警告。

INSERT IGNORE INTO Student(Stud_ID, Name, Email, City) 
VALUES (4,'Donald', 'donald@javatpoint.com', 'New York'), 
(5, 'Joseph', 'Joseph@javatpoint.com', 'Chicago');

MySQL将产生一条消息:添加了一行,而另一行被忽略。

1 row affected, 1 warning(s): 1062 Duplicate entry for key email.
Records: 2  Duplicates: 1  Warning: 1

我们可以使用SHOW WARNINGS命令查看详细的警告:

因此,如果存在某些重复项,并且我们使用INSERT IGNORE语句,MySQL会发出警告而不是发出错误,并将其余记录添加到表中。

使用REPLACE的UPSERT

在某些情况下,我们希望将现有记录更新到表中以保持更新。如果为此目的使用标准插入查询,它将为PRIMARY KEY错误提供重复条目。在这种情况下,我们将使用REPLACE语句执行我们的任务。当我们使用REPLACE命令时,会发生两种可能的事件:

  • 如果在现有数据行中找不到匹配值,则执行标准INSERT语句。
  • 如果旧记录与新记录匹配,则replace命令将删除现有行,然后执行常规INSERT语句,将新记录添加到表中。

在REPLACE语句中,更新分两个步骤执行。首先,它将删除现有记录,然后添加新更新的记录,类似于标准INSERT命令。因此,可以说REPLACE语句执行两个标准功能,即DELETE和INSERT。

MySQL中REPLACE语句的语法如下:

REPLACE [INTO] table_name(column_list)
VALUES(value_list);

让我们借助一个真实的例子来理解它。在这里,我们将获取之前创建的Student表,其中包含以下数据:

现在,我们将使用REPLACE语句用新的城市Los Angeles更新id = 2的学生所在的城市。为此,请执行以下语句:

REPLACE INTO Student(Stud_ID, Name, Email, City)
VALUES(2, 'Joseph', 'joseph@javatpoint.com', 'Los Angeles');

成功执行后,我们将获得如下输出:

在上图中,当我们仅更新了单个行的值时,我们可以看到消息“受影响的2行”。这是因为REPLACE命令首先删除了记录,然后将新记录添加到了表中。因此,该消息显示为“受影响的2行。”

使用INSERT ON DUPLICATE KEY UPDATE的UPSERT

到目前为止,我们已经看到了两个UPSERT命令,但是它们有一些限制。 INSERT IGNORE语句仅忽略重复错误,而不对表进行任何修改。并且REPLACE方法检测到INSERT错误,但是它将在添加新记录之前删除该行。因此,到目前为止,我们仍在寻找更完善的解决方案。

因此,我们将使用更完善的解决方案作为INSERT ON DUPLICATE KEY UPDATE语句。这是一种非破坏性方法,表示它不会删除重复的行。相反,当我们在SQL语句中指定ON DUPLICATE KEY UPDATE子句时,一行将导致UNIQUE或PRIMARY KEY索引列中出现重复的错误值,那么将更新现有行。

在MySQL中,Insert on Duplicate Key Update语句的语法如下:

INSERT INTO table (column_names)
VALUES (data)
ON DUPLICATE KEY UPDATE 
column1 = expression, column2 = expression...;

让我们借助一个真实的例子来理解它。在这里,我们将采用之前创建的Student表。现在,使用以下查询在表中再添加一行:

INSERT INTO Student(Stud_ID, Name, Email, City) 
VALUES (4,'John', 'john@javatpoint.com', 'New York');

该查询将一条记录成功添加到表中,因为它没有任何重复的值。

接下来,执行以下MySQL UPSERT命令,以更新Stud_ID列中的重复记录:

INSERT INTO Student(Stud_ID, Name, Email, City) 
VALUES (4, 'John', 'john@javatpoint.com', 'New York')
ON DUPLICATE KEY UPDATE City = 'California';

成功执行后,MySQL给出以下消息:

Query OK, 2 rows affected.

在输出中,我们可以看到id = 4行已经存在。因此,该查询仅用加利福尼亚更新纽约市。