如果行尚未存在,我该如何插入?

时间:2015-11-27 18:28:43

标签: postgresql

我正在尝试插入一行,但只有在表中尚未存在的情况下才会插入。目前我正在使用类似于以下内容的代码:

<mapping resource="employee.hbm.xml"/>

但我有时会看到它在日志中出现以下错误而失败

  

错误:重复键值违反了唯一约束“mentions_pkey”

     

详细信息:Key(project_id,id)=(3,123456789)已经存在。

,约束定义为

cfg.configure("hibernate.cfg.xml");

由于我只是在exists子句为false时才插入,所以我不明白这种情况如何会因违反约束而失败。

这可能是并发问题吗?我假设个别陈述是原子的,但事实并非如此?

我知道一旦9.5艘船我可以使用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; ,但我现在正在运行9.4。

2 个答案:

答案 0 :(得分:1)

在插入时使用ON CONFLICT可选子句:

insert into mentions  (project_id, id, data_source, channel)
  values (3, '123456789', 'example.com', 'twitter')
  ON CONFLICT (project_id, id) DO NOTHING;

看:http://www.postgresql.org/docs/9.5/static/sql-insert.html#SQL-ON-CONFLICT

答案 1 :(得分:0)

  1. 处理存储过程中的错误
  2.   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;
    
    1. 锁定表
    2. 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;
      
      1. 处理postgres'客户端
      2. 上的错误