0

ユーザーとそのグループを 3 つのテーブルと 2 つのテーブルに格納することの長所と短所について疑問に思っています。

2テーブルのメリット

  1. グループは簡単にユーザー自身である可能性があり、ほとんどのシナリオでは、ユーザーと同じフィールド (名前、画像、パスワード、電子メールなど) をすべて共有しているように見えます。

3テーブルの長所

  1. 3 番目groupsのテーブルがあると、より明確になるため、開発者が理解したり維持したりするのが容易になる可能性があります。

3 つのテーブルの短所 1. 上記の「2 つのテーブルの長所」の 1 を実行しないことにより、アプリケーション コード全体で DRY 原則に違反します。

他に何を考えるべきですか?

2 つの必須テーブルは、usersテーブルとgroup_memberテーブルです。

+---------+      +------------+
| users    |      | group_member |     +----------+
+---------+      +------------+     | groups    |
| user_id |----->| user_id    |     +----------+
| name    |      | group_id   |<----| group_id |
| pass    |      +------------+     | name     | 
| ...     |                         | ...      |
+---------+                         +----------+

                                    **theoretical 3rd table**

注:表のuser_idとは両方ともgroup_id、表group_memberの を指してuser_idいます。users

4

2 に答える 2

3

要点: ユーザーとグループが (ほとんどの) 特性を共有するため、1 つのテーブルに格納したい場合、これは完全に有効です。ただし、これは技術的にはグループがユーザーのメンバーになることができることを意味し、ユーザーがグループに所属できることをデータベースレベルで強制することはできず、他の注意を払うことはできません。

1 つのテーブルのシナリオ:

CREATE TABLE users_and_groups (id int...
CREATE TABLE group_members (
    group_id, 
    user_id
    FOREIGN KEY (group_id) REFERENCES users_and_group (id) -- no way to limit on only groups
    FOREIGN KEY (user_id) REFERENCES users_and_group (id) -- no way to limit on only users   
)

2 つのテーブルのシナリオ:

CREATE TABLE users (id int...
CREATE TABLE groups (id int...
CREATE TABLE group_members (
    group_id, 
    user_id
    FOREIGN KEY (group_id) REFERENCES groups (id) -- guarantees a group
    FOREIGN KEY (user_id) REFERENCES users (id)   -- guarantees a user
)

このように防御的にデータベースを設定することで、アプリケーション レベルでバグが発生した場合に、多くの被害を防ぐことができます。


ただし、user&groupエンティティが多くのデータを共有する場合 (たとえば、両方とも他のオブジェクトを所有したり、プロファイル ページを持ったりすることができます)、4 つのテーブル ソリューションがうまく機能します。

CREATE TABLE users_and_groups (id, ...shared data...
CREATE TABLE users (users_and_groups_id, ...user specific data...
CREATE TABLE groups (users_and_groups_id, .. group specific data...
CREATE TABLE group_members (
    group_id, 
    user_id
    FOREIGN KEY (group_id) REFERENCES groups (users_and_groups_id) -- guarantees a group
    FOREIGN KEY (user_id) REFERENCES users (users_and_groups_id)   -- guarantees a user
)

これにはいくつかの利点があります。

  • グループまたはユーザーのいずれかが許可されている外部キーは、1 列に含めることができます。
  • アプリケーションレベルでは、これは古典的な継承です: base users_and_groups、および両方userとその基本クラス/テーブルをgroup 拡張します。
  • グループまたはユーザーのいずれかを強制することは、外部キーを使用して引き続き可能です
  • ユーザーまたはグループが特定のデータを取得する場合、テーブルに列を追加する必要はありません。これは、レコードの大部分にとって役に立たないため、タイプ固有のテーブルに格納できます。

いくつかの欠点:

  • エンティティがユーザーまたはグループのいずれかであることを強制することはできませんが、両方またはいずれでもないことは強制できません(型なし)
  • 冗長な列type(またはis_group/ is_user) を格納しない限り、エンティティがグループであるかユーザーであるかを判断するには が必要JOINですが、これは両側の主キーにあるため、オーバーヘッドは小さいはずです
于 2013-09-23T22:36:41.467 に答える
2

group_memberどちらかといえば、オプションのテーブルだと思います。usersとgroupsの間に多対多の関係が必要な場合にのみ、このテーブルが必要です。つまり、ユーザーが複数のグループに所属できる場合、 を にリンクできるテーブルが必要になります。ユーザーが1 つのグループにしか所属できない場合でも、おそらくテーブルが必要であり、そのテーブルに列が必要です。user_idgroup_idgroupsgroup_idusers

ただし、元の質問に答えるには、グループ情報 (グループ名など) をgroup_memberテーブルに保存した場合、グループ内のユーザーごとにこのデータを繰り返す必要があります。同じグループ名を持つ多くの行があり、後でグループ名を変更したい場合は、1 つではなく多くの行を更新する必要があります。また、誰が同じグループに属しているのかを判別することも非常に難しくなり、そのようなクエリの多くは非常に非効率になります。

個別のグループを単一のgroupsテーブルに正規化することは、1 つまたは 2 つのテーブルを使用するかに関係なく、間違いなく正しいアプローチです。

于 2013-09-23T22:22:33.360 に答える