2011-07-26 82 views
1

可視性說我有一個功能副本(整數,出整數)它創建表MYTABLE通過標識的行的副本中參數。新行的標識符被返回。PostgreSQL的 - 更新 - 功能

我想將更新應用到新的/重複的行,而不是舊行:

update mytable set field = ... where identifier = (select copy(1)); 

這似乎並沒有工作。副本已創建,但仍具有舊值。我期望在where子句被評估時新行不可見。也就是說,沒有更新正在發生。

下無法正常工作或:

update mytable set field = ... from copy(1) as c where identifier = c.copy; 

當我把它寫在兩行,它完美的作品:

select copy(1); 
update mytable set field = ... where identifier = <value returned by copy(1)>; 

我有兩個問題:

(1)這可以在一個班輪內完成嗎?

(2)是否有可能寫一個重寫規則或觸發這樣的,我甚至可以寫

​​

,同時在後臺創建副本和更新的重複/新行應用?我無法看到一個無法終止的解決方案。

示例代碼

drop table if exists t cascade; 

create table t 
(
    identifier serial primary key, 
    title  text 
); 

create or replace function copy(in integer, out integer) as 
$$ 
     begin 
       insert into t (title) values ((select title from t where identifier = $1)) returning identifier into $2; 
     end 
$$ language plpgsql; 

insert into t (title) values ('title - old'); 
update t set title = 'title - new' where identifier = (select copy(1)); 
select * from t; 

請注意,在拷貝()行通常是取入一個單獨的變量。爲了簡單起見,我直接在這個示例代碼中獲取標題。

+0

你可以發佈'copy()'函數代碼嗎? – Kev

+0

Kev,我加了一些示例代碼來說明這一點。請注意,這是快速和骯髒的,但它解釋了我的問題,我希望。 –

回答

1

我認爲這不是出於同樣的原因,除了從PG 9.1開始,你不能使用語句返回。這應該在9.1做工精細:

drop table if exists t cascade; 

create table t (
    identifier  serial  primary key, 
    title       text 
); 

insert into t (title) values ('title - old'); 

with copy as (
insert into t (title) select title from t where identifier = 1 
returning identifier 
) 
update t set title = 'title - new' from copy where t.identifier = copy.identifier; 

select * from t; 

編輯:可能9.0的建議沒有工作。

+0

可以確認第二個片段在9.04中不起作用。 – Kev

+0

剝光。感謝您檢查(我不能,在iPad上)。 –

+0

我嘗試了9.1測試版3的建議,它仍然返回一個新行,但舊標題。 (我已經在update語句中添加'from copy')。有任何想法嗎? –