2017-03-02 21 views
1

SQL Serverデータベースを開始日と終了日に制限して、リソースを予約することができないようにしました(つまり、重複または重複予約なし)。日付範囲のSQL Server規則

私のリソースは、テーブルがRESOURCEID、開始日、終了日 のように見える、ステータス

は、だから私は、リソース#1を持って言うことができますよう番号が付けられていると仮定します。私は、2011年1月1日から2011年1月16日までのご予約と、2011年1月10日から2011年1月18日までの別々の予約について、同じリソースでは予約できないようにしたいと考えています。

さらに複雑な問題が2つあります。リソースのStartDateは、リソースのEndDateと同じにすることができます。したがって、2011年1月8日から2011年1月16日まで、2011年1月20日から2011年1月20日までは、1人が他の人のチェックアウトと同じ日にチェックインすることができます。

さらに、ステータスフィールドは、リソースの予約がアクティブかキャンセルかを示します。キャンセルされた予約はすべて無視されます。

保存時にコード(Stored Procsおよび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 

別のオプションは、重複を見つけ、インデックス付きビューを作成し、独自のを置くことです:それは重複を検出した場合は、代わりにトランザクションをロールバックFOR INSERT、UPDATEトリガーを作成することによって、これを強制するためにトリガーを使用することができます1つ以上のレコードが存在する場合、そのビューに対する制約が違反します。これは、通常、二重の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 

それがすべてクリアされている場合、その後、あなたの関数を作成します。

このような関数を書くには、いくつかの方法があります。我々はStartDateEndDateをスキップしてのみ上記のクエリのようなReservationIdに基づいて何かを使用しますが、私は、一例としてこれを使用することができます:

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 

最終:テストそれ。