簡體   English   中英

使用SQL觸發器阻止插入重疊的日期范圍

[英]Prevent inserting overlapping date ranges using a SQL trigger

我有一個簡化的表格如下:

create table Test
(
 ValidFrom date not null,
 ValidTo date not null,
 check (ValidTo > ValidFrom)
)

我想編寫一個觸發器來阻止插入與現有日期范圍重疊的值。 我寫了一個如下所示的觸發器:

create trigger Trigger_Test
on Test
for insert
as
begin
 if exists(
  select *
  from Test t
   join inserted i
   on ((i.ValidTo >= t.ValidFrom) and (i.ValidFrom <= t.ValidTo))
 )
 begin
  raiserror (N'Overlapping range.', 16, 1);
  rollback transaction;
  return
 end;
end

但它不起作用,因為我新插入的記錄是兩個表Test的一部分,並在觸發器內插入 因此,插入表中的新記錄始終在Test表中與其自身連接。 觸發器將始終恢復轉換。

我無法區分新記錄和現有記錄。 因此,如果我排除相同的日期范圍,我將能夠在表格中插入多個完全相同的范圍。

主要問題是

是否可以編寫一個可以按預期工作的觸發器,而無需在Test表中添加額外的標識列,我可以使用它來從exists()語句中排除新插入的記錄,如:

create trigger Trigger_Test
on Test
for insert
as
begin
 if exists(
  select *
  from Test t
   join inserted i
   on (
    i.ID <> t.ID and /* exclude myself out */
    i.ValidTo >= t.ValidFrom and i.ValidFrom <=t.ValidTo
   )
 )
 begin
  raiserror (N'Overlapping range.', 16, 1);
  rollback transaction;
  return
 end;
end

重要提示 :如果不可能沒有身份是唯一的答案,我歡迎您提出一個合理的解釋原因。

我知道這已經回答了,但我最近解決了這個問題,並提出了一些有效的方法(並且對每個插入的行執行單例搜索都表現良好)。 請參閱本文中的示例: http//michaeljswart.com/2011/06/enforcing-business-rules-vs-avoiding-triggers-which-is-better/

(並且它沒有使用標識列)

兩個小的改變,一切都應該工作得很好。

首先,在觸發器中添加where子句,以從連接中排除重復記錄。 那么你不會將插入的記錄與自己進行比較:

select *
  from testdatetrigger t
   join inserted i
   on ((i.ValidTo >= t.ValidFrom) and (i.ValidFrom <= t.ValidTo))
  Where not (i.ValidTo=t.Validto and i.ValidFrom=t.ValidFrom)

除此之外,這將允許精確的重復范圍,因此您必須在兩列中添加唯一約束。 實際上,您可能希望每列都有唯一約束,因為默認情況下,同一天開始(或完成)的任何兩個范圍都是重疊的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM