ON CONFLICT ON CONSTRAINT从任何约束触发

时间:2017-06-12 20:27:58

标签: 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;

1 个答案:

答案 0 :(得分:1)

  

我正在尝试在任何约束上触发UPSERT,但似乎找不到与 ON CONFLICT ON CONSTRAINT (*) 类似的语法。

省略 可选冲突目标条款ON CONSTRAINT以触发任何唯一违规行为:

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

Details in the manual on INSERT.

我会提供你的功能的工作版本,但是你发布的内容是不一致的。 "@UserID"未定义,等等。

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