2015-11-27 63 views
0

我試圖插入一行,但僅當它不在表中。目前我使用類似於下面的代碼:如何僅在不存在的情況下插入行?

insert into mentions (project_id, id, data_source, channel) 
    select 3, '123456789', 'example.com', 'twitter' 
    where not exists 
    (select 1 as "one" from mentions where (project_id = 3 and id = '123456789')) 
returning reach; 

但我有時會看到它在日誌中

ERROR: duplicate key value violates unique constraint "mentions_pkey"

DETAIL: Key (project_id, id)=(3, 123456789) already exists.

失敗,出現以下錯誤和約束被定義爲

Index "public.mentions_pkey" 
┌────────────┬─────────┬────────────┐ 
│ Column │ Type │ Definition │ 
├────────────┼─────────┼────────────┤ 
│ project_id │ integer │ project_id │ 
│ id   │ text │ id   │ 
└────────────┴─────────┴────────────┘ 
primary key, btree, for table "public.mentions" 

因爲我只在exists子句爲false時插入,所以我不明白這是如何違反約束而失敗的。

它可能是一個併發問題?我假設個人陳述是原子的,但也許情況並非如此?

我知道一旦有9.5艘船可以使用ON CONFLICT DO NOTHING,但我現在正在運行9.4。在存儲過程

+0

這個問題被問時最新的版本的PostgreSQL有沒有衝突條款。請注意,前兩個問題之後的指定版本也發佈了。 – Roberto

回答

0
  1. 手柄錯誤
CREATE OR REPLACE FUNCTION some_insert() RETURNS VOID AS 
    $$BEGIN 
    BEGIN 
     insert into mentions (project_id, id, data_source, channel) 
      select 3, '123456789', 'example.com', 'twitter'; 
     RETURN; 
    EXCEPTION WHEN unique_violation THEN 
     -- do nothing 
    END; 
    END;$$ 
    LANGUAGE plpgsql; 
  • 鎖表
  • BEGIN; 
    LOCK TABLE mentions IN SHARE ROW EXCLUSIVE MODE; 
    INSERT INTO mentions (project_id, id, data_source, channel) 
        SELECT 3, '123456789', 'example.com', 'twitter' 
        WHERE NOT EXISTS 
         (SELECT 1 AS "one" FROM mentions WHERE (project_id = 3 AND id = '123456789')) 
    COMMIT; 
    
  • 手柄postgres的客戶端錯誤
  • +0

    是的,我認爲我將不得不去存儲過程版本,希望避免: - ( –

    相關問題