2011-07-31 8 views
1

私は、関係の各側からのエンティティが一度に1つしかリンクされていないか、またはリンクされていないという制約のある多対多の関係を確立したいと考えています。リレーショナルデータベース内で制約の多い多対多関係を表現する最良の方法は何ですか?

この問題によく似たのは、車と駐車場です。多くの車と多くのスペースがあります。 1つのスペースには1台の車を入れることができます。車は一度に1つのスペースにしか入れることができないか、またはスペースを空けない(駐車していない)。

CarsテーブルとSpacesテーブル(場合によってはリンクテーブル)があります。 carsテーブルの各行は、自動車の一意のインスタンス(ライセンス、所有者、モデルなど)を表し、Spacesテーブルの各行は、固有の駐車スペース(ガレージフロアレベル、行および番号のアドレス)を表します。これらのテーブルをデータベースにリンクし、上記の制約を適用する最善の方法は何ですか?

(私はC#、NHibernateはとOracleを使用しています。)

答えて

2

あなたは歴史を心配していない場合 - 「今」についての唯一の心配つまり、次の操作を行います。

create table parking (
    car_id references car, 
    space_id references space, 
    unique car_id, 
    unique space_id 
); 

を両方のクルマと空間参照がユニークにすることで、あなたは一つのリンクの最大に各側面を制限しますつまり、車は、最大で1つのスペースに駐車することができ、スペースには、最大で1つの自動車を駐車することができます。

+0

これは理にかなっています。それぞれの外部キーの一意性制約は、後の制約を強制します。 – CyberMonk

0

3番目のテーブルを作成します。

parking 
-------- 
car_id 
space_id 
start_dt 
end_dt 

制約のため、あなたの状況に問題があると思うのは、交差テーブル自体に対して複雑なルールをチェックする必要があるということです。トリガーでこれを試すと、突然変異が報告されます。

これを回避する1つの方法は、テーブルを複製し、このレプリケーションに対してクエリに対してクエリを行うことです。

+0

ありがとう、私はリンクテーブルに傾いていた。しかし、私はレプリケーションがどのように適用されるかを理解していません。これはどのように制約を強制するのでしょうか?また、私は自分のシナリオで時間について心配していません - ちょうどガレージの現在の状態。 – CyberMonk

1

すべてのリレーショナルデータベースでは、多対多リレーションシップには、その組み合わせを表すための結合テーブルが必要です。答えに示されているように(しかし、理論的な背景はあまりありません)、すべての組み合わせを格納するテーブルを中央に置かずに多対多の関係を表現することはできません。

また、ヒストリを必要としない場合にのみ問題を解決するということも解決策に記載されています。現実の世界のアプリケーションでは、ほとんどの場合、履歴データを表現する必要があることを伝えてください。これを行うには多くの方法がありますが、単純な方法は、追加テーブルを使用して三項関係と呼ばれるものを作成することです。理論的には、他の2つのソーステーブルの継承されたキーとプライマリキー(別個のタイムスタンプなど)をリンクする「時間」テーブルを作成することもできます。これにより、同じ時間内に2つの車が同じ駐車場にある場合のエラーを防ぐことができます。タイムテーブルを使用すると、単純な整数IDを使用して複数の駐車場に同じ時間データを再利用することができます。

テーブル車 car_id(整数/数字はインデックスに最速です) ...

テーブルの駐車スペース が 場所

をspace_idので

だから、あなたのデータテーブルは、次のようになりますテーブルタイムスロット time_id整数 begin_datetime(必要がなければ秒を使用しないでください!) end_time(あなたがしなければ秒を使用しないでください!)

ここで、それは楽しいものです。あなたは、car.car_id + parking_space.space_id + time_idで構成された複合主キーを持つ中間テーブルを追加します。あなたがここで最適化するために追加することができる他のものがありますが、あなたは考えを得る、私は願っています。

テーブル予約 car_id PK parking_space_idのPK TIME_IDのPK(それは整数だ - ちょうどできるだけきめ細かいとしてそれを維持しよう - 30分単位か何か - あなたは、これは秒/ミリ秒を含めることができた場合は/ etc利点あなたがタイムテーブルから同じ値を再利用することができないためキャンセルされます) (これは、この特定のアカウント、予約などとは異なる変動金利、割引などを保存する場所でもあります)。

今では、ジョインテーブル(予約)でタイムスタンプを複製していないため、データ量を減らすことができます。整数を使用することで、複数の駐車スペースにそのタイムスロットを再利用できますが、指定された日/時間枠で同じ「タイムスロット」のスポットを2台の車がレンタルできないように制約を適用することもできます。これはまた、顧客に関するいくつかの履歴を保存することを容易にするでしょう。誰が知っていますか、より頻繁に賃貸して割引を提供する顧客に関するレポートを見たいかもしれません。

3つの関係モデルを使用することで、特定のタイムスロット(各バリデーションルールが追加されている可能性があります)ごとに各スポットが一意になります。

タイムスタンプの代わりに整数をキーとして使用することで、データベースをインデックス化してソート/照会する必要がなくなります。大量のデータセットがあり、効率が必要な場合のデータウェアハウス/ OLAPレポート作成では、これが一般的な方法です。私はそれがここにも当てはまると思う。

関連する問題