一个相当简单的问题,如果我有一个处理员工,客户和供应商的系统,所有这些系统都有多个可能的电话号码,您将如何去存储这些数字以一种很好的规范化的方式?我有一个想法,逻辑的方式是不跳出来对我。来自数据库中不同实体的相同数据 - 最佳实践 - 电话号码示例
回答
在大多数情况下。 。 。
- “工作人员”总是描述人。
- 有些顾客是人。
- 一些客户是企业 (组织)。
- “供应商”通常是(总是?) 组织。
- 员工也可以是客户。
- 供应商也可以是客户。
将工作人员电话号码,供应商电话号码和客户电话号码分开列表存在严重问题。
- 员工可以是客户。如果一个工作人员 电话号码发生变化,请问客户 电话号码是否需要更新?你怎么知道哪一个更新?
- 供应商可以成为客户。如果 供应商的电话号码发生变化,那么客户的电话号码是否也需要更新?你怎么知道哪一个更新?
- 您必须复制和维护无误, 存储电话号码的每个表格中的电话号码约束 。
- 当客户的电话号码发生变化时,也会出现同样的问题。现在 你必须检查是否 工作人员和供应商的电话号码 也需要更新。
- 要回答这个问题:“谁的电话号码 是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
);
最直接的方法可能是最好的。即使员工,客户或供应商都拥有手机,手机和传真号码的位置,但最好将这些字段放在每张桌子上。
但是,你拥有的领域越多,你应该考虑某种“继承”或集中。如果有其他联系信息以及多个电话号码,则可以在集中表上使用这些常用值,联系人。作为客户,供应商等的特定字段将位于不同的表格中。例如,客户表将有一个ContactID外键返回到联系人。
我想这个决定必须基于对这种接触的信息是多么重要,多久它改变了多少实际的评估重叠有可能是不同类型的人与之间的电话号码。
如果联系人信息对于应用程序是不稳定和/或真正重要的,那么更多的标准化可能会更好。这意味着您的各种客户,供应商,员工表(等)可能会指向一个PHONE_NUMBER表 - 或者更有可能通过联系类型,联系人(客户/供应商/员工)和联系点(电话)。通过这种方式,您可以将员工的家庭电话号码作为其客户记录的主要业务号码,如果发生变化,则每次使用该联系点时都会更改一次。另一方面,如果你存储了电话号码,而你没有使用它们,并且可能不会维护它们,那么花费大量的时间和精力建模并将这种复杂性构建到您的数据库将不值得,并且您可以在客户,供应商,员工或您有什么问题上做好老式的Phone1,Phone2,Phone3 ......列。这是不好的数据库设计,但它是一个很好的系统开发实践,因为它将80/20规则应用于确定项目优先级。所以总结一下:如果数据很重要,那么做对,如果数据并不重要,就把它放在一边 - 或者更好,然后把它放在一边。
- 1. 数据库同步 - 最佳实践
- 2. 数据库最佳实践
- 3. 数据库ID最佳实践
- 4. 类和数据库的最佳实践
- 5. 最佳实践/ MariaDB的数据库
- 6. 数据库最佳实践 - 状态
- 7. 版本数据库的最佳实践
- 8. 设计类来表示数据库表的最佳实践
- 9. 将Lucene存储库与源数据同步的最佳实践?
- 10. 数据层最佳实践
- 11. 最佳实践:数据库引用表
- 12. 使用数据库最佳实践?
- 13. Android数据库连接最佳实践
- 14. 最佳实践数据库设计
- 15. Sqlite数据库连接最佳实践
- 16. 最佳实践SCRIPT安装数据库
- 17. 数据库设计最佳实践
- 18. 数据库部署最佳实践
- 19. 最佳实践在数据库表
- 20. 数据库备份最佳实践
- 21. 使用来自不同子域的相同Web服务的最佳实践
- 22. CouchDB最佳实践 - 单个数据库中的所有实体与每个实体的新数据库?
- 23. Spring/Hibernate相同实体不同的数据库结构
- 24. 来自不同数据库的关联表 - 实体框架
- 25. 来自不同实体核心数据属性的最大值
- 26. 处理具有相同数据类型但列名不同的数据集的最佳实践
- 27. 最佳实践模型数据的数据库
- 28. 重叠对象/数据实体类型的最佳实践
- 29. “数据库URL”和“数据库实例”是否相同?
- 30. 具有相同实体的不同数据库服务器的nhibernate会话