postgresql - ON CONFLICT ON CONSTRAINT 从任何约束触发

标签 postgresql plpgsql upsert

我试图在任何约束上触发 UPSERT,但似乎找不到类似于 ON CONFLICT ON CONSTRAINT (*) 的语法。我尝试使用案例来声明我的特定约束:

ON CONFLICT ON CONSTRAINT (
  CASE "@Type"
    WHEN 'user' THEN "Meta_User_Namespace"
    WHEN 'device' THEN "Meta_Device_Namespace"
    WHEN 'profile' THEN "Meta_UserProfile_Namespace"
    WHEN 'group' THEN "Meta_Group_Namespace"
  END
)

但我认为这不是一种合适的方式,而且这种语法似乎不起作用。

我该如何解决?我基本上有这个 SP 可以处理各种表类型的元数据。我认为只有 4 个具有唯一索引的列就足够了,而不是 4 个单独的表链接到我的元数据。请注意,此 SP 充当 UPSERT。

CREATE OR REPLACE FUNCTION "SetMeta" (
  "@Type"      VARCHAR(10),
  "@ID"        UUID,
  "@Namespace" VARCHAR(50),
  "@Data"      JSONB
)
RETURNS void AS
$func$
BEGIN
  INSERT INTO
    "Meta" AS um (
      "ID",
      "UserID",
      "UserProfileID",
      "DeviceID",
      "Namespace",
      "Data"
    )
  VALUES (
    UUID_GENERATE_V4(),
    CASE "@Type" WHEN 'user' THEN "@UserID" ELSE null END,
    CASE "@Type" WHEN 'profile' THEN "@UserProfileID" ELSE null END,
    CASE "@Type" WHEN 'device' THEN "@DeviceID" ELSE null END,
    CASE "@Type" WHEN 'group' THEN "@Namespace" ELSE null END,
    "@Namespace",
    "@Data"
  )
  ON CONFLICT ON CONSTRAINT (
    CASE "@Type"
      WHEN 'user' THEN "Meta_User_Namespace"
      WHEN 'device' THEN "Meta_Device_Namespace"
      WHEN 'profile' THEN "Meta_UserProfile_Namespace"
      WHEN 'group' THEN "Meta_Group_Namespace"
    END
  )
  DO UPDATE SET
    "Data" = "@Data",
    "Updated" = NOW()
  WHERE
    (
      um."UserID" = "@UserID" OR
      um."UserProfileID" = "@UserProfileID" OR
      um."DeviceID" = "@DeviceID" OR
      um."GroupID" = "@GroupID"
    ) AND
    um."Namespace" = "@Namespace";
END;
$func$ LANGUAGE PLPGSQL;

最佳答案

I'm trying to trigger an UPSERT on any constraint but can't seem to find a syntax that would be similar to ON CONFLICT ON CONSTRAINT (*).

只需省略可选的冲突目标子句 ON CONSTRAINT 以触发任何独特的违规行为:

INSERT INTO "Meta" AS um ( ... )
VALUES ( ... )
<b>ON CONFLICT</b>                            -- that's all!
DO UPDATE SET ...

Details in the manual on INSERT.

我会提供您函数的工作版本,但您发布的内容不一致。 "@UserID" 未定义等

并且在 Postgres 中到处使用简单的、不带引号的、合法的、小写的标识符,比如 @a_horse already suggested . (包括 SQL 和 PL/pgSQL 函数中的参数和变量名称。)

关于postgresql - ON CONFLICT ON CONSTRAINT 从任何约束触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44508178/

相关文章:

bash - 如何使用 bash 创建 POSTGRES 数据库的备份?

sql - 使用间距阈值对可变连续的带时间戳的记录进行分组

MySQL UPSERT 无法识别别名

sql - 等效于 Merge with output 子句在 SQL Server 到 Postgresql

带有 HikariCP 的 Java Spring Boot postgresql - 从语句查询中获取原始字符串输出

performance - 如何分析 PostgreSQL 9.2 中的 plpgsql 函数

sql - 如何在postgresql中获取更新、插入、删除查询的行数

postgresql - 获取行以在特定条件下交换表

sql - SnowFlake MERGE 更新/插入所有列

c# - MongoDb Upsert死锁