2012-09-05 54 views
2

我想添加一些東西到一個表(觸發?),因此,確切地說,每個ID只有一行具有特定列的特定值。因此,如果運行的語句不是這種情況,那麼將拋出異常並且插入將被回滾。將數據約束寫入表

讓我們來看看這個模式。

ID Current Value 
1  Y   0 
1  N   0 
1  N   2 
2  Y   2 

而我想要的約束是對於每個ID,恰好一行的電流爲'Y'。

因此,這些語句將不會被執行,並返回相應的錯誤:

insert into table values (1,'Y',1); 
insert into table values (3,'N',2); 
update table set current = 'N' where ID = 1; 

我有兩個問題:

  1. 這是個好主意,這種約束邏輯編碼成你的表,還是最適合操作數據的應用程序保存的?爲什麼?

  2. 這怎麼辦? oracle提供了什麼樣的工具來創建這樣的約束?

回答

2

如果您可以以聲明方式(而不是程序方式,例如使用觸發器)指定它,那麼最好。特別是因爲沒有某種鎖定算法的觸發器由於嘗試同時插入/更新表的併發會話而無法工作。

在這種情況下,最簡單的解決方案是一個獨特的,基於函數的索引,例如:

CREATE UNIQUE INDEX only_one_current ON thetable 
    (CASE WHEN Current = 'Y' THEN ID END); 

表達式爲NULL,如果電流=「N」,以及所有空索引中的行不存儲,這意味着唯一性約束將僅適用於Current ='Y'的行。

+0

優秀的答案。 – hol

+0

謝謝,這確實看起來像我正在尋找!我不明白這個語法,但我會玩這個,並在我確認後回來接受答案。 – Jeremy

+0

@Jeremy,像其他任何索引一樣 - 普通索引就像'CREATE UNIQUE INDEX index_name ON table_name(column_name)'。在這種情況下,我用一個將非當前行映射爲NULL的表達式替換了'column_name'。 –

-1

我認爲你在找什麼只是一個獨特的約束。 您可以使用下面的語句添加它,以便表中只能存在ID,Current的唯一組合。

ALTER TABLE table_name add CONSTRAINT constraint_name UNIQUE (ID,Current); 
+0

-1 OP希望允許具有相同ID的多行,其中Current ='N'。 –

+0

@Jeffery: - 每個ID恰好有1行具有特定列的特定值 - >這是什麼意思? –

+0

請注意,在問題中,他有2行,ID = 1,但Current = N.這些行應該被允許,但是您的約束將會禁止它們。 –