﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-西瓜地儿-随笔分类-数据库设计</title><link>http://www.blogjava.net/ashutc/category/48546.html</link><description>沈阳求职（java3年以上经验）！ashutc@126.com</description><language>zh-cn</language><lastBuildDate>Tue, 10 May 2011 09:17:32 GMT</lastBuildDate><pubDate>Tue, 10 May 2011 09:17:32 GMT</pubDate><ttl>60</ttl><item><title>数据库设计表和字段技巧</title><link>http://www.blogjava.net/ashutc/archive/2011/05/10/349927.html</link><dc:creator>西瓜</dc:creator><author>西瓜</author><pubDate>Tue, 10 May 2011 09:15:00 GMT</pubDate><guid>http://www.blogjava.net/ashutc/archive/2011/05/10/349927.html</guid><wfw:comment>http://www.blogjava.net/ashutc/comments/349927.html</wfw:comment><comments>http://www.blogjava.net/ashutc/archive/2011/05/10/349927.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ashutc/comments/commentRss/349927.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ashutc/services/trackbacks/349927.html</trackback:ping><description><![CDATA[<h1><font size="2"><strong>&nbsp; 1. 原始单据与实体之间的关系</strong> </font>
</h1>
<p style="text-indent: 2em"><font size="2">可以是一对一、一对多、多对多的关系。在一般情况下，它们是一
对一的关系：即一张原始单据对应且只对应一个实体。在特殊情况下，它们可能是一对多或多对一的关系，即一张原始单证对应多个实体，或多张原始单证对应一个
实体。这里的实体可以理解为基本表。明确这种对应关系后，对我们设计录入界面大有好处。 </font></p>
<p style="text-indent: 2em"><font size="2">【例1】：一份员工履历资料，在人力资源信息系统中，就对应三个基本表：员工基本情况表、社会关系表、工作简历表。这就是&#8220;一张原始单证对应多个实体&#8221;的典型例子。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>2. 主键与外键</strong> </font></p>
<p style="text-indent: 2em"><font size="2">一般而言，一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键，也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。 </font></p>
<p style="text-indent: 2em"><font size="2">主键与外键的设计，在全局数据库的设计中，占有重要地位。当全
局数据库的设计完成以后，有个美国数据库设计专家说：&#8220;键，到处都是键，除了键之外，什么也没有&#8221;，这就是他的数据库设计经验之谈，也反映了他对信息系统
核心(数据模型)的高度抽象思想。因为：主键是实体的高度抽象，主键与外键的配对，表示实体之间的连接。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>3. 基本表的性质</strong> </font></p>
<p style="text-indent: 2em"><font size="2">基本表与中间表、临时表不同，因为它具有如下四个特性： </font></p>
<p style="text-indent: 2em"><font size="2">(1) 原子性。基本表中的字段是不可再分解的。 </font></p>
<p style="text-indent: 2em"><font size="2">(2) 原始性。基本表中的记录是原始数据（基础数据）的记录。 </font></p>
<p style="text-indent: 2em"><font size="2">(3) 演绎性。由基本表与代码表中的数据，可以派生出所有的输出数据。 </font></p>
<p style="text-indent: 2em"><font size="2">(4) 稳定性。基本表的结构是相对稳定的，表中的记录是要长期保存的。 </font></p>
<p style="text-indent: 2em"><font size="2">理解基本表的性质后，在设计数据库时，就能将基本表与中间表、临时表区分开来。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>4. 范式标准</strong> </font></p>
<p style="text-indent: 2em"><font size="2">基本表及其字段之间的关系, 应尽量满足第三范式。但是，满足第三范式的数据库设计，往往不是最好的设计。为了提高数据库的运行效率，常常需要降低范式标准：适当增加冗余，达到以空间换时间的目的。 </font></p>
<p style="text-indent: 2em"><font size="2">【例2】：有一张存放商品的基本表，如表1所示。&#8220;金额&#8221;这个字段的存在，表明该表的设计不满足第三范式，因为&#8220;金额&#8221;可以由&#8220;单价&#8221;乘以&#8220;数量&#8221;得到，说明&#8220;金额&#8221;是冗余字段。但是，增加&#8220;金额&#8221;这个冗余字段，可以提高查询统计的速度，这就是以空间换时间的作法。 </font></p>
<p style="text-indent: 2em"><font size="2">在Rose 2002中，规定列有两种类型：数据列和计算列。&#8220;金额&#8221;这样的列被称为&#8220;计算列&#8221;，而&#8220;单价&#8221;和&#8220;数量&#8221;这样的列被称为&#8220;数据列&#8221;。 </font></p>
<p style="text-indent: 2em"><font size="2">表1 商品表的表结构 </font></p>
<p style="text-indent: 2em"><font size="2">商品名称 商品型号 单价 数量 金额 </font></p>
<p style="text-indent: 2em"><font size="2">电视机 29吋 2,500 40 100,000　　 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>5. 通俗地理解三个范式</strong> </font></p>
<p style="text-indent: 2em"><font size="2">通俗地理解三个范式，对于数据库设计大有好处。在数据库设计中，为了更好地应用三个范式，就必须通俗地理解三个范式(通俗地理解是够用的理解，并不是最科学最准确的理解)： </font></p>
<p style="text-indent: 2em"><font size="2">第一范式：1NF是对属性的原子性约束，要求属性具有原子性，不可再分解； </font></p>
<p style="text-indent: 2em"><font size="2">第二范式：2NF是对记录的惟一性约束，要求记录有惟一标识，即实体的惟一性； </font></p>
<p style="text-indent: 2em"><font size="2">第三范式：3NF是对字段冗余性的约束，即任何字段不能由其他字段派生出来，它要求字段没有冗余. </font></p>
<p style="text-indent: 2em"><font size="2">没有冗余的数据库设计可以做到。但是，没有冗余的数据库未必是
最好的数据库，有时为了提高运行效率，就必须降低范式标准，适当保留冗余数据。具体做法是：在概念数据模型设计时遵守第三范式，降低范式标准的工作放到物
理数据模型设计时考虑。降低范式就是增加字段，允许冗余。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>6. 要善于识别与正确处理多对多的关系</strong> </font></p>
<p style="text-indent: 2em"><font size="2">若两个实体之间存在多对多的关系，则应消除这种关系。消除的办法是，在两者之间增加第三个实体。这样，原来一个多对多的关系，现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个</font>实体中去。这里的第三个实体，实质上是一个较复杂的关系，它对应一张基本表。一般来讲，数据库设计工具不能识别多对多的关系，但能处理多对多的关系。 </p>
<p style="text-indent: 2em"><font size="2">【例3】：在&#8220;图书馆信息系统&#8221;中，&#8220;图书&#8221;是一个实体，&#8220;读
者&#8221;也是一个实体。这两个实体之间的关系，是一个典型的多对多关系：一本图书在不同时间可以被多个读者借阅，一个读者又可以借多本图书。为此，要在二者之
间增加第三个实体，该实体取名为&#8220;借还书&#8221;，它的属性为：借还时间、借还标志(0表示借书，1表示还书)，另外，它还应该有两个外键(&#8220;图书&#8221;的主键，
&#8220;读者&#8221;的主键)，使它能与&#8220;图书&#8221;和&#8220;读者&#8221;连接。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>7. 主键PK的取值方法</strong> </font></p>
<p style="text-indent: 2em"><font size="2">PK是供程序员使用的表间连接工具，可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时，建议字段的个数不要太多，多了不但索引占用空间大，而且速度也慢。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>8. 正确认识数据冗余</strong> </font></p>
<p style="text-indent: 2em"><font size="2">主键与外键在多表中的重复出现, 不属于数据冗余，这个概念必须清楚，事实上有许多人还不清楚。非键字段的重复出现, 才是数据冗余！而且是一种低级冗余，即重复性的冗余。高级冗余不是字段的重复出现，而是字段的派生出现。 </font></p>
<p style="text-indent: 2em"><font size="2">【例4】：商品中的&#8220;单价、数量、金额&#8221;三个字段，&#8220;金额&#8221;就
是由&#8220;单价&#8221;乘以&#8220;数量&#8221;派生出来的，它就是冗余，而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性，因为同一数
据，可能从不同时间、地点、角色上多次录入。因此，我们提倡高级冗余(派生性冗余)，反对低级冗余(重复性冗余)。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>9. E&#8211;R图没有标准答案</strong> </font></p>
<p style="text-indent: 2em"><font size="2">信息系统的E&#8211;R图没有标准答案，因为它的设计与画法不是惟一
的，只要它覆盖了系统需求的业务范围和功能内容，就是可行的。反之要修改E&#8211;R图。尽管它没有惟一的标准答案，并不意味着可以随意设计。好的E—R图的标
准是：结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>10. 视图技术在数据库设计中很有用</strong> </font></p>
<p style="text-indent: 2em"><font size="2">与基本表、代码表、中间表不同，视图是一种虚表，它依赖数据源
的实表而存在。视图是供程序员使用数据库的一个窗口，是基表数据综合的一种形式,
是数据处理的一种方法，是用户数据保密的一种手段。为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。
若三层视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。 </font></p>
<p style="text-indent: 2em"><font size="2">对于某些与国家政治、经济、技术、军事和安全利益有关的信息系
统，视图的作用更加重要。这些系统的基本表完成物理设计之后，立即在基本表上建立第一层视图，这层视图的个数和结构，与基本表的个数和结构是完全相同。并
且规定，所有的程序员，一律只准在视图上操作。只有数据库管理员，带着多个人员共同掌握的&#8220;安全钥匙&#8221;，才能直接在基本表上操作。请读者想想：这是为什
么？ </font></p>
<p style="text-indent: 2em"><font size="2"><strong>11. 中间表、报表和临时表</strong> </font></p>
<p style="text-indent: 2em"><font size="2">中间表是存放统计数据的表，它是为数据仓库、输出报表或查询结果而设计的，有时它没有主键与外键(数据仓库除外)。临时表是程序员个人设计的，存放临时记录，为个人所用。基表和中间表由DBA维护，临时表由程序员自己用程序自动维护。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>12. 完整性约束表现在三个方面</strong> </font></p>
<p style="text-indent: 2em"><font size="2">域的完整性：用Check来实现约束，在数据库设计工具中，对字段的取值范围进行定义时，有一个Check按钮，通过它定义字段的值城。参照完整性：用PK、FK、表级触发器来实现。用户定义完整性：它是一些业务规则，用存储过程和触发器来实现。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>13. 防止数据库设计打补丁的方法是&#8220;三少原则&#8221;</strong> </font></p>
<p style="text-indent: 2em"><font size="2">(1) 一个数据</font>库中表的个数越少越好。只有表的个数少了，才能说明系统的E&#8211;R图少而精，去掉了重复的多余的实体，形成了对客观世界的高度抽象，进行了系统的数据集成，防止了打补丁式的设计； </p>
<p style="text-indent: 2em"><font size="2">(2) 一个表中组合主键的字段个数越少越好。因为主键的作用，一是建主键索引，二是做为子表的外键，所以组合主键的字段个数少了，不仅节省了运行时间，而且节省了索引存储空间； </font></p>
<p style="text-indent: 2em"><font size="2">(3)
一个表中的字段个数越少越好。只有字段的个数少了，才能说明在系统中不存在数据重复，且很少有数据冗余，更重要的是督促读者学会&#8220;列变行&#8221;，这样就防止了
将子表中的字段拉入到主表中去，在主表中留下许多空余的字段。所谓&#8220;列变行&#8221;，就是将主表中的一部分内容拉出去，另外单独建一个子表。这个方法很简单，有
的人就是不习惯、不采纳、不执行。 </font></p>
<p style="text-indent: 2em"><font size="2">数据库设计的实用原则是：在数据冗余和处理速度之间找到合适的
平衡点。&#8220;三少&#8221;是一个整体概念，综合观点，不能孤立某一个原则。该原则是相对的，不是绝对的。&#8220;三多&#8221;原则肯定是错误的。试想：若覆盖系统同样的功能，
一百个实体(共一千个属性) 的E&#8211;R图，肯定比二百个实体(共二千个属性) 的E&#8211;R图，要好得多。 </font></p>
<p style="text-indent: 2em"><font size="2">提倡&#8220;三少&#8221;原则，是叫读者学会利用数据库设计技术进行系统的
数据集成。数据集成的步骤是将文件系统集成为应用数据库，将应用数据库集成为主题数据库，将主题数据库集成为全局综合数据库。集成的程度越高，数据共享性
就越强，信息孤岛现象就越少，整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。 </font></p>
<p style="text-indent: 2em"><font size="2">提倡&#8220;三少&#8221;原则的目的，是防止读者利用打补丁技术，不断地对
数据库进行增删改，使企业数据库变成了随意设计数据库表的&#8220;垃圾堆&#8221;，或数据库表的&#8220;大杂院&#8221;，最后造成数据库中的基本表、代码表、中间表、临时表杂乱无
章，不计其数，导致企事业单位的信息系统无法维护而瘫痪。 </font></p>
<p style="text-indent: 2em"><font size="2">&#8220;三多&#8221;原则任何人都可以做到，该原则是&#8220;打补丁方法&#8221;设计数据库的歪理学说。&#8220;三少&#8221;原则是少而精的原则，它要求有较高的数据库设计技巧与艺术，不是任何人都能做到的，因为该原则是杜绝用&#8220;打补丁方法&#8221;设计数据库的理论依据。 </font></p>
<p style="text-indent: 2em"><font size="2"><strong>14. 提高数据库运行效率的办法</strong> </font></p>
<p style="text-indent: 2em"><font size="2">在给定的系统硬件和系统软件条件下，提高数据库系统的运行效率的办法是： </font></p>
<p style="text-indent: 2em"><font size="2">(1) 在数据库物理设计时，降低范式，增加冗余, 少用触发器, 多用存储过程。 </font></p>
<p style="text-indent: 2em"><font size="2">(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条)，复杂计算要先在数据库外面，以文件系统方式用C++语言计算处理完成之后，最后才入库追加到表中去。这是电信计费系统设计的经验。 </font></p>
<p style="text-indent: 2em"><font size="2">(3) 发现某个表的记录太多，例如超过一千万条，则要对该表进行水平分割。水平分割的做法是，以该表主键PK的某个值为界线，将该表的记录水平分割为两个表。若发现某个表的字段太多，例如超过八十个，则垂直分割该表，将原来的一个表分解为两个表。 </font></p>
<p style="text-indent: 2em"><font size="2">(4) 对数据库管理系统DBMS进行系统优化，即优化各种系统参数，如缓冲区个数。 </font></p>
<p style="text-indent: 2em"><font size="2">(5) 在使用面向数据的SQL语言进行程序设计时，尽量采取优化算法。 </font></p>
<p style="text-indent: 2em"><font size="2">总之，要提高数据库的运行效率，必须从数据库系统级优化、数据库设计级优化、程序实现级优化，这三个层次上同时下功夫。 </font></p>
<p style="text-indent: 2em"><font size="2">上述十四个技巧，是许多人在大量的数据库分析与设计实践中，逐步总结出来的。对于这些经验的运用，读者不能生帮硬套，死记硬背，而要消化理解，实事求是，灵活掌握。并逐步做到：在应用中发展，在发展中应用。</font></p>
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/ashutc/aggbug/349927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ashutc/" target="_blank">西瓜</a> 2011-05-10 17:15 <a href="http://www.blogjava.net/ashutc/archive/2011/05/10/349927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据表的设计原则</title><link>http://www.blogjava.net/ashutc/archive/2011/05/10/349926.html</link><dc:creator>西瓜</dc:creator><author>西瓜</author><pubDate>Tue, 10 May 2011 09:12:00 GMT</pubDate><guid>http://www.blogjava.net/ashutc/archive/2011/05/10/349926.html</guid><wfw:comment>http://www.blogjava.net/ashutc/comments/349926.html</wfw:comment><comments>http://www.blogjava.net/ashutc/archive/2011/05/10/349926.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ashutc/comments/commentRss/349926.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ashutc/services/trackbacks/349926.html</trackback:ping><description><![CDATA[<br />
<p>(1)不应针对整个系统进行数据库设计，而应该根据系统架构中的组件划分，针对每个组件所处理的业务进行组件单元的数据库设计；不同组件间所对应的
数据库表之间的关联应尽可能减少，如果不同组件间的表需要外键关联也尽量不要创建外键关联，而只是记录关联表的一个主键，确保组件对应的表之间的独立性，
为系统或表结构的重构提供可能性。 </p>
<p>(2)采用领域模型驱动的方式和自顶向下的思路进行数据库设计，首先分析系统业务，根据职责定义对象。对象要符合封装的特性，确保与职责相关的数据
项被定义在一个对象之内，这些数据项能够完整描述该职责，不会出现职责描述缺失。并且一个对象有且只有一项职责，如果一个对象要负责两个或两个以上的职
责，应进行分拆。 </p>
<p>(3)根据建立的领域模型进行数据库表的映射，此时应参考数据库设计第二范式：一个表中的所有非关键字属性都依赖于整个关键字。关键字可以是一个属
性，也可以是多个属性的集合，不论那种方式，都应确保关键字能够保证唯一性。在确定关键字时，应保证关键字不会参与业务且不会出现更新异常，这时，最优解
决方案为采用一个自增数值型属性或一个随机字符串作为表的关键字。 </p>
<p>(4)由于第一点所述的领域模型驱动的方式设计数据库表结构，领域模型中的每一个对象只有一项职责，所以对象中的数据项不存在传递依赖，所以，这种思路的数据库表结构设计从一开始即满足第三范式：一个表应满足第二范式，且属性间不存在传递依赖。 </p>
<p>(5)同样，由于对象职责的单一性以及对象之间的关系反映的是业务逻辑之间的关系，所以在领域模型中的对象存在主对象和从对象之分，从对象是从1－N或N－N的角度进一步主对象的业务逻辑，所以从对象及对象关系映射为的表及表关联关系不存在删除和插入异常。 </p>
<p>(6)在映射后得出的数据库表结构中，应再根据第四范式进行进一步修改，确保不存在多值依赖。这时，应根据反向工程的思路反馈给领域模型。如果表结
构中存在多值依赖，则证明领域模型中的对象具有至少两个以上的职责，应根据第一条进行设计修正。第四范式：一个表如果满足BCNF，不应存在多值依赖。 </p>
<p>(7)在经过分析后确认所有的表都满足二、三、四范式的情况下，表和表之间的关联尽量采用弱关联以便于对表字段和表结构的调整和重构。并且，我认为
数据库中的表是用来持久化一个对象实例在特定时间及特定条件下的状态的，只是一个存储介质，所以，表和表之间也不应用强关联来表述业务（数据间的一致
性），这一职责应由系统的逻辑层来保证，这种方式也确保了系统对于不正确数据（脏数据）的兼容性。当然，从整个系统的角度来说我们还是要尽最大努力确保系
统不会产生脏数据，单从另一个角度来说，脏数据的产生在一定程度上也是不可避免的，我们也要保证系统对这种情况的容错性。这是一个折中的方案。 </p>
<p>(8)应针对所有表的主键和外键建立索引，有针对性的（针对一些大数据量和常用检索方式）建立组合属性的索引，提高检索效率。虽然建立索引会消耗部
分系统资源，但比较起在检索时搜索整张表中的数据尤其时表中的数据量较大时所带来的性能影响，以及无索引时的排序操作所带来的性能影响，这种方式仍然是值
得提倡的。 </p>
<p>(9)尽量少采用存储过程，目前已经有很多技术可以替代存储过程的功能如&#8220;对象/关系映射&#8221;等，将数据一致性的保证放在数据库中，无论对于版本控
制、开发和部署、以及数据库的迁移都会带来很大的影响。但不可否认，存储过程具有性能上的优势，所以，当系统可使用的硬件不会得到提升而性能又是非常重要
的质量属性时，可经过平衡考虑选用存储过程。 </p>
<p>(10)当处理表间的关联约束所付出的代价（常常是使用性上的代价）超过了保证不会出现修改、删除、更改异常所付出的代价，并且数据冗余也不是主要
的问题时，表设计可以不符合四个范式。四个范式确保了不会出现异常，但也可能由此导致过于纯洁的设计，使得表结构难于使用，所以在设计时需要进行综合判
断，但首先确保符合四个范式，然后再进行精化修正是刚刚进入数据库设计领域时可以采用的最好办法。 </p>
<p>(11)设计出的表要具有较好的使用性，主要体现在查询时是否需要关联多张表且还需使用复杂的SQL技巧。 </p>
<p>(12)设计出的表要尽可能减少数据冗余，确保数据的准确性，有效的控制冗余有助于提高数据库的性能。 </p>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/ashutc/aggbug/349926.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ashutc/" target="_blank">西瓜</a> 2011-05-10 17:12 <a href="http://www.blogjava.net/ashutc/archive/2011/05/10/349926.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计范式</title><link>http://www.blogjava.net/ashutc/archive/2011/05/10/349910.html</link><dc:creator>西瓜</dc:creator><author>西瓜</author><pubDate>Tue, 10 May 2011 05:13:00 GMT</pubDate><guid>http://www.blogjava.net/ashutc/archive/2011/05/10/349910.html</guid><wfw:comment>http://www.blogjava.net/ashutc/comments/349910.html</wfw:comment><comments>http://www.blogjava.net/ashutc/archive/2011/05/10/349910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ashutc/comments/commentRss/349910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ashutc/services/trackbacks/349910.html</trackback:ping><description><![CDATA[<span style="color: red;">设计范式</span>（<span style="font-family: Verdana;"><span style="color: #800080;">范式</span>,
数据库设计范式,数据库的设计范式）是符合某一种级别的关系模式的集合。构造数据库必须遵循一定的规则。在关系数据库中，这种规则就是范式。关系数据库中
的关系必须满足一定的要求，即满足不同的范式。目前关系数据库有六种范式：第一范式（1NF）、第二范式（2NF）、第三范式（3NF）、第四范式
（4NF）、第五范式（5NF）和第六范式（6NF）。满足最低要求的范式是第一范式（1NF）。在第一范式的基础上进一步满足更多要求的称为第二范式
（2NF），其余范式以次类推。一般说来，数据库只需满足第三范式（3NF）就行了。下面我们举例介绍第一范式（1NF）、第二范式（2NF）和第三范式
（3NF）。
<p class="cnt"><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
在创建一个数据库的过程中，范化是将其转化为一些表的过程，这种方法可以使从数据库得到的结果更加明确。这样可能使数据库产生重复数据，从而导致创建多余
的表。范化是在识别数据库中的数据元素、关系，以及定义所需的表和各表中的项目这些初始工作之后的一个细化的过程。</span></p>
<p class="cnt"><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面是范化的一个例子
Customer Item purchased Purchase price Thomas Shirt $40 Maria Tennis
shoes $35 Evelyn Shirt $40 Pajaro Trousers $25 </span></p>
<p class="cnt"><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
如果上面这个表用于保存物品的价格，而你想要删除其中的一个顾客，这时你就必须同时删除一个价格。范化就是要解决这个问题，你可以将这个表化为两个表，一
个用于存储每个顾客和他所买物品的信息，另一个用于存储每件产品和其价格的信息，这样对其中一个表做添加或删除操作就不会影响另一个表。<br />
<br />
<strong><span style="text-decoration: underline;">关系数据库的几种设计范式介绍</span></strong></span></p>
<p><span style="font-family: Verdana;">
</span></p>
<p class="cnt"><br />
<strong>1 第一范式（1NF）</strong></p>
<p class="cnt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在任何一个关系数据库中，第一范式（1NF）是对关系模式的基本要求，不满足第一范式（1NF）的数据库就不是关系数据库。</p>
<p class="cnt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
所谓第一范式（1NF）是指数据库表的每一列都是不可分割的基本数据项，同一列中不能有多个值，即实体中的某个属性不能有多个值或者不能有重复的属性。如
果出现重复的属性，就可能需要定义一个新的实体，新的实体由重复的属性构成，新实体与原实体之间为一对多关系。在第一范式（1NF）中表的每一行只包含一
个实例的信息。例如，对于图3-2
中的员工信息表，不能将员工信息都放在一列中显示，也不能将其中的两列或多列在一列中显示；员工信息表的每一行只表示一个员工的信息，一个员工的信息在表
中只出现一次。简而言之，第一范式就是无重复的列。</p>
<p class="cnt"><strong>2 第二范式（2NF）</strong></p>
<p class="cnt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
第二范式（2NF）是在第一范式（1NF）的基础上建立起来的，即满足第二范式（2NF）必须先满足第一范式（1NF）。第二范式（2NF）要求数据库表
中的每个实例或行必须可以被惟一地区分。为实现区分通常需要为表加上一个列，以存储各个实例的惟一标识。如图3-2
员工信息表中加上了员工编号（emp_id）列，因为每个员工的员工编号是惟一的，因此每个员工可以被惟一区分。这个惟一属性列被称为主关键字或主键、主
码。</p>
<p class="cnt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
第二范式（2NF）要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性，如果存在，那么这个属性和主关键字的这一部
分应该分离出来形成一个新的实体，新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列，以存储各个实例的惟一标识。简而言之，第二范式
就是非主属性非部分依赖于主关键字。</p>
<p class="cnt"><strong>3 第三范式（3NF）</strong></p>
<p class="cnt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
满足第三范式（3NF）必须先满足第二范式（2NF）。简而言之，第三范式（3NF）要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。例
如，存在一个部门信息表，其中每个部门有部门编号（dept_id）、部门名称、部门简介等信息。那么在图3-2的员工信息表中列出部门编号后就不能再将
部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表，则根据第三范式（3NF）也应该构建它，否则就会有大量的数据冗余。简
而言之，第三范式就是属性不依赖于其它非主属性。 </p>
<p class="cnt"><span style="font-family: Verdana;"><strong><span style="text-decoration: underline;">数据库设计三大范式应用实例剖析</span></strong> </span></p>
<p class="cnt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
数据库的设计范式是数据库设计所需要满足的规范，满足这些规范的数据库是简洁的、结构明晰的，同时，不会发生插入（insert）、删除（delete）
和更新（update）操作异常。反之则是乱七八糟，不仅给数据库的编程人员制造麻烦，而且面目可憎，可能存储了大量不需要的冗余信息。 <br />
<br />
设计范式是不是很难懂呢？非也，大学教材上给我们一堆数学公式我们当然看不懂，也记不住。所以我们很多人就根本不按照范式来设计数据库。 <br />
<br />
实质上，设计范式用很形象、很简洁的话语就能说清楚，道明白。本文将对范式进行通俗地说明，并以笔者曾经设计的一个简单论坛的数据库为例来讲解怎样将这些范式应用于实际工程。 <br />
<br />
<strong>　　 范式说明 </strong><br />
<br />
第一范式（1NF）：数据库表中的字段都是单一属性的，不可再分。这个单一属性由基本类型构成，包括整型、实数、字符型、逻辑型、日期型等。 <br />
<br />
例如，如下的数据库表是符合第一范式的： <br />
<br />
</p>
<table style="height: 43px;" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td height="18">字段1 </td>
            <td>字段2 </td>
            <td>字段3 </td>
            <td>字段4 </td>
        </tr>
        <tr>
            <td height="23">　　 </td>
            <td>　　 </td>
            <td>　　 </td>
            <td>　　 </td>
        </tr>
    </tbody>
</table>
<br />
而这样的数据库表是不符合第一范式的： <br />
<br />
<table style="height: 25px;" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td>字段1 </td>
            <td>字段2 </td>
            <td colspan="2">字段3 </td>
            <td>字段4 </td>
        </tr>
        <tr>
            <td>　　 </td>
            <td>　　 </td>
            <td>字段3.1 </td>
            <td>字段3.2 </td>
            <td>　　 </td>
        </tr>
    </tbody>
</table>
<p class="main"><br />
很显然，在当前的任何关系数据库管理系统（DBMS）中，傻瓜也不可能做出不符合第一范式的数据库，因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此，你想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。 <br />
<br />
<strong>第二范式（2NF）：</strong>数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖（部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况），也即所有非关键字段都完全依赖于任意一组候选关键字。 <br />
<br />
假定选课关系表为SelectCourse(学号, 姓名, 年龄, 课程名称, 成绩, 学分)，关键字为组合关键字(学号, 课程名称)，因为存在如下决定关系： <br />
<br />
(学号, 课程名称) &#8594; (姓名, 年龄, 成绩, 学分) <br />
<br />
这个数据库表不满足第二范式，因为存在如下决定关系： <br />
<br />
(课程名称) &#8594; (学分) <br />
<br />
(学号) &#8594; (姓名, 年龄) <br />
<br />
即存在组合关键字中的字段决定非关键字的情况。 <br />
<br />
由于不符合2NF，这个选课关系表会存在如下问题： <br />
<br />
(1) 数据冗余： <br />
<br />
同一门课程由n个学生选修，"学分"就重复n-1次；同一个学生选修了m门课程，姓名和年龄就重复了m-1次。 <br />
<br />
(2) 更新异常： <br />
<br />
若调整了某门课程的学分，数据表中所有行的"学分"值都要更新，否则会出现同一门课程学分不同的情况。 <br />
<br />
(3) 插入异常： <br />
<br />
假设要开设一门新的课程，暂时还没有人选修。这样，由于还没有"学号"关键字，课程名称和学分也无法记录入数据库。 <br />
<br />
(4) 删除异常： <br />
<br />
假设一批学生已经完成课程的选修，这些选修记录就应该从数据库表中删除。但是，与此同时，课程名称和学分信息也被删除了。很显然，这也会导致插入异常。 <br />
<br />
把选课关系表SelectCourse改为如下三个表： <br />
<br />
学生：Student(学号, 姓名, 年龄)； <br />
<br />
课程：Course(课程名称, 学分)； <br />
<br />
选课关系：SelectCourse(学号, 课程名称, 成绩)。 <br />
<br />
这样的数据库表是符合第二范式的， 消除了数据冗余、更新异常、插入异常和删除异常。 <br />
<br />
另外，所有单关键字的数据库表都符合第二范式，因为不可能存在组合关键字。 <br />
<br />
<strong>第三范式（3NF）：</strong>在第二范式的基础上，数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖，指的是如果存在"A &#8594; B &#8594; C"的决定关系，则C传递函数依赖于A。因此，满足第三范式的数据库表应该不存在如下依赖关系： <br />
<br />
关键字段 &#8594; 非关键字段x &#8594; 非关键字段y <br />
<br />
假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话)，关键字为单一关键字"学号"，因为存在如下决定关系： <br />
<br />
(学号) &#8594; (姓名, 年龄, 所在学院, 学院地点, 学院电话) <br />
<br />
这个数据库是符合2NF的，但是不符合3NF，因为存在如下决定关系： <br />
<br />
(学号) &#8594; (所在学院) &#8594; (学院地点, 学院电话) <br />
<br />
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。 <br />
<br />
它也会存在数据冗余、更新异常、插入异常和删除异常的情况，读者可自行分析得知。 <br />
<br />
把学生关系表分为如下两个表： <br />
<br />
学生：(学号, 姓名, 年龄, 所在学院)； <br />
<br />
学院：(学院, 地点, 电话)。 <br />
<br />
这样的数据库表是符合第三范式的，消除了数据冗余、更新异常、插入异常和删除异常。 <br />
<br />
<strong>鲍依斯-科得范式（BCNF）：</strong>在第三范式的基础上，数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合第三范式。 <br />
<br />
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量)，且有一个管理员只在一个仓库工作；一个仓库可以存储多种物品。这个数据库表中存在如下决定关系： <br />
<br />
(仓库ID, 存储物品ID) &#8594;(管理员ID, 数量) <br />
<br />
(管理员ID, 存储物品ID) &#8594; (仓库ID, 数量) <br />
<br />
所以，(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字，表中的唯一非关键字段为数量，它是符合第三范式的。但是，由于存在如下决定关系： <br />
<br />
(仓库ID) &#8594; (管理员ID) <br />
<br />
(管理员ID) &#8594; (仓库ID) <br />
<br />
即存在关键字段决定关键字段的情况，所以其不符合BCNF范式。它会出现如下异常情况： <br />
<br />
(1) 删除异常： <br />
<br />
当仓库被清空后，所有"存储物品ID"和"数量"信息被删除的同时，"仓库ID"和"管理员ID"信息也被删除了。 <br />
<br />
(2) 插入异常： <br />
<br />
当仓库没有存储任何物品时，无法给仓库分配管理员。 <br />
<br />
(3) 更新异常： <br />
<br />
如果仓库换了管理员，则表中所有行的管理员ID都要修改。 <br />
<br />
把仓库管理关系表分解为二个关系表： <br />
<br />
仓库管理：StorehouseManage(仓库ID, 管理员ID)； <br />
<br />
仓库：Storehouse(仓库ID, 存储物品ID, 数量)。 <br />
<br />
这样的数据库表是符合BCNF范式的，消除了删除异常、插入异常和更新异常。 </p>
<p class="cnt"><strong>　　 范式应用 </strong><br />
<br />
我们来逐步搞定一个论坛的数据库，有如下信息： <br />
<br />
（1） 用户：用户名，email，主页，电话，联系地址 <br />
<br />
（2） 帖子：发帖标题，发帖内容，回复标题，回复内容 <br />
<br />
第一次我们将数据库设计为仅仅存在表：</p>
<p class="cnt">
</p>
<table style="height: 25px;" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td>用户名 </td>
            <td>email </td>
            <td>主页 </td>
            <td>电话 </td>
            <td>联系地址 </td>
            <td>发帖标题 </td>
            <td>发帖内容 </td>
            <td>回复标题 </td>
            <td>回复内容 </td>
        </tr>
    </tbody>
</table>
<br />
这个数据库表符合第一范式，但是没有任何一组候选关键字能决定数据库表的整行，唯一的关键字段用户名也不能完全决定整个元组。我们需要增加"发帖ID"、"回复ID"字段，即将表修改为： <br />
<br />
<table style="height: 25px;" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td>用户名 </td>
            <td>email </td>
            <td>主页 </td>
            <td>电话 </td>
            <td>联系地址 </td>
            <td>发帖ID </td>
            <td>发帖标题 </td>
            <td>发帖内容 </td>
            <td>回复ID </td>
            <td>回复标题 </td>
            <td>回复内容 </td>
        </tr>
    </tbody>
</table>
<br />
这样数据表中的关键字(用户名，发帖ID，回复ID)能决定整行： <br />
<br />
(用户名,发帖ID,回复ID) &#8594; (email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容) <br />
<br />
但是，这样的设计不符合第二范式，因为存在如下决定关系： <br />
<br />
(用户名) &#8594; (email,主页,电话,联系地址) <br />
<br />
(发帖ID) &#8594; (发帖标题,发帖内容) <br />
<br />
(回复ID) &#8594; (回复标题,回复内容) <br />
<br />
即非关键字段部分函数依赖于候选关键字段，很明显，这个设计会导致大量的数据冗余和操作异常。 <br />
<br />
我们将数据库表分解为（带下划线的为关键字）： <br />
<br />
（1） 用户信息：用户名，email，主页，电话，联系地址 <br />
<br />
（2） 帖子信息：发帖ID，标题，内容 <br />
<br />
（3） 回复信息：回复ID，标题，内容 <br />
<br />
（4） 发贴：用户名，发帖ID <br />
<br />
（5） 回复：发帖ID，回复ID <br />
<br />
这样的设计是满足第1、2、3范式和BCNF范式要求的，但是这样的设计是不是最好的呢？ <br />
<br />
不一定。 <br />
<br />
观察可知，第4项"发帖"中的"用户名"和"发帖ID"之间是1：N的关系，因此我们可以把"发帖"合并到第2项的"帖子信息"中；第5项"回复"中的"
发帖ID"和"回复ID"之间也是1：N的关系，因此我们可以把"回复"合并到第3项的"回复信息"中。这样可以一定量地减少数据冗余，新的设计为： <br />
<br />
（1） 用户信息：用户名，email，主页，电话，联系地址 <br />
<br />
（2） 帖子信息：用户名，发帖ID，标题，内容 <br />
<br />
（3） 回复信息：发帖ID，回复ID，标题，内容 <br />
<br />
数据库表1显然满足所有范式的要求； <br />
<br />
数据库表2中存在非关键字段"标题"、"内容"对关键字段"发帖ID"的部分函数依赖，即不满足第二范式的要求，但是这一设计并不会导致数据冗余和操作异常； <br />
<br />
数据库表3中也存在非关键字段"标题"、"内容"对关键字段"回复ID"的部分函数依赖，也不满足第二范式的要求，但是与数据库表2相似，这一设计也不会导致数据冗余和操作异常。 <br />
<br />
由此可以看出，并不一定要强行满足范式的要求，对于1：N关系，当1的一边合并到N的那边后，N的那边就不再满足第二范式了，但是这种设计反而比较好！ <br />
<br />
对于M：N的关系，不能将M一边或N一边合并到另一边去，这样会导致不符合范式要求，同时导致操作异常和数据冗余。 <br />
对于1：1的关系，我们可以将左边的1或者右边的1合并到另一边去，设计导致不符合范式要求，但是并不会导致操作异常和数据冗余。 <br />
<br />
<strong>　　 结论 </strong><br />
<br />
满足范式要求的数据库设计是结构清晰的，同时可避免数据冗余和操作异常。这并意味着不符合范式要求的设计一定是错误的，在数据库表中存在1：1或1：N关系这种较特殊的情况下，合并导致的不符合范式要求反而是合理的。 <br />
<br />
在我们设计数据库的时候，一定要时刻考虑范式的要求。</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/ashutc/aggbug/349910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ashutc/" target="_blank">西瓜</a> 2011-05-10 13:13 <a href="http://www.blogjava.net/ashutc/archive/2011/05/10/349910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计</title><link>http://www.blogjava.net/ashutc/archive/2011/05/09/349855.html</link><dc:creator>西瓜</dc:creator><author>西瓜</author><pubDate>Mon, 09 May 2011 09:13:00 GMT</pubDate><guid>http://www.blogjava.net/ashutc/archive/2011/05/09/349855.html</guid><wfw:comment>http://www.blogjava.net/ashutc/comments/349855.html</wfw:comment><comments>http://www.blogjava.net/ashutc/archive/2011/05/09/349855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ashutc/comments/commentRss/349855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ashutc/services/trackbacks/349855.html</trackback:ping><description><![CDATA[<br />
<br />
<ol class="article">
    <li>原始单据与实体之间的关系</li>
    <p class="contentNew">可以是一对一、一对多、多对多的关系。在一般情况下，它们是一对一的关系：即一张原始单据对应且只
    对应一个实体。在特殊情况下，它们可能是一对多或多对一的关系，即一张原始单证对应多个实体，或多张原始单证对应一个实体。这里的实体可以理解为基本表。
    明确这种对应关系后，对我们设计录入界面大有好处。</p>
    <p class="contentNew">比如：一份员工履历资料，在人力资源信息系统中，就对应三个基本表：员工基本情况表、社会关系表、工作简历表。这就是&#8220;一张原始单证对应多个实体&#8221;的典型例子。</p>
    <li>主键与外键</li>
    <p class="contentNew">一般而言，一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体,
    可以定义主键，也可以不定义主键（因为它无子孙）, 但必须要有外键（因为它有父亲）。
    主键与外键的设计，在全局数据库的设计中，占有重要地位。当全局数据库的设计完成以后，有个美国数据库设计专家说：&#8220;键，到处都是键，除了键之外，什么也
    没有&#8221;，这就是他的数据库设计经验之谈，也反映了他对信息系统核心（数据模型）的高度抽象思想。因为：主键是实体的高度抽象，主键与外键的配对，表示实体
    之间的连接。</p>
    <li>基本表的性质</li>
    <p class="contentNew">基本表与中间表、临时表不同，因为它具有如下四个特性：</p>
    <ul class="article">
        <li>原子性。基本表中的字段是不可再分解的。</li>
        <li>原始性。基本表中的记录是原始数据（基础数据）的记录。</li>
        <li>演绎性。由基本表与代码表中的数据，可以派生出所有的输出数据。</li>
        <li>稳定性。基本表的结构是相对稳定的，表中的记录是要长期保存的。</li>
    </ul>
    <p class="contentNew">理解基本表的性质后，在设计数据库时，就能将基本表与中间表、临时表区分开来。</p>
    <li>范式标准</li>
    <p class="contentNew">基本表及其字段之间的关系, 应尽量满足第三范式。但是，满足第三范式的数据库设计，往往不是最好的设计。为了提高数据库的运行效率，常常需要降低范式标准：适当增加冗余，达到以空间换时间的目的。</p>
    <p class="contentNew">比如有一张存放商品的基本表，如表1所示。&#8220;金额&#8221;这个字段的存在，表明该表的设计不满足第三范式，因为&#8220;金额&#8221;可以由&#8220;单价&#8221;乘以&#8220;数量&#8221;得到，说明&#8220;金额&#8221;是冗余字段。但是，增加&#8220;金额&#8221;这个冗余字段，可以提高查询统计的速度，这就是以空间换时间的作法。</p>
    <p class="contentNew">在Rose 2002中，规定列有两种类型：数据列和计算列。&#8220;金额&#8221;这样的列被称为&#8220;计算列&#8221;，而&#8220;单价&#8221;和&#8220;数量&#8221;这样的列被称为&#8220;数据列&#8221;。</p>
    <table style="line-height: 150%;" align="center" border="1" cellspacing="0" width="600">
        <tbody>
            <tr>
                <td>商品名称</td>
                <td>商品型号</td>
                <td>单价</td>
                <td>数量</td>
                <td>金额</td>
            </tr>
            <tr>
                <td>电视机</td>
                <td>29吋</td>
                <td>2,500</td>
                <td>40</td>
                <td>100,000</td>
            </tr>
        </tbody>
    </table>
    <p align="center">表1 商品表的表结构</p>
    <li>通俗地理解三个范式</li>
    <p class="contentNew">通俗地理解三个范式，对于数据库设计大有好处。在数据库设计中，为了更好地应用三个范式，就必须通俗地理解三个范式（通俗地理解是够用的理解，并不是最科学最准确的理解）：</p>
    <ul class="article">
        <li>第一范式：1NF是对属性的原子性约束，要求属性具有原子性，不可再分解；</li>
        <li>第二范式：2NF是对记录的惟一性约束，要求记录有惟一标识，即实体的惟一性；</li>
        <li>第三范式：3NF是对字段冗余性的约束，即任何字段不能由其他字段派生出来，它要求字段没有冗余。</li>
    </ul>
    <p class="contentNew">没有冗余的数据库设计可以做到。但是，没有冗余的数据库未必是最好的数据库，有时为了提高运行效率，就必须降低范式标准，适当保留冗余数据。具体做法是：在概念数据模型设计时遵守第三范式，降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段，允许冗余。</p>
    <li>要善于识别与正确处理多对多的关系</li>
    <p class="contentNew">若两个实体之间存在多对多的关系，则应消除这种关系。消除的办法是，在两者之间增加第三个实体。这
    样，原来一个多对多的关系，现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个实体，实质上是一个较复杂的关系，
    它对应一张基本表。一般来讲，数据库设计工具不能识别多对多的关系，但能处理多对多的关系。</p>
    <p class="contentNew">比如在&#8220;图书馆信息系统&#8221;中，&#8220;图书&#8221;是一个实体，&#8220;读者&#8221;也是一个实体。这两个实体之间的关系，
    是一个典型的多对多关系：一本图书在不同时间可以被多个读者借阅，一个读者又可以借多本图书。为此，要在二者之间增加第三个实体，该实体取名为&#8220;借还
    书&#8221;，它的属性为：借还时间、借还标志（0表示借书，1表示还书），另外，它还应该有两个外键（&#8220;图书&#8221;的主键，&#8220;读者&#8221;的主键），使它能与&#8220;图书&#8221;和
    &#8220;读者&#8221;连接。</p>
    <li>主键PK的取值方法</li>
    <p class="contentNew">PK是供程序员使用的表间连接工具，可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时，建议字段的个数不要太多，多了不但索引占用空间大，而且速度也慢。</p>
    <li>正确认识数据冗余</li>
    <p class="contentNew">主键与外键在多表中的重复出现，不属于数据冗余，这个概念必须清楚，事实上有许多人还不清楚。非键字段的重复出现，才是数据冗余！而且是一种低级冗余，即重复性的冗余。高级冗余不是字段的重复出现，而是字段的派生出现。</p>
    <p class="contentNew">比如商品中的&#8220;单价、数量、金额&#8221;三个字段，&#8220;金额&#8221;就是由&#8220;单价&#8221;乘以&#8220;数量&#8221;派生出来的，它就
    是冗余，而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性，因为同一数据，可能从不同时间、地点、角色上多次录
    入。因此，我们提倡高级冗余（派生性冗余），反对低级冗余（重复性冗余）。</p>
    <li>E-R图没有标准答案</li>
    <p class="contentNew">信息系统的E-R图没有标准答案，因为它的设计与画法不是惟一的，只要它覆盖了系统需求的业务范围
    和功能内容，就是可行的。反之要修改E-R图。尽管它没有惟一的标准答案，并不意味着可以随意设计。好的E—R图的标准是：结构清晰、关联简洁、实体个数
    适中、属性分配合理、没有低级冗余。</p>
    <li>视图技术在数据库设计中很有用</li>
    <p class="contentNew">与基本表、代码表、中间表不同，视图是一种虚表，它依赖数据源的实表而存在。视图是供程序员使用数
    据库的一个窗口，是基表数据综合的一种形式, 是数据处理的一种方法，是用户数据保密的一种手段。为了进行复杂处理、提高运算速度和节省存储空间,
    视图的定义深度一般不得超过三层。 若三层视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义,
    视图的深度就不受限制了。</p>
    <p class="contentNew">对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统，视图的作用更加重要。这些系统的
    基本表完成物理设计之后，立即在基本表上建立第一层视图，这层视图的个数和结构，与基本表的个数和结构是完全相同。并且规定，所有的程序员，一律只准在视
    图上操作。只有数据库管理员，带着多个人员共同掌握的&#8220;安全钥匙&#8221;，才能直接在基本表上操作。请读者想想：这是为什么？</p>
    <li>中间表、报表和临时表</li>
    <p class="contentNew">中间表是存放统计数据的表，它是为数据仓库、输出报表或查询结果而设计的，有时它没有主键与外键（数据仓库除外）。临时表是程序员个人设计的，存放临时记录，为个人所用。基表和中间表由DBA维护，临时表由程序员自己用程序自动维护。</p>
    <li>完整性约束表现在三个方面</li>
    <p class="contentNew">域的完整性：用Check来实现约束，在数据库设计工具中，对字段的取值范围进行定义时，有一个Check按钮，通过它定义字段的值城。</p>
    <p class="contentNew">参照完整性：用PK、FK、表级触发器来实现。</p>
    <p class="contentNew">用户定义完整性：它是一些业务规则，用存储过程和触发器来实现。</p>
    <li>防止数据库设计打补丁的方法是&#8220;三少原则&#8221;</li>
    <ul class="article">
        <li>一个数据库中表的个数越少越好。只有表的个数少了，才能说明系统的E--R图少而精，去掉了重复的多余的实体，形成了对客观世界的高度抽象，进行了系统的数据集成，防止了打补丁式的设计；</li>
        <li>一个表中组合主键的字段个数越少越好。因为主键的作用，一是建主键索引，二是做为子表的外键，所以组合主键的字段个数少了，不仅节省了运行时间，而且节省了索引存储空间；</li>
        <li>一个表中的字段个数越少越好。只有字段的个数少了，才能说明在系统中不存在数据重复，且很少有数据冗余，更重要的是督促
        读者学会&#8220;列变行&#8221;，这样就防止了将子表中的字段拉入到主表中去，在主表中留下许多空余的字段。所谓&#8220;列变行&#8221;，就是将主表中的一部分内容拉出去，另外单
        独建一个子表。这个方法很简单，有的人就是不习惯、不采纳、不执行。</li>
    </ul>
    <p class="contentNew">数据库设计的实用原则是：在数据冗余和处理速度之间找到合适的平衡点。&#8220;三少&#8221;是一个整体概念，综
    合观点，不能孤立某一个原则。该原则是相对的，不是绝对的。&#8220;三多&#8221;原则肯定是错误的。试想：若覆盖系统同样的功能，一百个实体（共一千个属性）
    的E-R图，肯定比二百个实体（共二千个属性） 的E--R图，要好得多。</p>
    <p class="contentNew">提倡&#8220;三少&#8221;原则，是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系
    统集成为应用数据库，将应用数据库集成为主题数据库，将主题数据库集成为全局综合数据库。集成的程度越高，数据共享性就越强，信息孤岛现象就越少，整个企
    业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。</p>
    <p class="contentNew">提倡&#8220;三少&#8221;原则的目的，是防止读者利用打补丁技术，不断地对数据库进行增删改，使企业数据库变成了随意设计数据库表的&#8220;垃圾堆&#8221;，或数据库表的&#8220;大杂院&#8221;，最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章，不计其数，导致企事业单位的信息系统无法维护而瘫痪。</p>
    <p class="contentNew">&#8220;三多&#8221;原则任何人都可以做到，该原则是&#8220;打补丁方法&#8221;设计数据库的歪理学说。&#8220;三少&#8221;原则是少而精的原则，它要求有较高的数据库设计技巧与艺术，不是任何人都能做到的，因为该原则是杜绝用&#8220;打补丁方法&#8221;设计数据库的理论依据。</p>
    <li>提高数据库运行效率的办法</li>
    <p class="contentNew">在给定的系统硬件和系统软件条件下，提高数据库系统的运行效率的办法是：</p>
    <ul class="article">
        <li>在数据库物理设计时，降低范式，增加冗余，少用触发器, 多用存储过程。</li>
        <li>当计算非常复杂、而且记录条数非常巨大时（例如一千万条），复杂计算要先在数据库外面，以文件系统方式用C++语言计算处理完成之后，最后才入库追加到表中去。这是电信计费系统设计的经验。</li>
        <li>发现某个表的记录太多，例如超过一千万条，则要对该表进行水平分割。水平分割的做法是，以该表主键PK的某个值为界线，将该表的记录水平分割为两个表。若发现某个表的字段太多，例如超过八十个，则垂直分割该表，将原来的一个表分解为两个表。</li>
        <li>对数据库管理系统DBMS进行系统优化，即优化各种系统参数，如缓冲区个数。</li>
        <li>在使用面向数据的SQL语言进行程序设计时，尽量采取优化算法。</li>
    </ul>
    <p class="contentNew">总之，要提高数据库的运行效率，必须从数据库系统级优化、数据库设计级优化、程序实现级优化，这三个层次上同时下功夫。</p>
</ol>
<p class="contentNew">上述十四个技巧，是许多人在大量的数据库分析与设计实践中，逐步总结出来的。对于这些经验的运用，读者不能生帮硬套，死记硬背，而要消化理解，实事求是，灵活掌握。并逐步做到：在应用中发展，在发展中应用。 </p>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/ashutc/aggbug/349855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ashutc/" target="_blank">西瓜</a> 2011-05-09 17:13 <a href="http://www.blogjava.net/ashutc/archive/2011/05/09/349855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>