Oracle

如何在 oracle 中創建觸發器以防止日期範圍重疊

  • November 26, 2019

我正在學習 Oracle,但遇到了問題。

貓桌:

CREATE TABLE training
(
  id_training      NUMBER,
  id_user          NUMBER,
  start_training   DATE,
  end_training     DATE
);

我想id_user用另一個start_trainingend_training日期插入相同的內容。我必須創建一個觸發器,以確保日期不會位於任何先前註冊的日期start_trainingend_training日期之間。

我正在考慮在觸發器中使用:oldand :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 &lt;= 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 &lt;= end_training

我們也可以依靠這一點。

即使您可以更改觸發器中的 .old 和/或 .new 值,您會將它們更改為什麼

據推測,使用者將根據他們的可用性選擇參加培訓活動。當他們點擊“保存”時,讓數據庫“神奇地”將其更改為其他事件並不能帶來使用者友好的體驗。

我認為你能做的最好的事情就是引發一個錯誤,扔掉整個交易,讓他們選擇另一個事件。

引用自:https://dba.stackexchange.com/questions/213869