2017-03-02 2 views
1

SQL Server 데이터베이스를 시작 날짜와 종료 날짜로 제한하여 리소스를 예약 할 수 없도록했습니다 (즉, 중복되거나 예약이 중복되지 않음). 날짜 범위에 대한 SQL Server 조건

내 자원 테이블 의 ResourceId, STARTDATE, 종료 날짜, 상태

처럼 보이는 그런 번호 그래서 자원 번호를 말할 수있다 가정하자 1. 2011 년 1 월 1 일부터 2011 년 1 월 16 일까지는 예약 할 수 없으며 같은 리소스에 대해서는 2011 년 1 월 10 일부터 2011 년 1 월 18 일까지 별도 예약이 필요합니다.

두 가지 더 복잡한 경우 리소스의 StartDate는 리소스의 EndDate와 같을 수 있습니다. 따라서 2011 년 1 월 8 일부터 2011 년 1 월 16 일까지 및 2011 년 1 월 20 일부터 2011 년 1 월 20 일까지 1 월 16 일부터 17 일까지는 괜찮습니다 (즉, 한 사람이 다른 날 체크 아웃 한 당일에 체크인 할 수 있음).

또한 상태 필드는 리소스 예약이 활성 또는 취소 중임을 나타냅니다. 따라서 우리는 취소 된 모든 예약을 무시할 수 있습니다.

절약 할 때 Code (Stored Procs and C#)에서 이러한 중복 또는 이중 예약 예약을 방지했지만 DB Contraint를 추가하여 추가 보호 계층을 추가하고자합니다.

SQL Server에서 가능합니까? 사전

+0

방아쇠를 당기는 등의 일을 할 수는 있지만, 제약 조건에서 필요한 것을 할 수 있다고는 생각하지 않습니다. – pmbAustin

+1

[날짜 범위 중복 체크 제약] (http://stackoverflow.com/questions/12035747/date-range-overlapping-check-constraint) – SqlZim

답변

0

당신은 확실히 STARTDATE 쉽게 종료 날짜 또는 그 이전에 충분한 지 확인하기 위해 CHECK 제약 조건을 사용할 수있는

감사 :

제약 조건이 중복 날짜 범위를 방지에 도움이되지 않습니다
CONSTRAINT [CK_Tablename_ValidDates] CHECK ([EndDate] >= [StartDate]) 

.

CREATE TRIGGER [TR_Tablename_NoOverlappingDates] FOR INSERT, UPDATE AS 
IF EXISTS(SELECT * from inserted INNER JOIN [MyTable] ON blah blah blah ...) BEGIN 
    ROLLBACK TRANSACTION; 
    RAISERROR('hey, no overlapping date ranges here, buddy', 16, 1); 
    RETURN; 
END 

또 다른 옵션은 중복을 찾는 인덱싱 된 뷰를 작성하고 고유을 배치하는 것입니다 : 그것은 중복을 감지하면 대신 트랜잭션을 구르는에 대한 INSERT, UPDATE 트리거를 작성하여이를 시행하기 위해 트리거를 사용할 수 있습니다 두 개 이상의 레코드가있는 경우 위반되는 해당 뷰에 대한 제한 조건. 이것은 일반적으로 중복 된 id를 선택하는 집계 뷰에 2 열 데카르트가 결합 된 더미 테이블로 수행됩니다. 따라서 중복 된 하나의 레코드는 고유 인덱스가있는 동일한 위조 된 id 값을 갖는 뷰에서 2 행을 반환합니다.

두 가지 모두를 수행 했으므로 트리거 방법이 더 좋습니다.

0

여기에서 답변 : Date range overlapping check constraint.

첫째, 확인이 존재하지 않는 중복을 확인하십시오 :

select * 
from dbo.Reservation as r 
where exists (
    select 1 
    from dbo.Reservation i 
    where i.PersonId = r.PersonId 
    and i.ReservationId != r.ReservationId 
    and isnull(i.EndDate,'20990101') > r.StartDate 
    and isnull(r.EndDate,'20990101') > i.StartDate 
); 
go 

그것을 모두 지우기 경우, 함수를 만듭니다.

함수를 작성하는 몇 가지 방법이 있습니다.당신의 제약 다음 추가

create function dbo.udf_chk_Overlapping_StartDate_EndDate (
    @ResourceId int 
    , @StartDate date 
    , @EndDate date 
) returns bit as 
begin; 
    declare @r bit = 1; 
    if not exists (
    select 1 
    from dbo.Reservation as r 
    where r.ResourceId = @ResourceId 
     and isnull(@EndDate ,'20991231') > r.StartDate 
     and isnull(r.EndDate,'20991231') > @StartDate 
     and r.[Status] = 'Active' 
    group by r.ResourceId 
    having count(*)>1 
) 
    set @r = 0; 
    return @r; 
end; 
go 

: 마지막

alter table dbo.Reservation 
    add constraint chk_Overlapping_StartDate_EndDate 
    check (dbo.udf_chk_Overlapping_StartDate_EndDate(ResourceId,StartDate,EndDate)=0); 
go 

을 : 우리는 StartDateEndDate 건너 뛰고에만 위의 쿼리와 같은 ReservationId에 따라 뭔가를 사용하지만, 나는 예로 사용 할 수있는 테스트 그것.