【问题标题】:Multiple row insert or select if exists多行插入或选择(如果存在)
【发布时间】:2014-03-31 16:21:18
【问题描述】:
CREATE TABLE object (
  object_id serial,
  object_attribute_1 integer,
  object_attribute_2 VARCHAR(255)
)

-- primary key object_id
-- btree index on object_attribute_1, object_attribute_2

这是我目前拥有的:

SELECT * FROM object 
WHERE (object_attribute_1=100 AND object_attribute_2='Some String') OR
(object_attribute_1=200 AND object_attribute_2='Some other String') OR
(..another row..) OR
(..another row..)

当查询返回时,我会检查缺少的内容(因此,数据库中不存在)。

然后我将进行多行插入:

INSERT INTO object (object_attribute_1, object_attribute_2) 
VALUES (info, info), (info, info),(info, info)

然后我会选择我刚刚插入的内容

SELECT ... WHERE (condition) OR (condition) OR ...

最后,我将在客户端合并两个选择。

有没有一种方法可以将这 3 个查询组合成一个查询,我将在其中提供所有数据,如果记录尚不存在,则提供 INSERT,然后在最后执行 SELECT

【问题讨论】:

    标签: sql postgresql common-table-expression sql-insert


    【解决方案1】:

    你的怀疑是有根据的。使用data-modifying CTE(Postgres 9.1+)在单个语句中完成所有操作:

    WITH list(object_attribute_1, object_attribute_2) AS (
       VALUES
          (100, 'Some String')
        , (200, 'Some other String')
        ,  .....
       )
    , ins AS (
       INSERT INTO object (object_attribute_1, object_attribute_2)
       SELECT l.*
       FROM   list l
       LEFT   JOIN object o1 USING (object_attribute_1, object_attribute_2)
       WHERE  o1.object_attribute_1 IS NULL
       RETURNING *
       )
    SELECT * FROM ins   -- newly inserted rows
    
    UNION ALL           -- append pre-existing rows
    SELECT o.*
    FROM   list l
    JOIN   object o USING (object_attribute_1, object_attribute_2);
    

    请注意,竞态条件的时间框架很短。因此,如果许多客户同时尝试,这可能会中断。如果您在繁重的并发负载下工作,请考虑这个相关的答案,特别是关于 lockingserializable transaction isolation:
    Postgresql batch insert or ignore

    的部分

    【讨论】:

    • 我有一种感觉,你会再次来我的 postgresql 救援。再次感谢你!你有推特账号吗?
    • @alumns:考虑更新。我的初稿只返回了新插入的行。
    猜你喜欢
    • 2020-02-04
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2012-01-24
    • 1970-01-01
    • 2020-07-05
    • 2012-03-14
    相关资源
    最近更新 更多