34

この小さなデータベースを想像してみてください...

ダイアグラム

無効な ImageShack リンクの削除 - ボランティア データベースの図

テーブル

Volunteer     Event         Shift         EventVolunteer
=========     =====         =====         ==============
Id            Id            Id            EventId
Name          Name          EventId       VolunteerId
Email         Location      VolunteerId
Phone         Day           Description
Comment       Description   Start
                            End

協会

ボランティアは複数のイベントにサインアップできます。
イベントには、複数のボランティアが参加する場合があります。

イベントには複数のシフトがある場合があります。
シフトは 1 つのイベントのみに属します。

シフトには 1 人のボランティアのみが配置される場合があります。
ボランティアは、複数のシフトを担当する場合があります。

制約をチェック

  1. チェック制約を作成して、シフトのイベントにサインアップしていないボランティアがシフトに配置されないようにすることはできますか?

  2. チェック制約を作成して、重複する 2 つのシフトに同じボランティアが配置されないようにすることはできますか?

4

4 に答える 4

42

データの整合性を確保するのに最適な場所はデータベースです。開発者の中には、意図的であろうとなかろうと、一貫性のないものをデータベースに忍び込ませる方法を見つける人もいますのでご安心ください!

チェック制約を使用した例を次に示します。

CREATE FUNCTION dbo.SignupMismatches()
RETURNS int
AS BEGIN RETURN (
    SELECT count(*)
    FROM Shift s
    LEFT JOIN EventVolunteer ev
    ON ev.EventId = s.EventId
    AND ev.VolunteerId = s.VolunteerId
    WHERE ev.Id is null
) END
go
ALTER TABLE Shift ADD CONSTRAINT chkSignup CHECK (dbo.SignupMismatches() = 0);
go
CREATE FUNCTION dbo.OverlapMismatches()
RETURNS int
AS BEGIN RETURN (
    SELECT count(*)
    FROM Shift a
    JOIN Shift b
    ON a.id <> b.id
    AND a.Start < b.[End]
    AND a.[End] > b.Start
    AND a.VolunteerId = b.VolunteerId
) END
go
ALTER TABLE Shift ADD CONSTRAINT chkOverlap CHECK (dbo.OverlapMismatches() = 0);

新しいデータ整合性チェックのテストを次に示します。

insert into Volunteer (name) values ('Dubya')
insert into Event (name) values ('Build Wall Around Texas')

-- Dubya tries to build a wall, but Fails because he's not signed up
insert into Shift (VolunteerID, EventID, Description, Start, [End]) 
    values (1, 1, 'Dunbya Builds Wall', '2010-01-01', '2010-01-02')

-- Properly signed up?  Good
insert into EventVolunteer (VolunteerID, EventID) 
    values (1, 1)
insert into Shift (VolunteerID, EventID, Description, Start, [End]) 
    values (1, 1, 'Dunbya Builds Wall', '2010-01-01', '2010-01-03')

-- Fails, you can't start the 2nd wall before you finished the 1st
insert into Shift (VolunteerID, EventID, Description, Start, [End]) 
    values (1, 1, 'Dunbya Builds Second Wall', '2010-01-02', '2010-01-03')

テーブルの定義は次のとおりです。

set nocount on
if OBJECT_ID('Shift') is not null
    drop table Shift
if OBJECT_ID('EventVolunteer') is not null
    drop table EventVolunteer
if OBJECT_ID('Volunteer') is not null
    drop table Volunteer
if OBJECT_ID('Event') is not null
    drop table Event
if OBJECT_ID('SignupMismatches') is not null
    drop function SignupMismatches
if OBJECT_ID('OverlapMismatches') is not null
    drop function OverlapMismatches

create table Volunteer (
    id int identity primary key
,   name varchar(50)
)
create table Event (
    Id int identity primary key
,   name varchar(50)
)
create table Shift (
    Id int identity primary key
,   VolunteerId int foreign key references Volunteer(id)
,   EventId int foreign key references Event(id)
,   Description varchar(250)
,   Start datetime
,   [End] datetime
)
create table EventVolunteer (
    Id int identity primary key
,   VolunteerId int foreign key references Volunteer(id)
,   EventId int foreign key references Event(id)
,   Location varchar(250)
,   [Day] datetime
,   Description varchar(250)
)
于 2010-04-06T21:21:51.433 に答える
2

質問1は簡単です。Shift テーブルに EventVolunteer テーブルを直接参照させるだけで、準備は完了です。

于 2010-04-07T01:50:43.120 に答える
1

私がすることは、EventId と VolunteerId のペアに一意の制約を付けて、自動インクリメントする EventVolunteer テーブルに Identity 列を作成することです。Shift テーブルへの外部キーとして EventVolunteerId (ID) を使用します。これにより、データを多少正規化しながら、必要な制約をかなり簡単に適用できます。

これがあなたの一般的な質問に対する答えではないことは理解していますが、これがあなたの特定の問題に対する最善の解決策だと思います.

編集:

私は質問を完全に読むべきでした。この解決策により、1 人のボランティアが同じイベントで 2 つのシフトを行うことを防ぐことができます (重複していない場合でも)。おそらく、シフトの開始時刻と終了時刻を EventVolunteer に移動し、そのテーブルの時刻にチェック制約を設定するだけで十分ですが、Shift テーブルの外にシフト データがあり、直感的にはわかりません。

于 2010-04-06T21:30:08.607 に答える
-5

トリガーを使用してそれを行う方法がありますが、これはお勧めしません。ビジネス ロジックをデータベース レベルに配置しないことをお勧めします。データベースは、誰がいつ特定のシフトにスタッフを配置しているかを知る必要はありません。そのロジックは、ビジネス層に配置する必要があります。リポジトリ構築パターンを使用することをお勧めします。Scott Gutherie は、彼の mvc 1.0 の本の中で、これについて説明している非常に優れた章を持っています (以下のリンク)。

http://weblogs.asp.net/scottgu/archive/2009/03/10/free-asp-net-mvc-ebook-tutorial.aspx

于 2010-04-06T20:59:26.923 に答える