5
CREATE TABLE Phone
(
phoneID - PK
.
.
.
);

CREATE TABLE PhoneDetail
(
phoneDetailID - PK
phoneID - FK points to Phone
phoneTypeID ...
phoneNumber ...
.
.
.
);

CREATE TABLE Customer
(
customerID - PK
firstName
phoneID - Unique FK points to Phone
.
.
.
);

一个客户可以有多个电话号码,例如 Cell、Work 等。Customer 表中的 phoneID 是唯一的,并且指向 Phone 表中的 PhoneID。如果客户记录被删除,Phone 表中的 phoneID 也应该被删除。

你对我的设计有任何顾虑吗?这设计得当吗?我的问题是 Customer 表中的 phoneID 是一个孩子,如果删除了子记录,那么我无法自动删除父(电话)记录。

4

2 回答 2

12

我认为你过度设计了它。我认为单独的 Phone + PhoneDetail 表没有用。通常有两种实用的方法。

1)简单- 将所有电话放入客户记录本身。是的,它违反了规范化规则,但它在实践中非常简单,并且只要您提供(工作、家庭、移动、传真、紧急情况)通常就可以工作。好处是代码很简单,实现时间更短。检索具有客户记录的所有电话很简单,使用特定类型的电话 (Customer.Fax) 也是如此。

缺点:稍后添加其他电话类型有点痛苦,而且搜索电话号码很麻烦。你必须像"select * from customer where cell = ? or home = ? or work = ? or emergency = ?". 预先评估您的设计。如果这些问题中的任何一个是一个问题,或者您不知道它是否可能是一个问题,请使用标准化方法。

2)可扩展性- 走你要去的路线。电话类型可以稍后添加,无需更改 DDL。客户 -> 客户电话

Customer (
   customerId
)

CustomerPhone (
   customerId references Customer(customerId)
   phoneType references PhoneTypes(phoneTypeId)
   phoneNumber
)

PhoneTypes (
   phoneTypeId   (H, W, M, F, etc.)
   phoneTypeDescription
)
于 2010-04-08T01:47:48.143 回答
1

由于 mrjoltcola 已经解决了规范化问题,我将解决在电话中有记录而没有电话详细信息记录的问题。

如果这是您唯一的问题,则有三种方法:

1) 不要从明细表中删除,而是使用 CASCADE DELETE 从手机中删除 - 使用单个 SQL 语句从两个表中删除并保持数据一致

2)在详细表上有触发器,当父级的最后一条记录从子级中删除时会自动删除父级(这不会很好,并且会减慢表上的所有删除速度。而且很丑。仍然有可能去做吧)

3)在应用程序的业务逻辑层进行 - 如果该层被正确分离并且用户(应用程序)将仅通过该层修改数据,您可能会达到所需的一致性保证水平

于 2010-04-08T10:26:58.853 回答