2015-05-18 20 views
2

考慮以下幾點:PostgreSQL是否有機制在單個查詢中多次更新同一行?

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函數的JSON內容(How do I modify fields inside the new PostgreSQL JSON datatype?),儘管我希望該原理可以應用於任何函數,例如虛構的concat_string(column_name, 'string-to-append')

更新2:我沒有浪費時間在這個問題上,而是寫了一個小功能來完成它。但是,如果知道這是否可行,那還是很好的,如果是的話,如何。

回答

2

你可以做的是建立使用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

使用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

+0

不錯! - 參考[聚合在這裏]選項(http://www.postgresql.org/docs/9.0/static/sql-expressions.html#SYNTAX-AGGREGATES) – StuartLC

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 
相關問題