2016-04-17 74 views
0

在PostgreSQL 9.5數據庫中,我有不同類型的對象(每個對象存儲在它自己的表中),這些對象在DAG中是相互關聯的。爲了表示這個DAG,我設置了nodeedge表。該node表只存儲一個獨一無二的ID,這將是存儲對象的所有表共享:Postgres:插入WITH語句的SELECT查詢的結果

CREATE TABLE node (
    id SERIAL PRIMARY KEY NOT NULL 
); 

比方說,我的對象類型中的一種是在表library。忽略了其他領域,這個表很簡單:

CREATE TABLE library (
    uuid INTEGER NOT NULL REFERENCES node(id), 
    id TEXT PRIMARY KEY NOT NULL 
) 

我可以按如下id爲XXX一個單一的入口裝入library

WITH x AS (
    INSERT INTO node (id) VALUES (DEFAULT) RETURNING id 
) 
INSERT INTO library (id, uuid) VALUES ('XXX', (SELECT id FROM x)); 

不過,我有一個觀點import.library引用外部資源,並且我想從該視圖加載public.library整體。換句話說,我想要做這樣的事情:

INSERT INTO library (uuid, id) 
    WITH x AS (
    INSERT INTO node (id) VALUES (DEFAULT) RETURNING id 
) 
    SELECT (SELECT id FROM x), id FROM import.library; 

那是不可能的,因爲數據修改WITH聲明必須是在頂層。

我可以通過在DO語句中使用匿名函數達到相同的結果:

DO $$DECLARE l_id TEXT; 
BEGIN 
    FOR x IN SELECT id FROM import.library 
    LOOP 
    WITH x AS (
     INSERT INTO node (id) VALUES (DEFAULT) RETURNING id 
    ) 
    INSERT INTO library (id, uuid) VALUES (l_id, (SELECT id FROM x)); 
    END LOOP; 
END$$; 

這工作,但我仍想知道是否有可能做同樣的一個簡單的SQL語句,而不訴諸匿名功能。

回答

2

正如node表中的UUID是由序列生成的,我能想到的唯一方法是翻轉的插入順序:

WITH x AS (
    INSERT INTO library (uuid, id) 
    SELECT nextval('node_id_seq'), id 
    FROM import_library 
    returning uuid 
) 
INSERT INTO node (id) 
select uuid 
from x 
+0

@wjv:看到我的編輯 –

+0

這真的以爲外面的框!是的,這似乎是訣竅,所以我要擊中'接受'...謝謝! – wjv