2012-09-14 17 views
8

我有一個帶有SERIAL主鍵的表,還有一個ltree列,其值我想成爲這些主鍵的串聯。例如在同一INSERT期間,在另一列中的串行列的參考值

id | path 
---------- 
1 1 
2 1.2 
3 1.2.3 
4 1.4 
5 1.5 

我很好奇,如果有一種方法,在一個查詢做這樣的插入,例如

INSERT INTO foo (id, ltree) VALUES (DEFAULT, THIS.id::text) 

我可能在這裏超出範圍,試圖在一個查詢中做我應該做的兩件事(分組在事務中)。

+0

該路徑看起來不太可查詢。 – 2012-09-14 23:21:46

+0

我的路徑值基於此:http://stackoverflow.com/a/607379/39529 –

+0

PostgreSQL具有遞歸,公用表表達式,更容易和更快您的路徑解決方案/解決方法。 –

回答

7

你可以使用一個子查詢或寫入CTE來檢索值從序列一次和反覆使用它

WITH i AS (
    SELECT nextval('foo_id_seq') AS id 
    ) 
INSERT INTO foo (id, ltree) 
SELECT id, '1.' || id 
FROM i; 

Data-modifying CTE需要Postgres 9.1或更高版本。

如果你不知道該序列的名稱,你可以使用 pg_get_serial_sequence()代替:

WITH i AS (
    SELECT nextval(pg_get_serial_sequence('foo', 'id')) AS id 
    ) 
INSERT INTO foo (id, ltree) 
SELECT id, '1.' || id 
FROM i; 

如果表名稱爲「foo」可能不是橫跨在數據庫中的所有模式獨特,您可以架構 - 使它合格。如果任何名稱的拼寫是非標準的,你必須仔細報價:

pg_get_serial_sequence('"My_odd_Schema".foo', 'id') 



快速測試表明@Mark's idealastval()可能工作過:

INSERT INTO foo (ltree) VALUES ('1.' || lastval()); 
  • 您可以將id排除在查詢之外,serial列將自動分配。沒有區別。

  • 行之間不應該存在競爭條件。我quote the manual

currval

Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.

lastval

Return the value most recently returned by nextval in the current session. This function is identical to currval, except that instead of taking the sequence name as an argument it fetches the value of the last sequence used by nextval in the current session. It is an error to call lastval if nextval has not yet been called in the current session.

大膽重點煤礦。

但是,因爲@Bernard commented,它畢竟可能會失敗。再次想到,這是有道理的:不能保證缺省值被填充(並且在過程中調用nextval()之前lastval()被調用來填充第二列ltree。所以堅持第一個解決方案和nextval()是肯定的。

+0

正是我在找什麼,謝謝! –

+0

是否保證會先調用nextval()來查找下一個主鍵,以便lastval()不會拋出錯誤? – Bernard

+1

您的第二個建議會在PostgreSQL 9.5上拋出一個「55000錯誤:lastval尚未在此會話中定義」。 – Bernard

3

這個工作在我的測試:

INSERT INTO foo (id, ltree) VALUES (DEFAULT, (SELECT last_value from foo_id_seq)); 

我覺得有一個競爭條件存在,如果兩個刀片都在同一時間發生的事情,因爲這引用,而不是當前行的最後一個序列值。我個人更傾向於做這(僞代碼):

my $id = SELECT nextval('foo_id_seq'); 
INSERT INTO foo (id, ltree) VALUES ($id, '$id'); 
相關問題