是否可以执行需要在 Postgres 中过滤的更新插入?
Is it possible to perform an upsert that requires filtering in Postgres?
我想知道是否可以使用以下语句进行带过滤的更新插入。也就是说,我是否可以先尝试使用 where 子句进行更新,如果失败,则插入,而不是相反?我想在 Postgres 中这样做。
INSERT ... ON CONFLICT DO NOTHING/UPDATE
我确实看到了这个,但它肯定有点复杂
https://dba.stackexchange.com/questions/13468/idiomatic-way-to-implement-upsert-in-postgresql
That is, can I first try to update with a where clause, if it fails, then insert, rather than the other way around?
不清楚您为什么要这样做。
UPSERT 的目的是确保数据库恰好包含具有给定键和一组给定的其他列值的一行。 Postgres 首先尝试 INSERT,因为当键与重复行冲突时 INSERT 将失败(这样它可以回退到更新冲突行而不是引发异常)。如果 WHERE 子句什么都不匹配,UPDATE 将不会失败。它将successfully update zero rows。如果您违反约束条件(例如 CHECK 或 NOT NULL 约束条件),UPDATE 可能会失败,但不会因为您没有匹配任何行而失败。
并且,另一方面,如果您的 UPDATE 将更改现有行,那么您的 INSERT 必然会因唯一性冲突而失败(因为该行存在)。所以在这种情况下首先尝试 INSERT 实际上并没有改变结果。
可以使用 INSERT... ON CONFLICT DO UPDATE... WHERE...
形式的语法在 PostgreSQL 的 UPSERT 上挂起条件。这将:
- 插入您提供的行。
- 对于与现有行的每个冲突,评估该行的 WHERE 条件。
- 如果满足 WHERE 条件,则更新现有行,否则什么也不做。
我相信这在功能上等同于您所要求的,因为:
- 如果该行不存在,Postgres 将插入它。 UPDATE 不会影响它,因此您的方法无论如何都必须回退到 INSERTing 它。
- 如果该行存在,但与 WHERE 子句不匹配,则 Postgres 将不执行任何操作。我认为您的方法在尝试 INSERT 后要么什么都不做,要么因唯一性约束而失败,但对于这种情况,您可能还有其他想法。
- 如果该行存在并且与 WHERE 子句匹配,Postgres 和您的方法都将对该行执行更新。
我想知道是否可以使用以下语句进行带过滤的更新插入。也就是说,我是否可以先尝试使用 where 子句进行更新,如果失败,则插入,而不是相反?我想在 Postgres 中这样做。
INSERT ... ON CONFLICT DO NOTHING/UPDATE
我确实看到了这个,但它肯定有点复杂 https://dba.stackexchange.com/questions/13468/idiomatic-way-to-implement-upsert-in-postgresql
That is, can I first try to update with a where clause, if it fails, then insert, rather than the other way around?
不清楚您为什么要这样做。
UPSERT 的目的是确保数据库恰好包含具有给定键和一组给定的其他列值的一行。 Postgres 首先尝试 INSERT,因为当键与重复行冲突时 INSERT 将失败(这样它可以回退到更新冲突行而不是引发异常)。如果 WHERE 子句什么都不匹配,UPDATE 将不会失败。它将successfully update zero rows。如果您违反约束条件(例如 CHECK 或 NOT NULL 约束条件),UPDATE 可能会失败,但不会因为您没有匹配任何行而失败。
并且,另一方面,如果您的 UPDATE 将更改现有行,那么您的 INSERT 必然会因唯一性冲突而失败(因为该行存在)。所以在这种情况下首先尝试 INSERT 实际上并没有改变结果。
可以使用 INSERT... ON CONFLICT DO UPDATE... WHERE...
形式的语法在 PostgreSQL 的 UPSERT 上挂起条件。这将:
- 插入您提供的行。
- 对于与现有行的每个冲突,评估该行的 WHERE 条件。
- 如果满足 WHERE 条件,则更新现有行,否则什么也不做。
我相信这在功能上等同于您所要求的,因为:
- 如果该行不存在,Postgres 将插入它。 UPDATE 不会影响它,因此您的方法无论如何都必须回退到 INSERTing 它。
- 如果该行存在,但与 WHERE 子句不匹配,则 Postgres 将不执行任何操作。我认为您的方法在尝试 INSERT 后要么什么都不做,要么因唯一性约束而失败,但对于这种情况,您可能还有其他想法。
- 如果该行存在并且与 WHERE 子句匹配,Postgres 和您的方法都将对该行执行更新。