オプション 3 が最もクリーンです。お気に入りの追加と削除が最も簡単になります。そして、これは ORM フレームワークが実装するスキーマです。
オプション 1 は実行可能ですが、整合性を確保するための外部キー制約を定義できませんでした。クエリに述語WHERE type='Venue'
を追加すると、そのテーブルでの作業が、別の 'Favorite_Venue` テーブルでの作業とほぼ同じになります。
オプション 2 では、お気に入りが既に存在する場合、お気に入りの追加が複雑になります。(これには、挿入するのではなく、既存の行を更新する必要があります。誰かが 2 つのお気に入りの会場と 5 つのお気に入りのパフォーマーを持っている場合、それは何行になりますか? しかし、少なくとも外部キーを定義できます。
2 つのお気に入りの会場と 2 人のお気に入りのパフォーマーがいたとします。
userID venueID performerID
------ ------- -----------
1 11 177
1 NULL 654
1 12 NULL
お気に入りの会場 ID 11 が削除されたら、行を更新して会場 ID を NULL に設定します。しかし、venueID 12 がお気に入りから削除された場合、列を NULL に設定するか、行を削除しますか。お気に入りのパフォーマーを追加するときに、performerID が NULL の既存の行を更新しますか、それとも行を挿入しますか。実行不可能ではありませんが、より複雑です。
列の会場 ID または演奏者 ID の 1 つだけを入力できるというルールがある場合、次のような述語を使用WHERE venueID IS NOT NULL
すると、このテーブルを別の Favorite_Venue テーブルで作業するのとほとんど同じように操作できます。
結論として、やむを得ない理由がない限り、オプション 3 を使用します。
「ごちゃまぜ」ではありません。これらのテーブル Favorite_Venue と Favorite_Performer のそれぞれには、目的、「存在理由」、それがそこにある理由があります。各テーブルは、多対多の関係を解決します。
これら 2 つの別個の「関係」テーブルを 1 つのテーブルに結合すると、実際には混乱が生じます。行を区別するために列を追加すると (この行が実際にどのテーブルに属しているかという質問に効果的に答えるために)、その列は「乱雑」になります。2 つのリレーションシップに対して同じ行に 2 つの別々の列を使用すると、お気に入りの追加または削除を処理するコードが乱雑になります。