2012-05-28 94 views
1

我試圖在Postgres 8.4中創建一個使用CTE的plpgsql函數,但它給了我一個語法錯誤。他們不被允許?在plpgsql中使用CTE

(這樣的事情,請記住,我沒有我的代碼寫的。)

With foo as (SELECT id,a as alias FROM foo); 
UPDATE zoo SET b = alias FROM foo WHERE id = foo.id; 
^Error here 
+1

foo後刪除分號) – wildplasser

+0

這不是問題,我已經試過了。 – jpp1jpp1

回答

3
WITH foo as (
    SELECT id 
     , a AS zalias 
    FROM footable 
    ) 
UPDATE zoo z 
SET b = f.zalias 
FROM foo f 
WHERE z.id = f.id 
    ; 

注: 「別名」 是一個保留字。

Erwin Brandstetter對每條評論的更新:CTE在8.4的UPDATE語句中無效。你需要9.1或更高。 由於CTE實際上是一種即時視圖,因此可以將CTE主體放入視圖中,然後引用該視圖。

CREATE VIEW foo as (
    SELECT id 
     , a AS zalias 
    FROM footable 
    ); 
UPDATE zoo z 
SET b = f.zalias 
FROM foo f 
WHERE z.id = f.id 
    ; 
DROP VIEW foo; 
+0

'alias'是SQL:1999中的[保留字](http://www.postgresql.org/docs/current/interactive/sql-keywords-appendix.html),但不在標準的更高版本中,而不是在PostgreSQL中。所以自由使用應該是安全的。 –

+0

我站好了。我似乎記得,當函數沒有命名參數(pg 8.3?)別名是一個關鍵字。我仍然寧願避免它。 – wildplasser

+0

謝謝,我結束了使用臨時視圖的方法。 – jpp1jpp1

2

一個data modifying CTE(這是它是什麼)是在PostgreSQL的8.4不可用。

您的聲明可以在次要補丁中使用,如@wildplasser在PostgreSQL中演示的9.1或更高版本,其中引入了修改CTE的數據。

一個非常簡單的替代8.4將是一個子查詢

UPDATE zoo z 
SET b = f.alias 
FROM (SELECT id, a as alias FROM foo) f 
WHERE z.id = f.id; 

的例子可以進一步簡化(但也許在現實世界中情況更爲複雜):

UPDATE zoo z 
SET b = f.a 
FROM foo f 
WHERE z.id = f.id; 

記住以對WHERE子句中另外含糊的列名進行表格限定。

+0

這是一個真正的數據修改CTE嗎?看起來很常見,因爲它不是CTE內部的DDL語句。 – vyegorov

+0

@vyegorov:我一開始並不確定自己。但是我研究了這本手冊,並在8.4集羣上試用了測試用例:沒有喜悅。 –

+0

我猶豫還增加了最後的減少到'更新...從...' – wildplasser