可以在Postgres中关于2列中只有一列的冲突吗?

时间:2016-11-13 08:52:31

标签: sql postgresql

我有一个表有两列是唯一的,如果第一列(或两列)有冲突,我想要upsert,但如果只有第二列有冲突,则不执行任何操作。这可能吗?

CREATE TABLE test (
    username    VARCHAR(255) NOT NULL UNIQUE,
    email       VARCHAR(255) NOT NULL UNIQUE,
    status      VARCHAR(127)
);

以下是检查电子邮件冲突的方法:

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

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

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

1 个答案:

答案 0 :(得分:1)

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

首先,您只能有一个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;