2011-03-28 51 views

回答

23

在大多数情况下。 。 。

  • “工作人员”总是描述人。
  • 有些顾客是人。
  • 一些客户是企业 (组织)。
  • “供应商”通常是(总是?) 组织。
  • 员工也可以是客户。
  • 供应商也可以是客户。

将工作人员电话号码,供应商电话号码和客户电话号码分开列表存在严重问题。

  • 员工可以是客户。如果一个工作人员 电话号码发生变化,请问客户 电话号码是否需要更新?你怎么知道哪一个更新?
  • 供应商可以成为客户。如果 供应商的电话号码发生变化,那么客户的电话号码是否也需要更新?你怎么知道哪一个更新?
  • 您必须复制和维护无误, 存储电话号码的每个表格中的电话号码约束 。
  • 当客户的电话号码发生变化时,也会出现同样的问题。现在 你必须检查是否 工作人员供应商的电话号码 也需要更新。
  • 要回答这个问题:“谁的电话号码 是123-456-7890?”,你必须 看在“n”个不同的表,其中 “n”是各方的不同 “种”的号码,你处理。在 除了员工,客户和供应商 ,认为“承包者 手机”,“潜在客户的电话”等

你需要实现一个父/子架构。(PostgreSQL的代码,而不是严格的测试。)

create table parties (
    party_id integer not null unique, 
    party_type char(1) check (party_type in ('I', 'O')), 
    party_name varchar(10) not null unique, 
    primary key (party_id, party_type) 
); 

insert into parties values (1,'I', 'Mike'); 
insert into parties values (2,'I', 'Sherry'); 
insert into parties values (3,'O', 'Vandelay'); 

-- For "persons", a subtype of "parties" 
create table person_st (
    party_id integer not null unique, 
    party_type char(1) not null default 'I' check (party_type = 'I'), 
    height_inches integer not null check (height_inches between 24 and 108), 
    primary key (party_id), 
    foreign key (party_id, party_type) references parties (party_id, party_type) on delete cascade 
); 

insert into person_st values (1, 'I', 72); 
insert into person_st values (2, 'I', 60); 

-- For "organizations", a subtype of "parties" 
create table organization_st (
    party_id integer not null unique, 
    party_type CHAR(1) not null default 'O' check (party_type = 'O'), 
    ein CHAR(10), -- In US, federal Employer Identification Number 
    primary key (party_id), 
    foreign key (party_id, party_type) references parties (party_id, party_type) on delete cascade 
); 

insert into organization_st values (3, 'O', '00-0000000'); 

create table phones (
    party_id integer references parties (party_id) on delete cascade, 
    -- Whatever you prefer to distinguish one kind of phone usage from another. 
    -- I'll just use a simple 'phone_type' here, for work, home, emergency, 
    -- business, and mobile. 
    phone_type char(1) not null default 'w' check 
     (phone_type in ('w', 'h', 'e', 'b', 'm')), 
    -- Phone numbers in the USA are 10 chars. YMMV. 
    phone_number char(10) not null check (phone_number ~ '[0-9]{10}'), 
    primary key (party_id, phone_type) 
); 

insert into phones values (1, 'h', '0000000000'); 
insert into phones values (1, 'm', '0000000001'); 
insert into phones values (3, 'h', '0000000002'); 

-- Do what you need to do on your platform--triggers, rules, whatever--to make 
-- these views updatable. Client code uses the views, not the base tables. 
-- In current versions of PostgreSQL, I think you'd create some "instead 
-- of" rules. 
-- 
create view people as 
select t1.party_id, t1.party_name, t2.height_inches 
from parties t1 
inner join person_st t2 on (t1.party_id = t2.party_id); 

create view organizations as 
select t1.party_id, t1.party_name, t2.ein 
from parties t1 
inner join organization_st t2 on (t1.party_id = t2.party_id); 

create view phone_book as 
select t1.party_id, t1.party_name, t2.phone_type, t2.phone_number 
from parties t1 
inner join phones t2 on (t1.party_id = t2.party_id); 

要一点点进一步延伸了这一点,表实行“员工”需要参考的人亚型,而不是党的超类型。组织不能成为员工。

create table staff (
    party_id integer primary key references person_st (party_id) on delete cascade, 
    employee_number char(10) not null unique, 
    first_hire_date date not null default CURRENT_DATE 
); 

如果供应商只能是组织,而不是个人,则表实现供应商将引用组织亚型以类似的方式。

对于大多数公司来说,客户可以是个人或组织,因此实施客户的表应该引用超类型。

create table customers (
    party_id integer primary key references parties (party_id) on delete cascade 
    -- Other attributes of customers 
); 
-1

最直接的方法可能是最好的。即使员工,客户或供应商都拥有手机,手机和传真号码的位置,但最好将这些字段放在每张桌子上。

但是,你拥有的领域越多,你应该考虑某种“继承”或集中。如果有其他联系信息以及多个电话号码,则可以在集中表上使用这些常用值,联系人。作为客户,供应商等的特定字段将位于不同的表格中。例如,客户表将有一个ContactID外键返回到联系人。

0

我想这个决定必须基于对这种接触的信息是多么重要,多久它改变了多少实际的评估重叠有可能是不同类型的人与之间的电话号码。

如果联系人信息对于应用程序是不稳定和/或真正重要的,那么更多的标准化可能会更好。这意味着您的各种客户,供应商,员工表(等)可能会指向一个PHONE_NUMBER表 - 或者更有可能通过联系类型,联系人(客户/供应商/员工)和联系点(电话)。通过这种方式,您可以将员工的家庭电话号码作为其客户记录的主要业务号码,如果发生变化,则每次使用该联系点时都会更改一次。另一方面,如果你存储了电话号码,而你没有使用它们,并且可能不会维护它们,那么花费大量的时间和精力建模并将这种复杂性构建到您的数据库将不值得,并且您可以在客户,供应商,员工或您有什么问题上做好老式的Phone1,Phone2,Phone3 ......列。这是不好的数据库设计,但它是一个很好的系统开发实践,因为它将80/20规则应用于确定项目优先级。所以总结一下:如果数据很重要,那么做对,如果数据并不重要,就把它放在一边 - 或者更好,然后把它放在一边。