3

これは元々、ここで別の質問で提示された論理スキーマの「更新」になる予定でした:MySQLでエラー1701、エラー1452、およびエラー1305エラーを取得する-専門知識が必要です...

このスキーマを第1正規形と第2正規形で正常に検証できたと思いますが、これが第3正規形に一致するかどうかはわかりません。問題のモデルは次のとおりです。

論理データベースモデルの第3正規形への試み

そして、これが関連するコードです(注:上記の論理モデルに示されているように、何らかの理由でSQLコードで1:1の関係を再作成できません):

-- database_schema.sql.
-- This sql script creates the structure.
-- of the rugby club database.

DROP DATABASE IF EXISTS database_rugby;

CREATE DATABASE database_rugby;

USE database_rugby;

-- Create the "person" table.
--
-- This table has one:one relationships
-- with the parent, coach and player 
-- tables.
DROP TABLE IF EXISTS `person` ;
CREATE TABLE `person` (
  `personID` INT(5) NOT NULL AUTO_INCREMENT ,
  `firstName` VARCHAR(50) NOT NULL ,
  `lastName` VARCHAR(50) NOT NULL ,
  `dateOfBirth` DATE NOT NULL ,
  `streetAddress` VARCHAR(150) NOT NULL ,
  `suburbAddress` VARCHAR(150) NULL DEFAULT NULL ,
  `cityAddress` VARCHAR(150) NOT NULL ,
  `photo` BLOB NULL DEFAULT NULL ,
  PRIMARY KEY (`personID`))
ENGINE = InnoDB;

-- Create the "parent" table.
DROP TABLE IF EXISTS `parent` ;
CREATE TABLE `parent` (
  `parentID` INT(5) NOT NULL ,
  `personID` INT(5) NOT NULL ,
  PRIMARY KEY (`parentID`, `personID`), 
  FOREIGN KEY (`personID`) REFERENCES `person` (`personID`)
  ON DELETE CASCADE 
  ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "school" table.
DROP TABLE IF EXISTS `school` ;
CREATE TABLE `school` (
  `schoolID` INT(5) NOT NULL AUTO_INCREMENT ,
  `schoolName` VARCHAR(100) NOT NULL ,
  PRIMARY KEY (`schoolID`))
ENGINE = InnoDB;


-- Create the "player" table.
--
-- Inherits fields from the "person"
-- and "school" tables.
DROP TABLE IF EXISTS `player` ;

CREATE TABLE `player` (
  `playerID` INT(5) NOT NULL ,
  `personID` INT(5) NOT NULL ,
  `schoolID` INT(5) NOT NULL ,
  PRIMARY KEY (`playerID`, `personID`), 
    FOREIGN KEY (`personID`) 
    REFERENCES `person` (`personID`)
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    FOREIGN KEY (`schoolID`)
    REFERENCES `school` (`schoolID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "coach" table.
DROP TABLE IF EXISTS `coach`;
CREATE TABLE `coach`(
  `coachID` INT(5) NOT NULL ,
  `dateBeganCoaching` DATE NOT NULL ,
  `personID` INT(5) NOT NULL ,
  PRIMARY KEY (`coachID`, `personID`), 
  FOREIGN KEY (`personID`) 
  REFERENCES `person` (`personID`)
  ON DELETE CASCADE 
  ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "family" table.
--
-- This is a linking table 
-- that describes the many:many 
-- relationship between "parent" 
-- and "player" tables.
DROP TABLE IF EXISTS `family` ;
CREATE TABLE `family` (
  `parentID` INT(5) NOT NULL ,
  `playerID` INT(5) NOT NULL ,
    FOREIGN KEY (`playerID` )
    REFERENCES `player` (`playerID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`parentID`)
    REFERENCES `parent` (`parentID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- Create the "grade" table.
DROP TABLE IF EXISTS `grade`;
CREATE  TABLE `grade`(
  `gradeID` INT(5) NOT NULL AUTO_INCREMENT ,
  `gradeName` VARCHAR(50) NOT NULL ,
  `minWeight` INT(3) NOT NULL ,
  `maxWeight` INT(3) NOT NULL ,
  `minAge` INT(3) NOT NULL ,
  `maxAge` INT(3) NOT NULL ,
  `ballSize` INT(1) NOT NULL ,
  PRIMARY KEY (`gradeID`) )
ENGINE = InnoDB;


-- Create the "coachQualification" table.
DROP TABLE IF EXISTS `coachQualification` ;

CREATE TABLE `coachQualification` (
  `qualID` INT(5) NOT NULL AUTO_INCREMENT ,
  `qualName` CHAR(5) NOT NULL ,
  `gradeID` INT(5) NOT NULL ,
  PRIMARY KEY (`qualID`) ,
    FOREIGN KEY (`gradeID`)
    REFERENCES `grade` (`gradeID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "homePhone" table.
DROP TABLE IF EXISTS `homePhone` ;
CREATE TABLE `homePhone` (
  `homePhoneID` INT(5) NOT NULL AUTO_INCREMENT ,
  `homeNumber` CHAR(9) NOT NULL ,
  PRIMARY KEY (`homePhoneID`))
ENGINE = InnoDB;


-- Create the "mobilePhone" table.
DROP TABLE IF EXISTS `mobilePhone` ;

CREATE TABLE `mobilePhone` (
  `mobilePhoneID` INT(5) NOT NULL AUTO_INCREMENT ,
  `mobileNumber` CHAR(10) NULL DEFAULT NULL ,
  PRIMARY KEY (`mobilePhoneID`))
ENGINE = InnoDB;


-- Create the "emailAddress" table.
DROP TABLE IF EXISTS `emailAddress` ;

CREATE TABLE `emailAddress` (
  `emailAddressID` INT(5) NOT NULL AUTO_INCREMENT ,
  `emailAddress` CHAR(10) NULL DEFAULT NULL ,
  PRIMARY KEY (`emailAddressID`))
ENGINE = InnoDB;


-- Create the "Contact" table
--
-- This is a linking table 
-- that describes the many:many 
-- relationships between "person" 
-- and the "homePhone", "mobilePhone", 
-- and "emailAddress" tables.
DROP TABLE IF EXISTS `contact` ;
CREATE TABLE `contact` (
  `personID` INT(5) NOT NULL ,
  `homePhoneID` INT(5) NOT NULL ,
  `mobilePhoneID` INT(5) NULL DEFAULT NULL ,
  `emailAddressID` INT(5) NULL DEFAULT NULL ,
    FOREIGN KEY (`personID` )
    REFERENCES `person` (`personID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`homePhoneID`)
    REFERENCES `homePhone` (`homePhoneID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`mobilePhoneID`)
    REFERENCES `mobilePhone` (`mobilePhoneID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`emailAddressID`)
    REFERENCES `emailAddress` (`emailAddressID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "qualificationSet" table.
--
-- This is a linking table 
-- that describes the many:many 
-- relationship between "coach" 
-- and "coachQualification" tables.
DROP TABLE IF EXISTS `qualificationSet` ;
CREATE TABLE `qualificationSet` (
  `coachID` INT(5) NOT NULL ,
  `qualID` INT(5) NOT NULL ,
    FOREIGN KEY (`coachID`)
    REFERENCES `coach` (`coachID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`qualID`)
    REFERENCES `coachQualification` (`qualID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "team" table.
DROP TABLE IF EXISTS `team` ;
CREATE TABLE `team` (
  `teamID` INT(5) NOT NULL AUTO_INCREMENT ,
  `teamName` VARCHAR(50) NOT NULL ,
  `teamYear` INT(2) NOT NULL ,
  `gradeID` INT(5) NOT NULL ,
  PRIMARY KEY (`teamID`) ,
    FOREIGN KEY (`gradeID`)
    REFERENCES `grade` (`gradeID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "teamAllocation" table
--
-- this is a linking table for a 
-- many:many relationship between
-- team and player tables.
DROP TABLE IF EXISTS `teamAllocation` ;

CREATE TABLE `teamAllocation` (
  `teamID` INT(5) NOT NULL ,
  `playerID` INT(5) NOT NULL ,
    FOREIGN KEY (`teamID` )
    REFERENCES `team` (`teamID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`playerID`)
    REFERENCES `player` (`playerID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- Create the "teamCoachAllocation" table.
--
-- This is a linking table 
-- that describes the many:many 
-- relationship between "coach" 
-- and "team" tables.
DROP TABLE IF EXISTS `teamCoachAllocation` ;
CREATE TABLE `teamCoachAllocation` (
  `coachID` INT(5) NOT NULL ,
  `teamID` INT(5) NOT NULL ,
    FOREIGN KEY (`coachID`)
    REFERENCES `coach` (`coachID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`teamID`)
    REFERENCES `team` (`teamID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

以下のこれらのリンクから:

これは、3NFへの正規化についての私の理解です。

  • 第一正規形は、値の繰り返しを許可しないことを意味します
  • 2番目の正規形は、1NFと属性が主キーの一部ではなく、主キー全体に依存していることを意味します(テーブル内の値が何らかの方法で相互に関連付けられ、比較が行われる必要がある場合、これはテーブルの分割と見なします)。
  • 3番目の正規形は、2NFを意味し、遷移値はありません(たとえば、x=yおよびy=zの場合、x = z)

理論からの知識を実践することは私にとって非常に困難です。特に、その「実践」を機能する正規化されたMySQLコードに変換することは非常に困難です。誰かが私がモデルを調べて、モデルを3NFに正規化することについてのいくつかの指針を私に与えるのを手伝ってくれるなら、私はそれをとても感謝します。

前もって感謝します!

4

2 に答える 2

1

これは3NFではないと思いcontactます。私が間違っている場合でも、これはデータを保存するための悪い方法であり、おそらく変更する必要があります。

これが少し混乱している場合は申し訳ありません...

contactテーブル全体が主キーであるため、テーブルに次の構造を含めることは完全に可能です。

+ ---------- + ------------- + --------------- + -------- -+
| ペルソナID| homephoneid | mobilephoneid | emailid |
+ ---------- + ------------- + --------------- + -------- -+
| 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 2 |
| 1 | 1 | 2 | 3 |
+ ---------- + ------------- + --------------- + -------- -+

homephoneid両方を見ることができmobilephoneid、複製されているので、テーブルhomephoneを更新すると、が3回更新されcontactます。

私はデータモデルに同意しません。あなたが持っている必要があるpersonので、homehone私は持っていません。モバイルだけです。この状況では、新しいものを作成するときに、新しいものとperson新しいものも作成する必要があります。contacthomephone

contactは主キーであり、主キーの値をnullにすることはできないため、aと、の作成も必要です。これは、に依存していることを意味します。mobilephoneemailaddresspersonemailaddress

emailaddressに依存しているように、これは、3NFを壊す循環依存関係を作成したことcontactに依存しています。person

私が見ているように、人々が自宅の電話番号を持っていることを確認したい場合は、2つのオプションがあります。

  1. person1つ だけにしたい場合は、これをテーブルhomephoneに追加します。personこれは固有の連絡先レベル情報であり、そこに保存する必要があります。
  2. 人々が複数の自宅の電話番号を持つことができるようにしたい場合(複数の人が同じ電話番号を使用できることを覚えておいてください)、携帯電話は気にしないでください personhomephones。たとえば、主キーpersonid, homephoneidを使用してテーブルを作成homephoneidし、連絡先テーブル。

個人的にはどちらもしません。私は誰かが自宅の電話番号を持っている必要があることを保証しませんが、代わりにあなたがそれがどんなタイプであるかを気にしない主要な電話番号を持っている必要があります。私は人々が異なる連絡方法を追加することを許可しますが、これらは存在しないことを許可します

これには、次の構造が必要になります。

  • person- 追加primaryPhoneID
  • primaryphone ( primaryphoneID, phonenumber)-PKprimaryphoneID

次に、存在できないことが許可されている連絡方法について:

  • contactType ( contactTypeID, contactType )-PKcontactTypeID
  • contact ( contactID, contactTypeID, value )-PKcontactID, contactTypeID
  • personContact ( personID, contactID, contactTypeID )-すべてをPKする

これにより、データが重複する可能性がありますがcontactprimaryphoneこれらは別個のデータであり、これで問題ないと思います。重複をまったく許可しないことに固執する場合は、電話を他の連絡方法から分離する必要があります。これにより、モデルがより複雑になります。

  • phonetype ( phoneTypeId, phoneType )
  • phone ( phoneID, phoneTypeID, phonenumber)-PKphoneID, phoneTypeID
  • contactPhone ( personID, phoneTypeID, phoneID )-すべてをPKする
于 2012-04-22T11:17:31.713 に答える
1

3NFで同等のスキーマを取得するために、スキーマ内の各リレーションを最終的に分解するアルゴリズムがあります。グーグルはそのために良いです!

スキーマ設計に関するヒントを得るには、少なくとも、表現する必要のあるエンティティに関するコンテキストと機能上の制約について説明する必要があります。

于 2012-04-22T09:59:07.257 に答える