有条件地插入与Postgres中匹配条件的行数

时间:2017-12-02 01:34:57

标签: sql postgresql unique upsert

我有一张这样的表:

  create table if not exists features (
     username text not null,
     feature text not null,
     attributes text[] not null,

     primary key(username, feature)
  );

我想为用户插入新功能,但前提是它们目前在表中的功能少于2个。如果用户已在表中具有该功能,我还想更新该功能的属性。

这是我到目前为止所得到的:

with f (username, feature, attributes, fcount) as (
    values (
        'bob', 'dashboard', '{"theme=dark"}'::text[], 
        (select count(*) from features where username = 'bob' and feature = 'dashboard')
    )
)
insert into features (
    username,
    feature,
    attributes
)
select username, feature, attributes 
from f 
where fcount < 2
on conflict (username, feature)
do update set attributes = excluded.attributes
;        

当我使用不同的功能名称运行三次时,它会添加三行而不是2行。

username    feature     attributes
bob         dashboard   theme=dark
bob         dashboard1  theme=dark
bob         dashboard2  theme=dark

我怎样才能做到这一点?是否可以使用单个插入查询执行此操作,还是需要使用事务和多个查询?

http://sqlfiddle.com/#!17/dcc7c/2

1 个答案:

答案 0 :(得分:2)

主要问题 - 括号中的选择列表给出了一个元组,而不是单个列。此外,值子句中的attributes应明确转换为text[].。另请注意excluded部分中特殊记录on conflict的正确使用。

with f (username, feature, attributes, fcount) as (
    values (
        'bob', 'dashboard', '{"theme=dark"}'::text[], 
        (select count(*) from features where username = 'bob')
    )
)
insert into features (
    username,
    feature,
    attributes
)
select username, feature, attributes 
from f 
where fcount < 2
on conflict (username, feature)
do update set attributes = excluded.attributes;