[英]Need some assistance in verifying a database logical schema to Third Normal Form
這最初是對另一個問題中提出的邏輯模式的“更新”: MySQL中出現ERROR 1701,ERROR 1452和ERROR 1305錯誤 - 需要一些專業知識 ......
我想我已成功將此模式驗證為第1和第2范式,但我不確定這是否符合第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標准化的理解:
將這些知識從理論付諸實踐對我來說非常困難,特別是將“實踐”轉化為工作的,規范化的MySQL代碼。 如果有人能夠幫助我完成模型並給我一些關於將模型標准化為3NF的指示,我將非常感激。
提前致謝!
我認為這不是在3NF,在contact
表周圍。 如果我錯了,這仍然是存儲數據的壞方法,應該可能會改變。
對不起,如果這有點困惑......
完全可以在contact
表中具有以下結構,因為整個表是主鍵:
+----------+-------------+---------------+---------+ | personid | homephoneid | mobilephoneid | emailid | +----------+-------------+---------------+---------+ | 1 | 1 | 1 | 1 | | 1 | 1 | 1 | 2 | | 1 | 1 | 2 | 3 | +----------+-------------+---------------+---------+
正如您所看到的, homephoneid
和mobilephoneid
都是重復的,因此更新表homephone
將導致3次更新contact
。
我不同意數據模型,因為你需要一個person
有一個我沒有的homehone
,只有一部手機。 在這種情況下,創建一個新的時person
,你也必須創建一個新的contact
和新的homephone
。
由於contact
僅僅是一個主鍵,主鍵的值不能為空,你還需要創建mobilephone
和emailaddress
,這意味着person
是依賴於emailaddress
。
由於emailaddress
依賴於contact
,而contact
依賴於person
你創建了一個循環依賴,打破了3NF。
當我看到它,你有兩個選擇,如果你想保證人們一直到有一個家的電話號碼:
person
擁有一部 homephone
那么將其添加到person
表中。 它是唯一的聯系級別信息,應存儲在那里。 personhomephones
,也就是說,與主鍵personid, homephoneid
和沒有把homephoneid
放在聯系表中。 就個人而言,我不會做其中任何一個。 我不會確保有人必須有一個家庭電話號碼,而是一個主要電話號碼,你不關心它是什么類型。 我會允許人們添加不同的聯系方式,但允許這些方法不存在
這需要以下結構:
person
- 添加primaryPhoneID
primaryphone ( primaryphoneID, phonenumber)
- PK primaryphoneID
然后,對於不存在的聯系方法:
contactType ( contactTypeID, contactType )
- PK contactTypeID
contact ( contactID, contactTypeID, value )
- PK contactID, contactTypeID
personContact ( personID, contactID, contactTypeID )
- PK一切 雖然這可能導致contact
和主要primaryphone
之間的重復, primaryphone
它們是不同的數據位,我認為這很好。 如果您堅持不允許任何重復,則必須將手機與其他聯系方式分開,這會使模型更加復雜:
phonetype ( phoneTypeId, phoneType )
phone ( phoneID, phoneTypeID, phonenumber)
- PK phoneID, phoneTypeID
contactPhone ( personID, phoneTypeID, phoneID )
- PK一切
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.