数据库中主键和外键的设计原则/数据库事务的四种特性oracle

来源:互联网 发布:重启网络命令 编辑:程序博客网 时间:2024/05/17 04:27

数据库中主键和外键的设计原则

主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。主键和外键的设计对物理数据库的性能和可用性都有着决定性的影响。
必须将数据库模式从理论上的逻辑设计转换为实际的物理设计。而主键和外键的结构是这个设计过程的症结所在。一旦将所设计的数据库用于了生产环境,就很难对这些键进行修改,所以在开发阶段就设计好主键和外键就是非常必要和值得的。
主键:
  关系数据库依赖于主键---它是数据库物理模式的基石。主键在物理层面上只有两个用途:
        1. 惟一地标识一行。
 
        2. 作为一个可以被外键有效引用的对象。 http://www.mscto.com
  基于以上这两个用途,下面给出了我在设计物理层面的主键时所遵循的一些原则:
 
        1. 主键应当是对用户没有意义的。如果用户看到了一个表示多对多关系的连接表中的数据,并抱怨它没有什么用处,那就证明它的主键设计地很好。
        2. 主键应该是单列的,以便提高连接和筛选操作的效率。
软件开发网
 
       注:使用复合键的人通常有两个理由为自己开脱,而这两个理由都是错误的。其一是主键应当具有实际意义,然而,让主键具有意义只不过是给人为地破坏数据库提供了方便。其二是利用这种方法可以在描述多对多关系的连接表中使用两个外部键来作为主键,我也反对这种做法,理由是:复合主键常常导致不良的外键,即当连接表成为另一个从表的主表,而依据上面的第二种方法成为这个表主键的一部分,然,这个表又有可能再成为其它从表的主表,其主键又有可能成了其它从表主键的一部分,如此传递下去,越靠后的从表,其主键将会包含越多的列了。
 
        3. 永远也不要更新主键。实际上,因为主键除了惟一地标识一行之外,再没有其他的用途了,所以也就没有理由去对它更新。如果主键需要更新,则说明主键应对用户无意义的原则被违反了。
       注:这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。
        4. 主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。
        5. 主键应当有计算机自动生成。如果由人来对主键的创建进行干预,就会使它带有除了惟一标识一行以外的意义。一旦越过这个界限,就可能产生认为修改主键的动机,这样,这种系统用来链接记录行、管理记录行的关键手段就会落入不了解数据库设计的人的手中。
我认为主键可以分为两种,一种是无意义的主键,例如News表中的NewsID主键,目的只是为了唯一标识一条记录,如果数据表中去掉这个主键字段,该表中的信息也是完整的,也就是说该字段对用户是透明的,用户理不理解都无所谓;一种是有意义的主键,比如Orders表中的OrderNO主键,这个表是离不开OrderNO这个字段的,这个字段已经成为业务实体的一部分了,这在做系统分析的时候就已经确定了,它对用户来说是可理解的,甚至是需要记忆的。 

  有意义的主键是需要自己写程序或者建立专门的数据表来生成的,而且生成的规则也是在系统分析的时候就确定好的;对于无意义的主键则根本没有这个必要,下面我列出了一个流程步骤来说明怎样给数据表分配一个主键: 

  1、数据表一定要有主键,该主键可以是一个或者多个呵呵,废话一句 

  2、数据表的主键选择首先在该数据表自有的字段中找,依据是该字段或者字段组合可以唯一的标识一条记录,好像也是废话 

  3、如果在自有字段中实在找不到可以唯一标识一条记录的字段或者字段组合(例如News表)时,需要给表增加一个主键字段,这个增加的主键是无意义的。 

  4、如果找到一个字段可以唯一的标识一条记录,则该表的主键则为这个字段(例如Orders表),这个主键就是有意义的 

  5、如果找到一个字段组合可以唯一的标识一条记录,则分为以下两种情况 

  6、如果该数据表不需要与其他的表进行数据主-外键关联,则该表的主键则为这个字段组合,这个字段组合的主键也是有意义的 

  7、如果该数据表表需要与其它表产生主-外键关联,这时候也要增加一个主键字段,而把找到的那个字段组合作成唯一索引,原因是多字段主键没法与其它表建立数据关联,这个增加的主键是无意义的。 

  8、无意义的主键类型在自增的int与guid中选择,选择的依据是是否该数据现在或者以后需要进行表分布,需要分布就选择guid,否则就选择自增int,原因是自增的int没法进行表分布

数据库事务的四种特性

概念

事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

特性

  事务是恢复和并发控制的基本单位。

  事务应该具有4个属性:原子性、一致性、隔离性、持续性。这四个属性通常称为ACID特性。

  原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。

  一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

  隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

  持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

一般的数据库都事务都会满足这四个特点,也有不满足的。

oracle分页查询的实现

oracle分页查询主要是用来解决数据表中数据量太大时,资源不够引起的问题。试想如果硬件资源足够多的话,编程是不会考虑硬件的,愿意怎么实现就怎么实现,一次性读出数据来难道不是最简单的办法?然后现实确不允许我们这么做,因为你这么做了程序会报内存溢出的出错,最后还是我们的责任。所以必须得分页。

来不及整理,转一篇文章当做笔记:

分页查询格式:

[sql] view plain copy
 print?
  1. SELECT * FROM   
  2. (  
  3. SELECT A.*, ROWNUM RN   
  4. FROM (SELECT * FROM TABLE_NAME) A   
  5. WHERE ROWNUM <= 40  
  6. )  
  7. WHERE RN >= 21  

其中最内层的查询SELECT * FROM TABLE_NAME表示不进行翻页的原始查询语句。ROWNUM <= 40和RN >= 21控制分页查询的每页的范围。

上面给出的这个分页查询语句,在大多数情况拥有较高的效率。分页的目的就是控制输出结果集大小,将结果尽快的返回。在上面的分页查询语句中,这种考虑主要体现在WHERE ROWNUM <= 40这句上。

选择第21到40条记录存在两种方法,一种是上面例子中展示的在查询的第二层通过ROWNUM <= 40来控制最大值,在查询的最外层控制最小值。而另一种方式是去掉查询第二层的WHERE ROWNUM <= 40语句,在查询的最外层控制分页的最小值和最大值。这是,查询语句如下:

[sql] view plain copy
 print?
  1. SELECT * FROM   
  2. (  
  3. SELECT A.*, ROWNUM RN   
  4. FROM (SELECT * FROM TABLE_NAME) A   
  5. )  
  6. WHERE RN BETWEEN 21 AND 40  

对比这两种写法,绝大多数的情况下,第一个查询的效率比第二个高得多。

这是由于CBO优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第一个查询语句,第二层的查询条件WHERE ROWNUM <= 40就可以被Oracle推入到内层查询中,这样Oracle查询的结果一旦超过了ROWNUM限制条件,就终止查询将结果返回了。

而第二个查询语句,由于查询条件BETWEEN 21 AND 40是存在于查询的第三层,而Oracle无法将第三层的查询条件推到最内层(即使推到最内层也没有意义,因为最内层查询不知道RN代表什么)。因此,对于第二个查询语句,Oracle最内层返回给中间层的是所有满足条件的数据,而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成,显然这个效率要比第一个查询低得多。






0 0