sql - Postgres UPSERT(INSERT 或 UPDATE)仅当值不同时

标签 sql postgresql merge upsert

我正在更新 Postgres 8.4 数据库(来自 C# 代码),基本任务非常简单:更新现有行或插入新行(如果尚不存在)。通常我会这样做:

UPDATE my_table
SET value1 = :newvalue1, ..., updated_time = now(), updated_username = 'evgeny'
WHERE criteria1 = :criteria1 AND criteria2 = :criteria2

如果 0 行受到影响,则执行插入:

INSERT INTO my_table(criteria1, criteria2, value1, ...)
VALUES (:criteria1, :criteria2, :newvalue1, ...)

不过,有一个轻微的扭曲。我不想更改 updated_timeupdated_username 列,除非任何新值实际上与现有值不同以避免误导用户关于数据更新的时间。

如果我只执行更新,那么我也可以为值添加 WHERE 条件,但这在这里不起作用,因为如果数据库已经是最新的,更新将影响 0 行,然后我会尝试插入。

除了 SELECT,然后 UPDATE 或 INSERT 之外,谁能想到一种优雅的方式来做到这一点?

最佳答案

查看 BEFORE UPDATE 触发器以检查并设置正确的值:

CREATE OR REPLACE FUNCTION my_trigger() RETURNS TRIGGER LANGUAGE plpgsql AS
$$
BEGIN
    IF OLD.content = NEW.content THEN
        NEW.updated_time= OLD.updated_time; -- use the old value, not a new one.
    ELSE
        NEW.updated_time= NOW();
    END IF;
    RETURN NEW;
END;
$$;

现在您甚至不必在 UPDATE 查询中提及字段 updated_time,它将由触发器处理。

http://www.postgresql.org/docs/current/interactive/plpgsql-trigger.html

关于sql - Postgres UPSERT(INSERT 或 UPDATE)仅当值不同时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3464750/

相关文章:

algorithm - 合并排序中的比较数

sql - Postgres/Redshift 按状态计算最后 5 行

postgresql - 如何在 PostgreSQL 中列出用户定义的函数和过程

python - 如何使用 Pandas 从一个数据框中的另一个数据框中查找值?

PostgreSQL - 将列数据类型从整数更改为整数数组

postgresql - idx_scan 在 PostgreSQL 统计中非常低

git - 在 OS X 上使用 vi 添加 git 提交消息

sql - 基于集合的操作和调用存储过程

SQL错误,group by执行不正确

mysql - 左连接,其中左表列 = 某些内容或 null