0

我已經在DB上使用以下字段作爲PK:DOC_IDSECTION_IDSET_IDCELL_ID。正如您可以推斷的那樣,這是指一組Excel電子表格。更新多個記錄,臨時密鑰重疊

除了這些字段,我還有一個CELL_ROW字段和CELL_COL字段。 與SET_ID獨特),他們形成一個替代關鍵。因此,至少在理論上,如果我想交換兩個單元格的座標,我需要釋放該約束,或者使用第三個臨時自由位置(例如A100000例如)。

假設我有以下細胞:

DOC_ID | SECTION_ID | SET_ID | CELL_ID | CELL_ROW | CELL_COL 
--------|------------|--------|---------|----------|---------- 
    5 |  456 | 8778 | 15045 | 5  | 4 
    5 |  456 | 8778 | 15048 | 5  | 5 

而且假設我有我從中執行UPDATE到主表中的下列臨時表:

DOC_ID | SECTION_ID | SET_ID | CELL_ID | CELL_ROW | CELL_COL 
--------|------------|--------|---------|----------|---------- 
    5 |  456 | 8778 | 15045 | 5  | 5 
    5 |  456 | 8778 | 15048 | 5  | 4 

理論上,UPDATE應提出例外...

但剛試過,它的工作原理!

你能解釋一下爲什麼嗎? Oracle是否將其作爲原子操作執行,因此只有在整個操作(而不是每個記錄的記錄)之後檢查約束?

MS SQL Server 2008 r2和Postgres在這種情況下的表現如何?

回答

1

PostgreSQL將拋出一個錯誤,除非你推遲了唯一約束(然後你不能將它用作外鍵)。我不確定SQL Server。

簡而言之,您可能想稱之爲Postgres或PostgreSQL。調用Postgre是一個跡象,表明你與社區的聯繫太少,無法糾正。 PostgreSQL的

更多信息

PostgreSQL的元組檢查在元組更新時間限制。這意味着即使在以不違反唯一約束的原子方式更新集合的情況下,也會違反唯一約束。這導致了一些有趣的解決方法,比如將一個整數鍵乘以-1,然後在下一次更新中再次乘以-1並加1。

+0

感謝您的回答!其實,我沒有與Postgres社區聯繫。在我的公司,我們提供了對所提到的DBMS的全面支持,但自從我一年前聘用PostgreSQL後,我從未從事過Postgres工作。 – Teejay 2013-02-26 13:16:12

+0

我在SQL Server上試過,似乎沒有問題。現在,對於PG,是否有辦法改變一個約束並將其設置爲「DEFERRABLE」?或者這個屬性只能在創建表格時設置?請注意,約束不是FK。 – Teejay 2013-02-26 15:19:27

+0

決定在數據庫創建時將其設置爲DEFERRABLE以解決問題。 – Teejay 2013-02-26 23:34:01

1

我試圖在PostgreSQL和預期引發重複鍵錯誤:

create table t (
    doc_id integer, 
    section_id integer, 
    set_id integer, 
    cell_id integer, 
    cell_row integer, 
    cell_col integer, 
    primary key (doc_id, section_id, set_id, cell_id), 
    unique (set_id, cell_row, cell_col) 
); 

insert into t (doc_id, section_id, set_id, cell_id, cell_row, cell_col) 
values 
(5, 456, 8778, 15045, 5, 4), 
(5, 456, 8778, 15048, 5, 5); 

create temporary table t_temp (
    doc_id integer, 
    section_id integer, 
    set_id integer, 
    cell_id integer, 
    cell_row integer, 
    cell_col integer 
); 

insert into t_temp (doc_id, section_id, set_id, cell_id, cell_row, cell_col) 
values 
(5, 456, 8778, 15045, 5, 5), 
(5, 456, 8778, 15048, 5, 4); 

update t 
set 
    cell_col = t_temp.cell_col 
from t_temp 
where 
    t.doc_id = t_temp.doc_id 
    and t.section_id = t_temp.section_id 
    and t.set_id = t_temp.set_id 
    and t.cell_id = t_temp.cell_id 
; 
ERROR: duplicate key value violates unique constraint "t_set_id_cell_row_cell_col_key" 
DETAIL: Key (set_id, cell_row, cell_col)=(8778, 5, 5) already exists. 

我能做到這一點,如果約束被設置爲deferrable。檢查您的關鍵字的創建表語句。

+0

感謝您的回答! – Teejay 2013-02-26 13:20:58