数据库设计指南2(转)
19. 仔细选择数字类型
在SQL 中使用smallint 和tinyint 类型要特别小心,比如,假如你想看看月销售总额,你的总额字
段类型是smallint,那么,如果总额超过了$32,767 你就不能进行计算操作了。
— egermain
20. 删除标记
在表中包含一个“删除标记”字段,这样就可以把行标记为删除。在关系数据库里不要单独删除
某一行;最好采用清除数据程序而且要仔细维护索引整体性。
— kol
21. 避免使用触发器
触发器的功能通常可以用其他方式实现。在调试程序时触发器可能成为干扰。假如你确实需要采
用触发器,你最好集中对它文档化。
— kol
22. 包含版本机制
建议你在数据库中引入版本控制机制来确定使用中的数据库的版本。无论如何你都要实现这一要
求。时间一长,用户的需求总是会改变的。最终可能会要求修改数据库结构。虽然你可以通过检
查新字段或者索引来确定数据库结构的版本,但我发现把版本信息直接存放到数据库中不更为方
便吗?。
— Richard Foster
23. 给文本字段留足余量
ID 类型的文本字段,比如客户ID 或定单号等等都应该设置得比一般想象更大,因为时间不长你
多半就会因为要添加额外的字符而难堪不已。比方说,假设你的客户ID 为10 位数长。那你应该
把数据库表字段的长度设为12 或者13 个字符长。这算浪费空间吗?是有一点,但也没你想象的
那么多:一个字段加长3 个字符在有1 百万条记录,再加上一点索引的情况下才不过让整个数据
库多占据3MB 的空间。但这额外占据的空间却无需将来重构整个数据库就可以实现数据库规模
的增长了。
— tlundin
24. 列命名技巧
我们发现,假如你给每个表的列名都采用统一的前缀,那么在编写SQL 表达式的时候会得到大
大的简化。这样做也确实有缺点,比如破坏了自动表连接工具的作用,后者把公共列名同某些数
据库联系起来,不过就连这些工具有时不也连接错误嘛。举个简单的例子,假设有两个表:
Customer 和Order。Customer 表的前缀是cu_,所以该表内的子段名如下:cu_name_id、
cu_surname、cu_initials 和cu_address 等。Order 表的前缀是or_,所以子段名是:
or_order_id、or_cust_name_id、or_quantity 和or_description 等。
这样从数据库中选出全部数据的SQL 语句可以写成如下所示:
Select * from Customer, Order
Where cu_surname = "MYNAME"
and cu_name_id = or_cust_name_id
and or_quantity = 1;
在没有这些前缀的情况下则写成这个样子:
Select * from Customer, Order
Where Customer.surname = "MYNAME"
and Customer.name_id = Order.cust_name_id
and Order.quantity = 1
第1 个SQL 语句没少键入多少字符。但如果查询涉及到5 个表乃至更多的列你就知道这个技巧
多有用了。
— Bryce Stenberg
第3 部分— 选择键和索引
1. 数据采掘要预先计划
我所在的市场部门一度要处理8 万多份联系方式,同时填写每个客户的必要数据(这绝对不是小
活)。我从中还要确定出一组客户作为市场目标。当我从最开始设计表和字段的时候,我试图不
在主索引里增加太多的字段以便加快数据库的运行速度。然后我意识到特定的组查询和信息采掘
既不准确速度也不快。结果只好在主索引中重建而且合并了数据字段。我发现有一个指示计划相
当关键——当我想创建系统类型查找时为什么要采用号码作为主索引字段呢?我可以用传真号码
进行检索,但是它几乎就象系统类型一样对我来说并不重要。采用后者作为主字段,数据库更新
后重新索引和检索就快多了。
— hscovell
可操作数据仓库(ODS)和数据仓库(DW)这两种环境下的数据索引是有差别的。在DW 环境
下,你要考虑销售部门是如何组织销售活动的。他们并不是数据库管理员,但是他们确定表内的
键信息。这里设计人员或者数据库工作人员应该分析数据库结构从而确定出性能和正确输出之间
的最佳条件。
— teburlew
2. 使用系统生成的主键
这一天类同技巧1,但我觉得有必要在这里重复提醒大家。假如你总是在设计数据库的时候采用
系统生成的键作为主键,那么你实际控制了数据库的索引完整性。这样,数据库和非人工机制就
有效地控制了对存储数据中每一行的访问。
采用系统生成键作为主键还有一个优点:当你拥有一致的键结构时,找到逻辑缺陷很容易。
— teburlew
3. 分解字段用于索引
为了分离命名字段和包含字段以支持用户定义的报表,请考虑分解其他字段(甚至主键)为其组
成要素以便用户可以对其进行索引。索引将加快SQL 和报表生成器脚本的执行速度。比方说,
我通常在必须使用SQL LIKE 表达式的情况下创建报表,因为 case number 字段无法分解为
year、serial number、case type 和defendant code 等要素。性能也会变坏。假如年度和类型字
段可以分解为索引字段那么这些报表运行起来就会快多了。
— rdelval
4. 键设计4 原则
· 为关联字段创建外键。
· 所有的键都必须唯一。
· 避免使用复合键。
· 外键总是关联唯一的键字段。
— Peter Ritchie
5. 别忘了索引
索引是从数据库中获取数据的最高效方式之一。95%的数据库性能问题都可以采用索引技术得到
解决。作为一条规则,我通常对逻辑主键使用唯一的成组索引,对系统键(作为存储过程)采用
唯一的非成组索引,对任何外键列采用非成组索引。不过,索引就象是盐,太多了菜就篌了。你
得考虑数据库的空间有多大,表如何进行访问,还有这些访问是否主要用作读写。
— tduvall
大多数数据库都索引自动创建的主键字段,但是可别忘了索引外键,它们也是经常使用的键,比
如运行查询显示主表和所有关联表的某条记录就用得上。还有,不要索引memo/note 字段,不
要索引大型字段(有很多字符),这样作会让索引占用太多的存储空间。
— gbrayton
6. 不要索引常用的小型表
不要为小型数据表设置任何键,假如它们经常有插入和删除操作就更别这样作了。对这些插入和
删除操作的索引维护可能比扫描表空间消耗更多的时间。
— kbpatel
7. 不要把社会保障号码(SSN)选作键
永远都不要使用SSN 作为数据库的键。除了隐私原因以外,须知政府越来越趋向于不准许把
SSN 用作除收入相关以外的其他目的,SSN 需要手工输入。永远不要使用手工输入的键作为主
键,因为一旦你输入错误,你唯一能做的就是删除整个记录然后从头开始。
— teburlew
上个世纪70 年代我还在读大学的时候,我记得那时SSN 还曾被用做学号,当然尽管这么做是非
法的。而且人们也都知道这是非法的,但他们已经习惯了。后来,随着盗取身份犯罪案件的增
加,我现在的大学校园正痛苦地从一大摊子数据中把SSN 删除。
— generalist
8. 不要用用户的键
在确定采用什么字段作为表的键的时候,可一定要小心用户将要编辑的字段。通常的情况下不要
选择用户可编辑的字段作为键。这样做会迫使你采取以下两个措施:
· 在创建记录之后对用户编辑字段的行为施加限制。假如你这么做了,你可能会发现你的应用程
序在商务需求突然发生变化,而用户需要编辑那些不可编辑的字段时缺乏足够的灵活性。当用
户在输入数据之后直到保存记录才发现系统出了问题他们该怎么想?删除重建?假如记录不可
重建是否让用户走开?
· 提出一些检测和纠正键冲突的方法。通常,费点精力也就搞定了,但是从性能上来看这样做的
代价就比较大了。还有,键的纠正可能会迫使你突破你的数据和商业/用户界面层之间的隔
离。
所以还是重提一句老话:你的设计要适应用户而不是让用户来适应你的设计。
— Lamont Adams
不让主键具有可更新性的原因是在关系模式下,主键实现了不同表之间的关联。比如,
Customer 表有一个主键CustomerID,而客户的定单则存放在另一个表里。Order 表的主键可能
是OrderNo 或者OrderNo、CustomerID 和日期的组合。不管你选择哪种键设置,你都需要在
Order 表中存放CustomerID 来保证你可以给下定单的用户找到其定单记录。
假如你在Customer 表里修改了CustomerID,那么你必须找出Order 表中的所有相关记录对其进
行修改。否则,有些定单就会不属于任何客户——数据库的完整性就算完蛋了。
如果索引完整性规则施加到表一级,那么在不编写大量代码和附加删除记录的情况下几乎不可能
改变某一条记录的键和数据库内所有关联的记录。而这一过程往往错误丛生所以应该尽量避免。
— ljboast
9. 可选键有时可做主键
记住,查询数据的不是机器而是人。
假如你有可选键,你可能进一步把它用做主键。那样的话,你就拥有了建立强大索引的能力。这
样可以阻止使用数据库的人不得不连接数据库从而恰当的过滤数据。在严格控制域表的数据库
上,这种负载是比较醒目的。如果可选键真正有用,那就是达到了主键的水准。
我的看法是,假如你有可选键,比如国家表内的state_code,你不要在现有不能变动的唯一键上
创建后续的键。你要做的无非是创建毫无价值的数据。比如以下的例子:
Select count(*)
from address, state_ref
where
address.state_id = state_ref.state_id
and state_ref.state_code = 'TN'
我的做法是这样的:
Select count(*)
from address
where
and state_code = 'TN'
如你因为过度使用表的后续键建立这种表的关联,操作负载真得需要考虑一下了。
— Stocker
10. 别忘了外键
大多数数据库索引自动创建的主键字段。但别忘了索引外键字段,它们在你想查询主表中的记录
及其关联记录时每次都会用到。还有,不要索引memo/notes 字段而且不要索引大型文本字段
(许多字符),这样做会让你的索引占据大量的数据库空间。。
— gbrayton
第4 部分— 保证数据的完整性
1. 用约束而非商务规则强制数据完整性
如果你按照商务规则来处理需求,那么你应当检查商务层次/用户界面:如果商务规则以后发生变
化,那么只需要进行更新即可。
假如需求源于维护数据完整性的需要,那么在数据库层面上需要施加限制条件。
如果你在数据层确实采用了约束,你要保证有办法把更新不能通过约束检查的原因采用用户理解
的语言通知用户界面。除非你 的字段命名很冗长,否则字段名本身还不够。 — Lamont Adams
只要有可能,请采用数据库系统实现数据的完整性。这不但包括通过标准化实现的完整性而且还
包括数据的功能性。在写数据的时候还可以增加触发器来保证数据的正确性。不要依赖于商务层
保证数据完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完整性规则之上。
— Peter Ritchie
2. 分布式数据系统
对分布式系统而言,在你决定是否在各个站点复制所有数据还是把数据保存在一个地方之前应该
估计一下未来5 年或者10 年的数据量。当你把数据传送到其他站点的时候,最好在数据库字段
中设置一些标记。在目的站点收到你的数据之后更新你的标记。为了进行这种数据传输,请写下
你自己的批处理或者调度程序以特定时间间隔运行而不要让用户在每天的工作后传输数据。本地
拷贝你的维护数据,比如计算常数和利息率等,设置版本号保证数据在每个站点都完全一致。
— Suhair TechRepublic
3. 强制指示完整性
没有好办法能在有害数据进入数据库之后消除它,所以你应该在它进入数据库之前将其剔除。激
活数据库系统的指示完整性特性。这样可以保持数据的清洁而能迫使开发人员投入更多的时间处
理错误条件。
— kol
4. 关系
如果两个实体之间存在多对一关系,而且还有可能转化为多对多关系,那么你最好一开始就设置
成多对多关系。从现有的多对一关系转变为多对多关系比一开始就是多对多关系要难得多。
— CS Data Architect
5. 采用视图
为了在你的数据库和你的应用程序代码之间提供另一层抽象,你可以为你的应用程序建立专门的
视图而不必非要应用程序直接访问数据表。这样做还等于在处理数据库变更时给你提供了更多的
自由。
— Gay Howe
6. 给数据保有和恢复制定计划
考虑数据保有策略并包含在设计过程中,预先设计你的数据恢复过程。采用可以发布给用户/开发
人员的数据字典实现方便的数据识别同时保证对数据源文档化。编写在线更新来“更新查询”供
以后万一数据丢失可以重新处理更新。
— kol
7. 用存储过程让系统做重活
解决了许多麻烦来产生一个具有高度完整性的数据库解决方案之后,我所在的团队决定封装一些
关联表的功能组,提供一整套常规的存储过程来访问各组以便加快速度和简化客户程序代码的开
发。在此期间,我们发现3GL 编码器设置了所有可能的错误条件,比如以下所示:
SELECT Cnt = COUNT (*)
FROM [<Table>]
WHERE [<primary key column>] = <new value>
IF Cnt = 0
BEGIN
INSERT INTO [<Table>]
( [< primary key column>] )
VALUES ( <New value> )
END
ELSE
BEGIN
<indicate duplication error>
END
而一个非3GL 编码器是这样做的:
INSERT INTO [<Table>]
( [< primary key column>] )
VALUES
( <New value> )
IF @@ERROR = 2627 -- Literal error code for Primary Key Constraint
BEGIN
<indicate duplication error>
END
第2 个程序简单多了,而且事实上,利用了我们给数据库的功能。虽然我个人不喜欢使用嵌入文
字(2627)。但是那样可以很方便地用一点预先处理来代替。数据库不只是一个存放数据的地
方,它也是简化编码之地。
— a-smith
8. 使用查找
控制数据完整性的最佳方式就是限制用户的选择。只要有可能都应该提供给用户一个清晰的价值
列表供其选择。这样将减少键入代码的错误和误解同时提供数据的一致性。某些公共数据特别适
合查找:国家代码、状态代码等。
— CS Data Architect
第5 部分— 各种小技巧
1. 文档、文档、文档
对所有的快捷方式、命名规范、限制和函数都要编制文档。
— nickypendragon
采用给表、列、触发器等加注释的数据库工具。是的,这有点费事,但从长远来看,这样做对开
发、支持和跟踪修改非常有用。
— chardove
取决于你使用的数据库系统,可能有一些软件会给你一些供你很快上手的文档。你可能希望先开
始在说,然后获得越来越多的细节。或者你可能希望周期性的预排,在输入新数据同时随着你的
进展对每一部分细节化。不管你选择哪种方式,总要对你的数据库文档化,或者在数据库自身的
内部或者单独建立文档。这样,当你过了一年多时间后再回过头来做第2 个版本,你犯错的机会
将大大减少。
— mrs_helm
2. 使用常用英语(或者其他任何语言)而不要使用编码
为什么我们经常采用编码(比如9935A 可能是墨水笔的供应代码,4XF788-Q 可能是帐目编
码)?理由很多。但是用户通常都用英语进行思考而不是编码。工作5 年的会计或许知道
4XF788-Q 是什么东西,但新来的可就不一定了。在创建下拉菜单、列表、报表时最好按照英语
名排序。假如你需要编码,那你可以在编码旁附上用户知道的英语。
— amasa
3. 保存常用信息
让一个表专门存放一般数据库信息非常有用。我常在这个表里存放数据库当前版本、最近检查/修
复(对Access)、关联设计文档的名称、客户等信息。这样可以实现一种简单机制跟踪数据
库,当客户抱怨他们的数据库没有达到希望的要求而与你联系时,这样做对非客户机/服务器环境
特别有用。
— Richard Foster
4. 测试、测试、反复测试
建立或者修订数据库之后,必须用用户新输入的数据测试数据字段。最重要的是,让用户进行测
试并且同用户一道保证你选择的数据类型满足商业要求。测试需要在把新数据库投入实际服务之
前完成。
— juneebug
5. 检查设计
在开发期间检查数据库设计的常用技术是通过其所支持的应用程序原型检查数据库。换句话说,
针对每一种最终表达数据的原型应用,保证你检查了数据模型并且查看如何取出数据。
— jgootee
6. Access 设计技巧
对复杂的Microsoft Access 数据库应用程序而言,可以把所有的主表放在一个数据库文件里,然
后增加其他数据库文件和装载同原有数据库有关的特殊函数。根据需要用这些函数连接到主文件
中的主表。比如数据输入、数据QC、统计分析、向管理层或者政府部门提供报表以及各类只读
查询等。这一措施简化了用户和组权限的分配,而且有利于应用程序函数的分组和划分,从而在
程序必须修改的时候易于管理。
— Dennis Walden
在SQL 中使用smallint 和tinyint 类型要特别小心,比如,假如你想看看月销售总额,你的总额字
段类型是smallint,那么,如果总额超过了$32,767 你就不能进行计算操作了。
— egermain
20. 删除标记
在表中包含一个“删除标记”字段,这样就可以把行标记为删除。在关系数据库里不要单独删除
某一行;最好采用清除数据程序而且要仔细维护索引整体性。
— kol
21. 避免使用触发器
触发器的功能通常可以用其他方式实现。在调试程序时触发器可能成为干扰。假如你确实需要采
用触发器,你最好集中对它文档化。
— kol
22. 包含版本机制
建议你在数据库中引入版本控制机制来确定使用中的数据库的版本。无论如何你都要实现这一要
求。时间一长,用户的需求总是会改变的。最终可能会要求修改数据库结构。虽然你可以通过检
查新字段或者索引来确定数据库结构的版本,但我发现把版本信息直接存放到数据库中不更为方
便吗?。
— Richard Foster
23. 给文本字段留足余量
ID 类型的文本字段,比如客户ID 或定单号等等都应该设置得比一般想象更大,因为时间不长你
多半就会因为要添加额外的字符而难堪不已。比方说,假设你的客户ID 为10 位数长。那你应该
把数据库表字段的长度设为12 或者13 个字符长。这算浪费空间吗?是有一点,但也没你想象的
那么多:一个字段加长3 个字符在有1 百万条记录,再加上一点索引的情况下才不过让整个数据
库多占据3MB 的空间。但这额外占据的空间却无需将来重构整个数据库就可以实现数据库规模
的增长了。
— tlundin
24. 列命名技巧
我们发现,假如你给每个表的列名都采用统一的前缀,那么在编写SQL 表达式的时候会得到大
大的简化。这样做也确实有缺点,比如破坏了自动表连接工具的作用,后者把公共列名同某些数
据库联系起来,不过就连这些工具有时不也连接错误嘛。举个简单的例子,假设有两个表:
Customer 和Order。Customer 表的前缀是cu_,所以该表内的子段名如下:cu_name_id、
cu_surname、cu_initials 和cu_address 等。Order 表的前缀是or_,所以子段名是:
or_order_id、or_cust_name_id、or_quantity 和or_description 等。
这样从数据库中选出全部数据的SQL 语句可以写成如下所示:
Select * from Customer, Order
Where cu_surname = "MYNAME"
and cu_name_id = or_cust_name_id
and or_quantity = 1;
在没有这些前缀的情况下则写成这个样子:
Select * from Customer, Order
Where Customer.surname = "MYNAME"
and Customer.name_id = Order.cust_name_id
and Order.quantity = 1
第1 个SQL 语句没少键入多少字符。但如果查询涉及到5 个表乃至更多的列你就知道这个技巧
多有用了。
— Bryce Stenberg
第3 部分— 选择键和索引
1. 数据采掘要预先计划
我所在的市场部门一度要处理8 万多份联系方式,同时填写每个客户的必要数据(这绝对不是小
活)。我从中还要确定出一组客户作为市场目标。当我从最开始设计表和字段的时候,我试图不
在主索引里增加太多的字段以便加快数据库的运行速度。然后我意识到特定的组查询和信息采掘
既不准确速度也不快。结果只好在主索引中重建而且合并了数据字段。我发现有一个指示计划相
当关键——当我想创建系统类型查找时为什么要采用号码作为主索引字段呢?我可以用传真号码
进行检索,但是它几乎就象系统类型一样对我来说并不重要。采用后者作为主字段,数据库更新
后重新索引和检索就快多了。
— hscovell
可操作数据仓库(ODS)和数据仓库(DW)这两种环境下的数据索引是有差别的。在DW 环境
下,你要考虑销售部门是如何组织销售活动的。他们并不是数据库管理员,但是他们确定表内的
键信息。这里设计人员或者数据库工作人员应该分析数据库结构从而确定出性能和正确输出之间
的最佳条件。
— teburlew
2. 使用系统生成的主键
这一天类同技巧1,但我觉得有必要在这里重复提醒大家。假如你总是在设计数据库的时候采用
系统生成的键作为主键,那么你实际控制了数据库的索引完整性。这样,数据库和非人工机制就
有效地控制了对存储数据中每一行的访问。
采用系统生成键作为主键还有一个优点:当你拥有一致的键结构时,找到逻辑缺陷很容易。
— teburlew
3. 分解字段用于索引
为了分离命名字段和包含字段以支持用户定义的报表,请考虑分解其他字段(甚至主键)为其组
成要素以便用户可以对其进行索引。索引将加快SQL 和报表生成器脚本的执行速度。比方说,
我通常在必须使用SQL LIKE 表达式的情况下创建报表,因为 case number 字段无法分解为
year、serial number、case type 和defendant code 等要素。性能也会变坏。假如年度和类型字
段可以分解为索引字段那么这些报表运行起来就会快多了。
— rdelval
4. 键设计4 原则
· 为关联字段创建外键。
· 所有的键都必须唯一。
· 避免使用复合键。
· 外键总是关联唯一的键字段。
— Peter Ritchie
5. 别忘了索引
索引是从数据库中获取数据的最高效方式之一。95%的数据库性能问题都可以采用索引技术得到
解决。作为一条规则,我通常对逻辑主键使用唯一的成组索引,对系统键(作为存储过程)采用
唯一的非成组索引,对任何外键列采用非成组索引。不过,索引就象是盐,太多了菜就篌了。你
得考虑数据库的空间有多大,表如何进行访问,还有这些访问是否主要用作读写。
— tduvall
大多数数据库都索引自动创建的主键字段,但是可别忘了索引外键,它们也是经常使用的键,比
如运行查询显示主表和所有关联表的某条记录就用得上。还有,不要索引memo/note 字段,不
要索引大型字段(有很多字符),这样作会让索引占用太多的存储空间。
— gbrayton
6. 不要索引常用的小型表
不要为小型数据表设置任何键,假如它们经常有插入和删除操作就更别这样作了。对这些插入和
删除操作的索引维护可能比扫描表空间消耗更多的时间。
— kbpatel
7. 不要把社会保障号码(SSN)选作键
永远都不要使用SSN 作为数据库的键。除了隐私原因以外,须知政府越来越趋向于不准许把
SSN 用作除收入相关以外的其他目的,SSN 需要手工输入。永远不要使用手工输入的键作为主
键,因为一旦你输入错误,你唯一能做的就是删除整个记录然后从头开始。
— teburlew
上个世纪70 年代我还在读大学的时候,我记得那时SSN 还曾被用做学号,当然尽管这么做是非
法的。而且人们也都知道这是非法的,但他们已经习惯了。后来,随着盗取身份犯罪案件的增
加,我现在的大学校园正痛苦地从一大摊子数据中把SSN 删除。
— generalist
8. 不要用用户的键
在确定采用什么字段作为表的键的时候,可一定要小心用户将要编辑的字段。通常的情况下不要
选择用户可编辑的字段作为键。这样做会迫使你采取以下两个措施:
· 在创建记录之后对用户编辑字段的行为施加限制。假如你这么做了,你可能会发现你的应用程
序在商务需求突然发生变化,而用户需要编辑那些不可编辑的字段时缺乏足够的灵活性。当用
户在输入数据之后直到保存记录才发现系统出了问题他们该怎么想?删除重建?假如记录不可
重建是否让用户走开?
· 提出一些检测和纠正键冲突的方法。通常,费点精力也就搞定了,但是从性能上来看这样做的
代价就比较大了。还有,键的纠正可能会迫使你突破你的数据和商业/用户界面层之间的隔
离。
所以还是重提一句老话:你的设计要适应用户而不是让用户来适应你的设计。
— Lamont Adams
不让主键具有可更新性的原因是在关系模式下,主键实现了不同表之间的关联。比如,
Customer 表有一个主键CustomerID,而客户的定单则存放在另一个表里。Order 表的主键可能
是OrderNo 或者OrderNo、CustomerID 和日期的组合。不管你选择哪种键设置,你都需要在
Order 表中存放CustomerID 来保证你可以给下定单的用户找到其定单记录。
假如你在Customer 表里修改了CustomerID,那么你必须找出Order 表中的所有相关记录对其进
行修改。否则,有些定单就会不属于任何客户——数据库的完整性就算完蛋了。
如果索引完整性规则施加到表一级,那么在不编写大量代码和附加删除记录的情况下几乎不可能
改变某一条记录的键和数据库内所有关联的记录。而这一过程往往错误丛生所以应该尽量避免。
— ljboast
9. 可选键有时可做主键
记住,查询数据的不是机器而是人。
假如你有可选键,你可能进一步把它用做主键。那样的话,你就拥有了建立强大索引的能力。这
样可以阻止使用数据库的人不得不连接数据库从而恰当的过滤数据。在严格控制域表的数据库
上,这种负载是比较醒目的。如果可选键真正有用,那就是达到了主键的水准。
我的看法是,假如你有可选键,比如国家表内的state_code,你不要在现有不能变动的唯一键上
创建后续的键。你要做的无非是创建毫无价值的数据。比如以下的例子:
Select count(*)
from address, state_ref
where
address.state_id = state_ref.state_id
and state_ref.state_code = 'TN'
我的做法是这样的:
Select count(*)
from address
where
and state_code = 'TN'
如你因为过度使用表的后续键建立这种表的关联,操作负载真得需要考虑一下了。
— Stocker
10. 别忘了外键
大多数数据库索引自动创建的主键字段。但别忘了索引外键字段,它们在你想查询主表中的记录
及其关联记录时每次都会用到。还有,不要索引memo/notes 字段而且不要索引大型文本字段
(许多字符),这样做会让你的索引占据大量的数据库空间。。
— gbrayton
第4 部分— 保证数据的完整性
1. 用约束而非商务规则强制数据完整性
如果你按照商务规则来处理需求,那么你应当检查商务层次/用户界面:如果商务规则以后发生变
化,那么只需要进行更新即可。
假如需求源于维护数据完整性的需要,那么在数据库层面上需要施加限制条件。
如果你在数据层确实采用了约束,你要保证有办法把更新不能通过约束检查的原因采用用户理解
的语言通知用户界面。除非你 的字段命名很冗长,否则字段名本身还不够。 — Lamont Adams
只要有可能,请采用数据库系统实现数据的完整性。这不但包括通过标准化实现的完整性而且还
包括数据的功能性。在写数据的时候还可以增加触发器来保证数据的正确性。不要依赖于商务层
保证数据完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完整性规则之上。
— Peter Ritchie
2. 分布式数据系统
对分布式系统而言,在你决定是否在各个站点复制所有数据还是把数据保存在一个地方之前应该
估计一下未来5 年或者10 年的数据量。当你把数据传送到其他站点的时候,最好在数据库字段
中设置一些标记。在目的站点收到你的数据之后更新你的标记。为了进行这种数据传输,请写下
你自己的批处理或者调度程序以特定时间间隔运行而不要让用户在每天的工作后传输数据。本地
拷贝你的维护数据,比如计算常数和利息率等,设置版本号保证数据在每个站点都完全一致。
— Suhair TechRepublic
3. 强制指示完整性
没有好办法能在有害数据进入数据库之后消除它,所以你应该在它进入数据库之前将其剔除。激
活数据库系统的指示完整性特性。这样可以保持数据的清洁而能迫使开发人员投入更多的时间处
理错误条件。
— kol
4. 关系
如果两个实体之间存在多对一关系,而且还有可能转化为多对多关系,那么你最好一开始就设置
成多对多关系。从现有的多对一关系转变为多对多关系比一开始就是多对多关系要难得多。
— CS Data Architect
5. 采用视图
为了在你的数据库和你的应用程序代码之间提供另一层抽象,你可以为你的应用程序建立专门的
视图而不必非要应用程序直接访问数据表。这样做还等于在处理数据库变更时给你提供了更多的
自由。
— Gay Howe
6. 给数据保有和恢复制定计划
考虑数据保有策略并包含在设计过程中,预先设计你的数据恢复过程。采用可以发布给用户/开发
人员的数据字典实现方便的数据识别同时保证对数据源文档化。编写在线更新来“更新查询”供
以后万一数据丢失可以重新处理更新。
— kol
7. 用存储过程让系统做重活
解决了许多麻烦来产生一个具有高度完整性的数据库解决方案之后,我所在的团队决定封装一些
关联表的功能组,提供一整套常规的存储过程来访问各组以便加快速度和简化客户程序代码的开
发。在此期间,我们发现3GL 编码器设置了所有可能的错误条件,比如以下所示:
SELECT Cnt = COUNT (*)
FROM [<Table>]
WHERE [<primary key column>] = <new value>
IF Cnt = 0
BEGIN
INSERT INTO [<Table>]
( [< primary key column>] )
VALUES ( <New value> )
END
ELSE
BEGIN
<indicate duplication error>
END
而一个非3GL 编码器是这样做的:
INSERT INTO [<Table>]
( [< primary key column>] )
VALUES
( <New value> )
IF @@ERROR = 2627 -- Literal error code for Primary Key Constraint
BEGIN
<indicate duplication error>
END
第2 个程序简单多了,而且事实上,利用了我们给数据库的功能。虽然我个人不喜欢使用嵌入文
字(2627)。但是那样可以很方便地用一点预先处理来代替。数据库不只是一个存放数据的地
方,它也是简化编码之地。
— a-smith
8. 使用查找
控制数据完整性的最佳方式就是限制用户的选择。只要有可能都应该提供给用户一个清晰的价值
列表供其选择。这样将减少键入代码的错误和误解同时提供数据的一致性。某些公共数据特别适
合查找:国家代码、状态代码等。
— CS Data Architect
第5 部分— 各种小技巧
1. 文档、文档、文档
对所有的快捷方式、命名规范、限制和函数都要编制文档。
— nickypendragon
采用给表、列、触发器等加注释的数据库工具。是的,这有点费事,但从长远来看,这样做对开
发、支持和跟踪修改非常有用。
— chardove
取决于你使用的数据库系统,可能有一些软件会给你一些供你很快上手的文档。你可能希望先开
始在说,然后获得越来越多的细节。或者你可能希望周期性的预排,在输入新数据同时随着你的
进展对每一部分细节化。不管你选择哪种方式,总要对你的数据库文档化,或者在数据库自身的
内部或者单独建立文档。这样,当你过了一年多时间后再回过头来做第2 个版本,你犯错的机会
将大大减少。
— mrs_helm
2. 使用常用英语(或者其他任何语言)而不要使用编码
为什么我们经常采用编码(比如9935A 可能是墨水笔的供应代码,4XF788-Q 可能是帐目编
码)?理由很多。但是用户通常都用英语进行思考而不是编码。工作5 年的会计或许知道
4XF788-Q 是什么东西,但新来的可就不一定了。在创建下拉菜单、列表、报表时最好按照英语
名排序。假如你需要编码,那你可以在编码旁附上用户知道的英语。
— amasa
3. 保存常用信息
让一个表专门存放一般数据库信息非常有用。我常在这个表里存放数据库当前版本、最近检查/修
复(对Access)、关联设计文档的名称、客户等信息。这样可以实现一种简单机制跟踪数据
库,当客户抱怨他们的数据库没有达到希望的要求而与你联系时,这样做对非客户机/服务器环境
特别有用。
— Richard Foster
4. 测试、测试、反复测试
建立或者修订数据库之后,必须用用户新输入的数据测试数据字段。最重要的是,让用户进行测
试并且同用户一道保证你选择的数据类型满足商业要求。测试需要在把新数据库投入实际服务之
前完成。
— juneebug
5. 检查设计
在开发期间检查数据库设计的常用技术是通过其所支持的应用程序原型检查数据库。换句话说,
针对每一种最终表达数据的原型应用,保证你检查了数据模型并且查看如何取出数据。
— jgootee
6. Access 设计技巧
对复杂的Microsoft Access 数据库应用程序而言,可以把所有的主表放在一个数据库文件里,然
后增加其他数据库文件和装载同原有数据库有关的特殊函数。根据需要用这些函数连接到主文件
中的主表。比如数据输入、数据QC、统计分析、向管理层或者政府部门提供报表以及各类只读
查询等。这一措施简化了用户和组权限的分配,而且有利于应用程序函数的分组和划分,从而在
程序必须修改的时候易于管理。
— Dennis Walden