2011-05-02 51 views
0

如果我創建一個表具有獨特的contraint,例如:如何捕捉唯一約束錯誤在PostgreSQL

CREATE TABLE distributors (
    did  integer, 
    name varchar(40) UNIQUE 
); 

,如果我嘗試輸入與已經存在的名稱的條目會發生什麼。我試圖這樣做,它只是退出而不顯示任何錯誤消息。有沒有辦法檢查一個新條目是否實際插入?

+0

不會插入任何數據,從數據庫中解釋失敗的方式取決於您使用何種數據訪問它? libpq/odbc等? – 2011-05-02 11:39:11

+0

我正在使用libpq,那會返回什麼? – error 2011-05-02 11:45:27

+0

用PQresultStatus檢查PQExec的結果; http://www.postgresql.org/docs/8.0/static/libpq-exec.html – 2011-05-02 11:50:00

回答

0

如果你試圖插入已存在的名稱記錄,您會收到錯誤信息是這樣的:

ERROR: duplicate key value violates unique constraint "distributors_name_key" 
DETAIL: Key (name)=(aaa) already exists. 

和記錄不會被插入。
如果從全部級別執行此操作,則會拋出類似於此消息的異常。程序員應該如何處理這個異常。

如果您的ID字段是自動生成的(SERIAL或BIGSERIAL),並且您只插入名稱,如果您插入已存在的名稱,則即使未插入任何記錄,ID序列也會增加1。

爲了避免在INSERT之前進行「SELECT」查詢來檢查,它的記錄已經存在。可以做到所有在一個事務中,在僞代碼:

BEGIN TRANSACTION; 
int records = SELECT name FROM table WHERE name = 'aaa' FOR UPDATE; //FOR UPDATE to lock the row from being read by other user until transaction finishes. 
if (records == 0) 
    INSERT INTO table VALUES (1, 'aaa'); 
else 
    MessageBox.Show("Record already exists"); 
COMMIT TRANSACCTION; 
+0

@ mj82:請注意,上面的代碼有時也會返回唯一的違規行爲。 – 2011-05-02 12:40:18

+0

@depesz:你能準確地說出它會發生什麼情況嗎? – mj82 2011-05-02 12:49:09

+0

@ mj83:如果有人在SELECT完成之後但INSERT執行之前插入一行 – 2011-05-02 12:56:02

2

如果插入失敗比應該有的錯誤代碼設置的地方,通過您所使用的接口的一些方法可讀 - 更多細節肯定是在文檔到您的訪問庫/模塊。

或者您可以將插入更改爲:

INSERT INTO distributors (did, name) values (...) RETURNING did; 

如果它不返回任何東西 - 出現了錯誤。