📜  PostgreSQL Upsert(1)

📅  最后修改于: 2023-12-03 15:18:38.383000             🧑  作者: Mango

PostgreSQL Upsert

在传统的SQL中,我们通常会使用INSERT和UPDATE语句来往数据库中添加数据和更新数据。但是有时候我们需要针对某些条件进行数据更新操作,如果没有符合条件的数据,则需要插入一行新的数据。这个操作通常被称为upsert。

PostgreSQL中提供了一种称为ON CONFLICT的扩展,使得upsert操作变得简单且易于实现。ON CONFLICT扩展从版本9.5开始被引入。

语法

upsert操作使用INSERT语句结合ON CONFLICT子句来实现。其基本语法如下:

INSERT INTO table_name (column1, column2, ...) 
VALUES (value1, value2, ...)
ON CONFLICT conflict_target DO UPDATE SET column1 = value1 WHERE condition;

在上面的语法中:

  • table_name:需要执行upsert操作的表名
  • column1, column2, ...:需要插入或更新的列名
  • value1, value2, ...:需要插入或更新的值
  • conflict_target:冲突检测条件,可以是UNIQUE约束、PRIMARY KEY或EXCLUDE约束的列。该条件指定了upsert操作需要判断的唯一性条件
  • DO UPDATE SET column1 = value1 WHERE condition:表示当冲突发生时需要执行的UPDATE操作。需要更新的列和其对应的值以及更新条件。
举例说明

为了更好地理解upsert操作,我们可以通过一个简单的例子来演示它的使用。

假设我们有一个名为students的表,它包含以下数据:

id | name  | age
---+-------+-----
 1 | Alice |  18
 2 | Bob   |  20

现在我们想要将名为Charlie的学生添加到students表中,如果该名学生已经存在于表中,则更新该学生的年龄。为了实现这个操作,我们可以使用以下语句:

INSERT INTO students (name, age) 
VALUES ('Charlie', 19) 
ON CONFLICT (name) DO UPDATE 
SET age = 19 
WHERE students.name = 'Charlie';

执行这个语句之后,我们可以得到如下结果:

id | name    | age
---+---------+-----
 1 | Alice   |  18
 2 | Bob     |  20
 3 | Charlie |  19

如果我们再次执行upsert操作,将名为Charlie的学生的年龄更新为20岁:

INSERT INTO students (name, age) 
VALUES ('Charlie', 20) 
ON CONFLICT (name) DO UPDATE 
SET age = 20 
WHERE students.name = 'Charlie';

我们可以得到如下结果:

id | name    | age
---+---------+-----
 1 | Alice   |  18
 2 | Bob     |  20
 3 | Charlie |  20

如上,upsert操作通过使用ON CONFLICT子句使得插入和更新操作变得非常容易。如果冲突检测条件匹配成功,则会执行UPDATE操作,否则会执行INSERT操作。