如何在 oracle 中創建觸發器以防止日期範圍重疊
我正在學習 Oracle,但遇到了問題。
貓桌:
CREATE TABLE training ( id_training NUMBER, id_user NUMBER, start_training DATE, end_training DATE );
我想
id_user
用另一個start_training
和end_training
日期插入相同的內容。我必須創建一個觸發器,以確保日期不會位於任何先前註冊的日期start_training
和end_training
日期之間。我正在考慮在觸發器中使用
:old
and:new
,但如果我insert
在觸發器中使用 an ,則數據:old
總是null
.
:old
如果我在觸發器中插入新值,如何克服更改值的問題?
這是一個草圖。我從 db<>fiddle 上的觸發器中得到一個錯誤,但你應該能夠使用這個想法。首先,我將在表上添加一些約束,這將大大簡化事情:
CREATE TABLE training ( id_user NUMBER NOT NULL , start_training DATE NOT NULL , end_training DATE , constraint ak1_training unique (id_user, start_training) , constraint c1_training check (start_training <= end_training) );
我假設
id_training
是某種自動遞增數字,所以我把它省略了,因為它與這個想法無關。評論:
- 除了 end_training 之外的所有屬性都不為空
- is_user 和 start_training 是唯一的
- start_training 早於或等於 end_training。如果 end_training 為空,則滿足約束。
.
CREATE OR REPLACE TRIGGER training_validation BEFORE INSERT ON training FOR EACH ROW BEGIN IF EXISTS ( select 1 from training t where t.id_user = new.user and (t.start_training between new.start_training and coalesce(new.end_training, current_date)) or coalesce(t.start_end, current_date) between new.start_training and coalesce(new.end_training, current_date)) ) THEN RAISE_APPLICATION_ERROR( -20001, 'Some msg ...' ); END IF; END training_validation;
我得到錯誤:
PLS-00103:在預期以下情況之一時遇到符號“文件結尾”:; 符號“;” 被替換為“文件結尾”以繼續。
FWIW,我在Google上搜尋的瑣碎範例中遇到了同樣的錯誤
無論如何,如果在 new.start_training 和 new.end_training 之間存在先前的 start_training,那麼這個想法是拋出一個錯誤。由於 new.end_training 通常為空,我們通過合併將其映射到 current_date。以同樣的方式,我們檢查之前的 start_training。
請注意,如果 start_training 不為空,我們就不必考慮可能的空值。也因為我們知道:
start_training <= end_training
我們也可以依靠這一點。
即使您可以更改觸發器中的 .old 和/或 .new 值,您會將它們更改為什麼?
據推測,使用者將根據他們的可用性選擇參加培訓活動。當他們點擊“保存”時,讓數據庫“神奇地”將其更改為其他事件並不能帶來使用者友好的體驗。
我認為你能做的最好的事情就是引發一個錯誤,扔掉整個交易,讓他們選擇另一個事件。