Database-Design

有兩個相同的實體,除了 1 個不同的屬性

  • October 26, 2017

在數據庫設計任務的範例場景中,一家公司提供酒店房間(分為兩個實體 - 酒店和房間)和公寓。因此數據庫將包含以下實體:

Hotel (hotelNo(PK), name, address, telephone)

Room (roomNo(PK), hotelNo(PK), dailyRentalRate)

Apartment (apartmentNo(PK), address, numberOfRooms, dailyRentalRate)

在規範中,公司希望數據庫包含一個儲存以下數據的檢查實體:

  • 檢查日期,
  • 房間/公寓的狀況,
  • 進行檢查的工作人員。
  • 酒店和房間號和公寓號取決於檢查是在酒店房間還是公寓上。

我的問題是最好將其拆分為兩個實體,如下所示,或者擁有一個實體(也如下所示),該實體的酒店和房間號都為空值(當檢查是針對公寓時),或公寓號碼(當檢查是酒店房間時)。

兩個獨立的實體:

HotelInspection (hotelInspectionNo, date, condition, staffNo(FK), roomNo(FK), hotelNo(FK))

ApartmentInspection (apartmentInspectionNo, date, Condition, staffNo(FK), apartmentNo(FK))

一個實體:

Inspection (inspectionNo, date, condition, staffNo(FK), roomNo(FK), hotelNo(FK), apartmentNo(FK))

如果我是你,我會做如下的事情:

(tl;dr) - 你應該有一個檢查實體 - 它們相距一縷頭髮,在這種情況下,本質上是一回事!稍微修改您的架構會使它們變得相同。

CREATE TABLE location  -- "master" room/apartment (could be called "accomomation" or similar)
(
 location_id INTEGER PRIMARY_KEY,
 location_type VARCHAR (10) NOT NULL,
 -- CHECK accommodation_type IN ('Hotel', 'Appartment'), could also have 'Hostel', 'AirBNB', 'Tent'...
 -- MySQL doesn't support `CHECK` constraints - use a lookup table!
 location_name VARCHAR (25), -- colloquial name
 location_phone VARCHAR (20) -- either the switch or owner's mobile/cell.
);

筆記:

  • 表名全部小寫 - 易於閱讀:SQL 大寫,標識符小寫,下劃線。

  • 總是(取決於您的 RDBMS - 儘管現在所有主要的 RDBMS 都符合),給您PRIMARY KEY的 s、FOREIGN KEYs 和UNIQUE INDEXes(即所有數據庫對象)提供有意義的名稱 - 使調試更容易。

  • 您會注意到我為我的欄位輸入了長名稱 - 這是因為

    • a) 更易於調試,並且,
    • b) 程式碼/程序 99% 的時間都花在維護上——輸入幾個額外的字元是為了讓生活更輕鬆而付出的小代價!
  • 永遠不要使用關鍵字(例如DATE)作為表名或列名!使用帶引號的標識符 &c 讓生活陷入困境。

  • NULL始終嘗試減少(在合理範圍內)架構中可以輸入 s的點數。它使邏輯更容易,並且可以幫助優化器!我的大部分列定義都可以跟在NOT NULL下面!

  • 您可能還想查看此站點以獲取其他想法。我的想法只是“第一關”。

CREATE TABLE hotel
(
 hotel_id INTEGER PRIMARY KEY,
 hotel_name VARCHAR (50) NOT NULL,  -- full business name
 hotel_address INTEGER, -- FK reference to address table?
);

CREATE TABLE room
(
 room_id INTEGER PRIMARY KEY, -- as opposed to room_no - room numbers in hotels can change, renovations, buidling works!
 location_id INTEGER, -- FK to location. Also `UNIQUE INDEX` to prevent dups.
 hotel_id INTEGER, -- FK to hotel
 room_no INTEGER,
 room_rate INTEGER -- FLOAT/DECIMAL/whatever
);

CREATE TABLE apartment
(
 apartment_id INTEGER PRIMARY KEY
 location_id INTEGER, -- FK to location! Also, `UNIQUE INDEX` to prevent dups!
 apartment_address INTEGER, -- FK to address table
 apartment_room_count INTEGER,
 apartment_rate INTEGER -- FLOAT, DECIMAL...
);

CREATE TABLE location_rating
(
 location_rating_id INTEGER NOT NULL PRIMARY KEY,  -- if possible give your PK a meaningful name.
 accomodation_rating_text VARCHAR (20) NOT NULL
);

INSERT INTO accomodation_rating
VALUES
(1, 'Call the police!'),
(2, 'Totally unaccptable'),
(3, 'Very poor'),
(4, 'Poor'),
(5, 'Acceptable'),
(6, 'Reasonable'),
(7, 'Good'),
(8, 'Very good'),
(9, 'Excellent'),
(10, 'Kiss the cleaners!');


CREATE TABLE inspection
(
 inspection_id INTEGER PRIMARY KEY, 
 accommodation_id  INTEGER, -- FK to accomodation
 inspection_date DATE, -- more meaningful than just date - anyway, NEVER call a table or field by a KEYWORD!
 inspection_rating INTEGER, -- FK to your accomodation_rating table - NEVER allow people to write free text if possible!

 -- NOW, no need for hotelNo or apartmentNo - plus no NULLs!
);

引用自:https://dba.stackexchange.com/questions/189351