7

私は中規模の MySQL データベースを持っており、主要な「persons」テーブルには、私が多数の Web アプリケーションの保守と開発を担当している劇場および演劇学校に接続しているすべての人間に関する基本的な連絡先情報が含まれています。

一部の人は単なる連絡先です。つまり、「persons」テーブル レコードは、その人について保存する必要があるすべての情報です。しかし、他の多くの人は、さまざまなシステムに対して異なる役割を引き受けることができなければなりません。このうち、ほとんどが学生としてスタートします。正社員としてスタートする方もいます。学生はインターンやパフォーマーになることができます。従業員は学生になることができます。すべての教師は従業員とパフォーマーなどです。

本質的に、それらは、システムのさまざまな部分にアクセスして対話するために、またそれらに関する情報を私たちのサイトの公開ページで利用できるようにするために、個人が着用しなければならないさまざまな「帽子」です。

このモデルを実装するための私の選択は、これらの「帽子」を表す他のいくつかのテーブルを用意することです。基本的な「人」情報を補足するメタ情報を含むテーブルで、すべて「人」ID を主キーとして使用します。たとえば、教師である人物は、彼または彼女の簡単な経歴情報と給与を含むレコードを教師テーブルに持っています。すべての教師は従業員でもあります (ただし、すべての従業員が教師であるわけではありません)。つまり、従業員テーブルにレコードがあり、給与システムに勤務時間を送信できます。

私の質問は、モデルをそのまま実装することの欠点は何ですか? 私が考えることができる唯一の他のオプションは、ほとんどのエントリに対して空で役に立たないフィールドで個人テーブルを膨らませ、次に個人が属することができる「グループ」の面倒なテーブルを持ち、次にすべてのほぼすべてのテーブルを持つことですシステムは個人person_idの外部キーを持ち、ビジネス ロジックに依存して、参照されている person_id が適切なグループに属していることを確認します。しかし、それはばかげていますね。

以下にいくつかのテーブル宣言の例を示します。これは、私が現在これらすべてをどのようにまとめているかを示し、システムが対処しなければならないさまざまな状況の現実をモデル化するためのより賢明な方法であると私が考える理由を示していることを願っています.

あらゆる提案やコメントを歓迎します。お時間をいただきありがとうございます。

EDIT何人かの回答者が、セキュリティのために ACL を使用することについて言及しています。最初の質問では、実際には、さまざまなシステムの実際のユーザーのきめ細かいアクセス制御のために別の ACL パッケージを使用していることには言及していませんでした。私の質問は、データベース スキーマに人に関するメタデータを格納するためのベスト プラクティスに関するものです。

CREATE TABLE persons (
    `id`            int(11) NOT NULL auto_increment,
    `firstName`     varchar(50) NOT NULL,
    `middleName`    varchar(50) NOT NULL default '',
    `lastName`      varchar(75) NOT NULL,
    `email`         varchar(100) NOT NULL default '',
    `address`       varchar(255) NOT NULL default '',
    `address2`      varchar(255) NOT NULL default '',
    `city`          varchar(75) NOT NULL default '',
    `state`         varchar(75) NOT NULL default '',
    `zip`           varchar(10) NOT NULL default '',
    `country`       varchar(75) NOT NULL default '',
    `phone`         varchar(30) NOT NULL default '',
    `phone2`        varchar(30) NOT NULL default '',
    `notes`         text NOT NULL default '',
    `birthdate`     date NOT NULL default '0000-00-00',
    `created`       datetime NOT NULL default '0000-00-00 00:00',
    `updated`       timestamp NOT NULL,
    PRIMARY KEY (`id`),
    KEY `lastName` (`lastName`),
    KEY `email` (`email`)
) ENGINE=InnoDB;

CREATE TABLE teachers (
    `person_id`     int(11) NOT NULL,
    `bio`           text NOT NULL default '',
    `image`         varchar(150) NOT NULL default '',
    `payRate`       float(5,2) NOT NULL,
    `active`        boolean NOT NULL default 0,
    PRIMARY KEY (`person_id`),
    FOREIGN KEY(`person_id`) REFERENCES `persons` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE classes (
    `id`            int(11) NOT NULL auto_increment,
    `teacher_id`    int(11) default NULL,
    `classstatus_id` int(11) NOT NULL default 0,
    `description`   text NOT NULL default '',
    `capacity`      tinyint NOT NULL,
    PRIMARY KEY(`id`),
    FOREIGN KEY(`teacher_id`) REFERENCES `teachers` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    FOREIGN KEY(`classstatus_id`) REFERENCES `classstatuses` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    KEY (`teacher_id`,`level_id`),
    KEY (`teacher_id`,`classstatus_id`)
) ENGINE=InnoDB;

CREATE TABLE students (
    `person_id`     int(11) NOT NULL,
    `image`         varchar(150) NOT NULL default '',
    `note`          varchar(255) NOT NULL default '',
    PRIMARY KEY (`person_id`),
    FOREIGN KEY(`person_id`) REFERENCES `persons` (`id`)
    ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE enrollment (
    `id`                int(11) NOT NULL auto_increment,
    `class_id`          int(11) NOT NULL,
    `student_id`        int(11) NOT NULL,
    `enrollmenttype_id` int(11) NOT NULL,
    `created`           datetime NOT NULL default '0000-00-00 00:00',
    `modified`          timestamp NOT NULL,
    PRIMARY KEY(`id`),
    FOREIGN KEY(`class_id`) REFERENCES `classes` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    FOREIGN KEY(`student_id`) REFERENCES `students` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    FOREIGN KEY(`enrollmenttype_id`) REFERENCES `enrollmenttypes` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
4

9 に答える 9

9

昨年、似たようなことを経験しました。問題は、エンティティを明示的にモデル化するか、一般的にモデル化するかということでした。あなたの例では、教師、学生などのエンティティ/テーブルが直接関係があるかどうかに関係なく持つことを意味します。

最終的に、一般的な「パーティー」モデルを採用しました。パーティーモデルは次のとおりです。

  • 当事者は個人または組織を表します。
  • ほとんどのパーティ タイプには、パーティ タイプに応じて追加情報を格納する依存テーブルがありました。たとえば、個人、組織、会社などです。
  • Student や Teacher などはParty Roleです。パーティーは、任意の数のパーティーの役割を持つことができます。Person は、教師と生徒の両方である場合があります。たとえば、次のようになります。
  • クラスなどはParty Role Relationshipsとして扱われます。たとえば、教師と生徒の役割の間の関係は、クラスの関係を示します。
  • 関係者役割関係には、追加情報用のサブタイプを含めることができます。モデルの教師と生徒の関係は登録であり、あなたが話している追加の属性を持つことができます。
  • 当事者同士は直接的な関係はありません。パーティーの役割のみが相互に関連しています。と
  • 情報を一般的にグループ化するために、関係がより間接的であるため SQL が少し複雑になる可能性があるため、役立つ場合はビューを作成しました (たとえば、教師と生徒のパーティ エンティティの間に 3 つのテーブルがあります)。

これは非常に強力なモデルであり、CRM タイプのシステムではかなり一般的です。このモデルは、 「The Data Model Resource Book: Volume 1」からほぼ引用されています。これは、そのようなことに関する優れたリソースです。

于 2009-01-08T21:55:08.413 に答える
1

あなたが説明するグループと帽子のモデルは、相互に変換可能です。データ損失の心配はありません。具体的には、「マスター グループ」テーブルは、「ハット パーソン」テーブルとさまざまな「ハット ディテール」テーブルの外部結合によって作成できます。

「帽子」モデルを使用している場合は、特定の「帽子テーブル」がその帽子の固有の特性を正確にカプセル化していることを確認する必要があります。グループ モデルよりも許容度がはるかに低くなります。

この方法を使用する場合、おそらく一般的なタスク用にいくつかのビューを設定する必要があります。

SELECT firstName, lastName 
FROM persons 
INNER JOIN teachers ON persons.id = teachers.person_id 

大いに役立ちます。

余談ですが、元のテーブルの主キーと同じ名前で外部キーを呼び出すと、便利であることがわかりました。そうすれば、

INNER JOIN original_table USING (primary_key) 

WHERE または ON の同等性をモンキーする代わりに、FROM で。

于 2009-01-08T21:37:34.627 に答える
0

私は帽子のアプローチが好きです。以前は、帽子とグループの組み合わせを実装していました。基本的に、ユーザーが実行できるすべての可能なアクション(権限)のリストがあります。次に、グループのテーブルがあります。各グループは、1つまたは複数のアクション(権限)を持つことができます。次に、ユーザーをグループに割り当てます。

これは私に多くの柔軟性を提供します。私は許可を得ることで非常に細かい粒子を得ることができます。また、グループを編集するだけで、多くのユーザーの権限をすばやく変更できます。実際、同じ権限を使用するための権限ページの設定があります。これにより、エンドユーザー(私ではない)が他のユーザーのアクセス許可を設定できるようになります。

于 2009-01-08T20:35:59.897 に答える
0

はい、そのような賃金率を持っているのは教師だけです。そのフィールドは、より正確には「classPayRate」と呼ばれる必要があります。これは、教師の従業員にとっては特別なケースです。教師以外の従業員は、給与システムの個別の項目として合計時間を提出します。

于 2009-01-08T20:37:44.030 に答える
0

教師を従業員に変更し、従業員タイプを追加する場合があります。

ただし、メール、アドレス、電話を個人テーブルに保存することは決してありません。人々は複数の電子メールアドレス(職場と自宅)、複数の電話番号(職場、自宅、携帯電話、ファックス)、および複数のアドレス(職場、自宅1、自宅2、学校など)を持っているため、これらはすべて独自の個別のテーブルである必要があります。それぞれを独自のテーブルに配置し、タイプを割り当てて、アドレスや電話番号などのタイプを識別できるようにします。

また、住所、電子メール、電話の場合、最初に連絡するために使用するメインレコードを識別するフラグが必要になる場合があります。私たちは通信を計算し、レコードを持っている人はそれぞれ1つだけの通信を持っている必要があるため、トリガーで最新に保たれるブール値です。したがって、通信が変更された場合は、古いものも自動的にリセットする必要があります。新しいレコードが入り、それが最初のレコードである場合は自動的に設定され、対応レコードが削除された場合、レコードが残っている場合は別のレコードに割り当てられます。

于 2009-01-08T20:38:05.650 に答える
0

私はサイトでのきめ細かい権限のためにACLパッケージを使用しています-私の質問の中心は、さまざまな役割を持つ個人のメタデータを保存し、データの整合性のためにシステムにいくつかの保護手段を構築する方法についてです(クラスの教師として設定するには、personに教師レコードが必要です。外部キー制約はpersonテーブルではなく、teacherテーブルを参照します)。

于 2009-01-08T21:14:27.027 に答える
0

セキュリティのために、私はアクセス制御リスト (ACL) を使用することを好みます。ACL には、プリンシパル (ユーザーまたはユーザーのグループ)、リソース (ファイル、レコード、またはレコードのグループなど)、およびアクション (読み取り、更新、削除など) があります。

デフォルトでは、誰も権限を持っていません。パーミッションを付与するには、Bob has Read Access to File Abc のようなエントリを追加します。

このようなものを実装するのに役立つコードを見つけることができるはずです。Java では、JAAS がこのメソッドをサポートしています。

于 2009-01-08T21:06:00.353 に答える
0

賃金率を持っているのは教師だけですか? このようにすることで、デザインを制限している可能性があります。あなたがやりたいことは、「人」の追加属性を格納する属性テーブルを持つことです。これにより、将来の変更が可能になります。

于 2009-01-08T20:26:39.590 に答える
0

以前はPartyモデルを使用していました。私は本当にほとんどの欠点を解決します。

于 2009-06-18T12:23:14.367 に答える