PostgreSQL是否有机制在单个查询中多次更新同一行?

时间:2015-05-18 06:17:58

标签: sql postgresql sql-update

请考虑以下事项:

create table tmp.x (i integer, t text);
create table tmp.y (i integer, t text);
delete from tmp.x;
delete from tmp.y;
insert into tmp.x values (1, 'hi');
insert into tmp.y values(1, 'there');
insert into tmp.y values(1, 'wow');

在上面,表x中有一行,我想要更新。在表格y中,有两行,我想要将这两行输入"将数据输入"更新。

以下是我的尝试:

update tmp.x
set t = x.t || y.t
from ( select * from tmp.y order by t desc ) y
where y.i = x.i;

select * from tmp.x;

我希望x.t的值为'hiwowthere',但该值最终为'hiwow'。我相信原因是update语句中的子查询返回两行(y.t'wow'首先返回),而where子句y.i = x.i只返回匹配第一行。

我可以使用单个update语句获得所需的结果吗?如果是,那该怎么做?

更新:上述text类型的使用仅用于说明目的。我实际上并不想使用我在这里发布的json_set函数(How do I modify fields inside the new PostgreSQL JSON datatype?)来修改文本内容,而是修改JSON内容,尽管我希望这个原则可以应用于任何函数,比如虚构的concat_string(column_name, 'string-to-append')

更新2:我实际上写了一个小函数来完成它,而不是在这个问题上浪费时间。但是,知道这是否可行仍然很好,如果可行,如何。

3 个答案:

答案 0 :(得分:3)

您可以使用string_agg建立一个连接字符串,按integer i分组,然后您可以在更新期间加入该字符串:

update tmp.x
set t = x.t || y.txt
from (select i, string_agg(t, '') as txt
     from(
       select tmp.y.i,tmp.y.t
        from tmp.y
        order by t desc
      ) z
      group by z.i) y
where y.i = x.i ;

为了保留订单,您可能需要一个额外的包装派生表。 SqlFiddle here

答案 1 :(得分:1)

使用string_agg,如下所示:

update tmp.x x
set t = x.t || (
                select string_agg(t,'' order by t desc) 
                from tmp.y where i = x.i 
                group by i
               )

SQLFiddle

答案 2 :(得分:0)

with cte as (
select y.i, string_agg(t, '' order by t desc)  as txt
      from y
      group by y.i
)
update x set t= x.t||cte.txt 
from cte where cte.i=x.i