2016-11-13 1 views
2

私は一意の2つの列を持ち、最初の列(または両方の列)に競合がある場合にアップサートしたいが、2番目の列のみが競合する場合は何もしない表があります。これは可能ですか?2つのカラムのうちの1つのカラムで競合が発生した場合、Postgresでアップセットできますか?

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', '[email protected]') 
    ON CONFLICT(email) DO UPDATE SET status='upserted'; 

しかし、私はこの(以下、無効な構文)のような何かをしたいと思います:あなたは、

(INSERT INTO test(username, email) 
    VALUES ('test', '[email protected]') 
    ON CONFLICT(email) DO UPDATE SET status='upserted') 
    ON CONFLICT DO NOTHING; 
+0

[ON CONFLICT句で使用する複数の競合の\ _target]の可能性のある重複http://stackoverflow.com/questions/35888012/use-multiple-conflict- target-in-on-conflict-clause) – e4c5

+0

@ e4c5この質問は、複数の起こりうる競合を条件付きで処理することについてです。あなたが参照する質問は、単に複数の制約に関するものです。 – Patrick

答えて

0

はいをこれを行うことができますが、一部の条件付きトリッキーが必要です。

まず、ON CONFLICT句を1つだけ持つことができますが、この句では、制約が定義された複数の列を指定できます。あなたの場合はON CONFLICT (username, email)になります。列のいずれか一方または両方ができる。第二に

衝突、conflict_actionキックをトリガする場合、conflict_action句は、現在の値に対して(EXCLUDEDによって参照)の挿入のための候補列から値を比較し、適切な行動を取るべきです。実際にはDO NOTHINGは使用できませんが、エフェクトが同じになるように古い値を新しい行に割り当てることができます(しかし、更新が行われます)。きれいではありませんが、それは多少のようになります。(

INSERT INTO test(username, email) 
    VALUES ('test', '[email protected]') 
    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; 
関連する問題