是否可以在 Postgres 中对 2 列之一发生冲突进行更新?

jhh*_*shi 9 sql postgresql

我有一个表,它有两列是唯一的,如果第一列(或两列)有冲突,我想向上插入,但如果只有第二列有冲突,什么都不做。这可能吗?

CREATE TABLE test (
    username    VARCHAR(255) NOT NULL UNIQUE,
    email       VARCHAR(255) NOT NULL UNIQUE,
    status      VARCHAR(127)
);
Run Code Online (Sandbox Code Playgroud)

以下工作用于检查电子邮件中的冲突:

INSERT INTO test(username, email)
    VALUES ('test', 'test@test.test')
    ON CONFLICT(email) DO UPDATE SET status='upserted';
Run Code Online (Sandbox Code Playgroud)

但我想做这样的事情(下面的语法无效):

(INSERT INTO test(username, email)
    VALUES ('test', 'test@test.test')
    ON CONFLICT(email) DO UPDATE SET status='upserted')
    ON CONFLICT DO NOTHING;
Run Code Online (Sandbox Code Playgroud)

Pat*_*ick 6

是的,您可以这样做,但它需要一些有条件的技巧。

首先,您只能有一个ON CONFLICT子句,但此子句可以指定多个列,并在其上定义约束。在你的情况下,那将是ON CONFLICT (username, email). 当任一列或两列触发冲突时,就会发生冲突conflict_action

其次,该conflict_action子句应该将要插入的候选行(由 引用EXCLUDED)中的值与当前值进行比较并采取适当的措施。DO NOTHING实际上是不可能的,但您可以将旧值分配给新行,因此效果相同(但会发生更新)。不漂亮,但看起来有点像这样:

INSERT INTO test(username, email)
    VALUES ('test', 'test@test.test')
    ON CONFLICT(username, email) DO UPDATE 
        SET status = CASE WHEN username != EXCLUDED.username -- only email offending
                          THEN status                        -- so "do nothing"
                          ELSE 'upserted'                    -- some other action
                     END;
Run Code Online (Sandbox Code Playgroud)

  • 将 UNIQUE 添加到两列是否不会在该对上创建一个唯一索引,因此只有当该对是唯一的而不仅仅是其中一个或另一个时才会捕获它? (2认同)