2016-10-20 49 views
0

我想創建一個觸發器,在該觸發器中,如果其中一個字段設置爲一個值的前一個條目不可能添加或更新條目。獨特列的觸發器

Let's把一個例子±

如下表:

id name   type, description, (some other fields) 
1 'Manuel'  'HUMAN' ... 
2 'Manuel'  'DOG' ... 
3 'Other name' 'HUMAN' ... 

如果我要添加新條目是這樣的:

insert into table_name (name, type, description,...) 
values ('Manuel', 'HUMAN', 'first entry', ...) 

它不應該因爲工作它不應該被允許爲Manuel這個名字添加另一個HUMAN類型。

但是,它應該被允許這樣做:

insert into table_name (name, type, description, ...) values ('Manuel', 'DOG', 'another description') 

(對不起,不能夠找到一個更好的例子:))

因此,基本的想法是,每個名稱,它應該只允許一個人入口類型。

我創造了這個觸發,但它不工作:

CREATE OR REPLACE TRIGGER TABLE_TYPE_REL 
BEFORE INSERT OR UPDATE ON table_name 
REFERENCING NEW AS NEW OLD AS OLD 
FOR EACH ROW 
WHEN (NEW.TYPE = 'HUMAN') 
declare @check int 

select @check = count(*) 
from table_name as f 
where f.type = 'HUMAN' 

if @check <> 0 
begin 
    rollback transaction 
    raiserror('Only one name, human is allowed.', 16, 1) 
end 

;

任何線索?

+2

我想你想的唯一約束在觸發 – Kritner

+2

行是不是這個矯枉過正? (name,type)上的唯一約束不會比觸發器足夠多並且更健壯? – Boneist

+0

爲什麼你要爲Oracle問題展示MS SQL-Server代碼? – OldProgrammer

回答

4

你的標籤說你正在使用Oracle。您發佈的觸發器代碼是針對SQL Server的。我會假設你實際上在使用Oracle,而你的觸發器「不起作用」的原因是它是用錯誤的語言編寫的(另外,包含錯誤堆棧而不是說某些內容「不工作」 「)

這聽起來像你想有一個基於函數的索引只包括其中type='HUMAN'

CREATE UNIQUE INDEX idx_one_human 
    ON table_name(CASE WHEN type = 'HUMAN' 
         THEN name 
         ELSE null 
        END); 
+1

@Manuelarte - 作爲一般原則,將觸發器視爲「最後的手段」,只有在其他所有事情都失敗時纔會使用的工具。當你可以找到使用它們的解決方案時,約束和索引是更好的選擇。 Namaste Justin提供簡單,優雅和可靠的解決方案。 – mathguy

+0

@JustinCave謝謝你的回答。這正是我們想要的。唯一可能發生的事情是,也許,如果我們沒有完成唯一索引,那麼我們可能擁有它的錯誤信息不是100%可讀的,對嗎? – Manuelarte

+0

@Manuelarte - 如果您想用自定義錯誤消息引發異常,您總是可以捕獲'dup_val_on_index'異常並使用'raise_application_error'來引發自定義異常。 –