2012-09-18 46 views
15

我的目標是在表中插入新行時自動插入主鍵字段。currval尚未定義此會話,如何獲取多會話序列?

如何獲取PostgreSQL中從會話到會話的序列?

[email protected]:/home/yves$ psql -d test 
Mot de passe : 
psql (8.4.13) 
Saisissez « help » pour l''aide. 

test=> create sequence test001 start 10; 
CREATE SEQUENCE 
test=> select currval('test001'); 
ERREUR: la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session 
--- current value not yet defined this session (???) 
test=> select setval('test001', 10); 
setval 
-------- 
     10 
(1 ligne) 

test=> select currval('test00'); 
    currval 
--------- 
     10 
(1 ligne) 

test=> \q 
[email protected]:/home/yves$ psql -d test 
Mot de passe : 
psql (8.4.13) 
Saisissez « help » pour l''aide. 

test=> select currval('test001'); 
ERREUR: la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session 
+0

一個序列的整個目的是讓它的本地會話。你不能「把」currval「交」給另一個會話。你爲什麼認爲你需要這個?爲什麼不在一次交易中做所有事情? –

+0

@a_horse_with_no_name,因爲我同時打開了兩個會話:管理員和生產者。所以我必須有兩個單獨的會議。 –

+0

爲什麼不創建一個單一的序列,然後在兩個會話之間分享?他們得到了獨特的ID,完成了工作。 –

回答

10

這可能比你想象的更簡單...

我的目標是獲得自動插入時 一個主鍵字段的表中插入新行。

只需設置列的默認值:

ALTER TABLE tbl ALTER COLUMN tbl_id SET DEFAULT nextval('my_seq'::regclass); 

或者更簡單的是,創建一個serial類型主鍵的表來開始:

CREATE TABLE tbl(
    tbl_id serial PRIMARY KEY 
,col1 txt 
    -- more columns 
); 

它創建一個專用序列並自動設置tbl_id的默認值。

如果在INSERT中沒有提及,則自動爲tbl_id分配附加順序中的下一個值。與任何會話,併發與否。

INSERT INTO tbl(col1) VALUES ('foo'); 

如果你想在新tbl_id回用它做什麼:

INSERT INTO tbl(col1) VALUES ('foo') RETURNING tbl_id; 
59

currval將返回在當前會話中序列生成的最後一個值。因此,如果另一個會話爲序列生成新值,您仍然可以檢索由會話生成的最後一個值,從而避免錯誤。

但是,要獲得任何會話最後生成的值,你可以用上面的:

SELECT last_value FROM your_sequence_name; 

要小心,如果該值用於其他會話與未提交(或中止)的交易,你使用此值作爲參考,您可能會收到錯誤。通常人們只需要currval甚至退還setval

+0

如何獲取其他會話生成的最後一個值。如果我使用歌手DB用戶,它仍然會影響準確性嗎? – Volatil3

+0

Actionally有趣的是,爲什麼'SELECT * FROM sequence'的可能性在官方文檔中甚至沒有提及? – Eugene

1

其實NEXTVAL將推進序列並返回新值,所以這將是你的問題的答案。

currval將返回最近使用nextval獲取的指定序列值(如果當前會話中沒有nextval,這可能會失敗)。

0

這個問題似乎是間歇性的,爲了保持一致性使用CTE獲得插入序列當前會話

插入AS( INSERT INTO notifn_main(notifn_dt,stat_id) SELECT NOW(),22 FROM notifn RETURNING id) SELECT id from inserted INTO tmp_id;

0

我會給這個問題一個實際的答案。 我的程序和我的psql終端使用我的數據庫服務器;所以有多個會話。目前我在我的psql終端:

fooserver=> select currval('fusion_id_seq'); 
ERROR: currval of sequence "fusion_id_seq" is not yet defined in this session 
fooserver=> select nextval('fusion_id_seq'); 
nextval 
--------- 
    320032 
(1 row) 

fooserver=> select currval('fusion_id_seq'); 
currval 
--------- 
    320032 
(1 row) 

看起來你只能看到你自己的會話中的值。這也會影響另一個會話的結果。這可能與服務器的多線程隔離不同的會話有關。計數器(在psql中是串行的)是一個共享對象。在我看來,只要計數器被正確鎖定以確保只有一個線程(會話)可以增加計數器(原子操作),該會話應該能夠獲得計數器的當前值。但我可能在這裏是錯誤的(不是數據庫服務器編寫者的專家)。