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

Insert conditionally on number of rows matching condition in Postgres

我有一个 table 这样的:

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

     primary key(username, feature)
  );

我想为用户插入一个新功能,但前提是他们当前在 table 中的功能少于 2 个。如果用户已经在 table.

中拥有该功能,我还想更新该功能的属性

这是我目前得到的:

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

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

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;