2011-03-30 42 views
1

如何在發生錯誤時抑制此表中的'id'增量?錯誤增加

db=> CREATE TABLE test (id serial primary key, info text, UNIQUE(info)); 
NOTICE: CREATE TABLE will create implicit sequence "test_id_seq" for serial column "test.id" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "test_pkey" for table "test" 
NOTICE: CREATE TABLE/UNIQUE will create implicit index "test_info_key" for table "test" 
CREATE TABLE 

db=> INSERT INTO test (info) VALUES ('hello') ; 
INSERT 0 1 

db=> INSERT INTO test (info) VALUES ('hello') ; 
ERROR: duplicate key violates unique constraint "test_info_key" 

db=> INSERT INTO test (info) VALUES ('hello') ; 
ERROR: duplicate key violates unique constraint "test_info_key" 

db=> INSERT INTO test (info) VALUES ('goodbye') ; 
INSERT 0 1 

db=> SELECT * from test; SELECT last_value from test_id_seq; 

id | info 
----+--------- 
    1 | hello 
    4 | goodbye 
(2 rows) 

last_value 
------------ 
      4 
(1 row) 
+0

你能解釋爲什麼這是你的問題? – intgr 2011-03-30 20:04:31

+0

當我將一個較小的遠程數據庫轉儲到一個更大的主數據庫中時,我注意到了id序列中的跳轉。有幾個遠程數據庫,我需要達到高潮。原來我省略了表格佈局中的'id',並僅依靠 – 2011-03-30 21:10:45

+0

...原來我在表佈局中省略了'id',並僅依賴於UNIQUE鍵值。這可防止在再次插入相同行時創建重複行。 – 2011-03-30 21:18:57

回答

0

我想通了。

我需要在我的INSERT語句中編寫一個包裝函數。

數據庫一般每次只有一個用戶,所以'下一個ID'競爭條件很少見。我擔心的是,當我的(未提到的)'從遠程數據庫表中'拉行'將嘗試重新插入不斷增長的遠程數據庫表到主數據庫表中。我顯示的是行ID,我不希望用戶看到編號中缺失的數據。

反正這裏是我的解決方案:

CREATE FUNCTION testInsert (test.info%TYPE) RETURNS void AS ' 
BEGIN 
    PERFORM info FROM test WHERE info=$1; 
    IF NOT FOUND THEN 
    INSERT INTO test (info) VALUES ($1); 
    END IF; 
END;' LANGUAGE plpgsql; 
5

不能抑制這一點 - 並沒有什麼錯在你的ID值的差距。

主鍵是一個完全沒有意義的值,僅用於唯一標識表中的一行。

你不能依靠ID來永遠沒有任何差距 - 只要想想如果你刪除一行就會發生什麼。

簡單地忽略它 - 沒有什麼是錯

編輯
只是想提一提,這種行爲也明確手冊中規定:

爲了避免阻斷獲得大量併發交易從相同的序列,nextval操作永遠不會回滾

http://www.postgresql.org/docs/current/static/functions-sequence.html
(滾動到底)

+0

感謝您的澄清。我認爲INSERT語句是一個原子事務,在成功插入時會增加。 – 2011-03-30 21:25:20

+0

編號的差距對我的代碼是有益的。 – 2011-03-30 21:26:13

+0

@John Wasinger:INSERT本身**是**原子的,只有序列號的生成是非事務性的,因此不是原子的(btw:這在所有支持序列的DBMS中都是相同的) – 2011-03-31 06:53:06

1

想象不同的事務去插入。事務A得到id = 1事務B得到id = 2。事務B提交。交易A回滾。現在我們該怎麼辦?我們如何回滾A的順序而不影響B或以後的交易?

+0

+1非常好說明序列不回滾的原因之一,以及爲什麼不應該堅持/依賴「無間隙」序列。 – 2011-03-31 19:58:40