打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
关系数据库中的“键”
关系数据库中的“键”

主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。主键和外键的设计对物理数据库的性能和可用性都有着决定性的影响。

必须将数据库模式从理论上的逻辑设计转换为实际的物理设计。而主键和外键的结构是这个设计过程的症结所在。一旦将所设计的数据库用于了生产环境,就很难对这些键进行修改,所以在开发阶段就设计好主键和外键就是非常必要和值得的。

首先来谈:主键。

关系数据库依赖于主键---它是数据库物理模式的基石。主键在物理层面上只有两个用途:
        1. 惟一地标识一行。
        2. 作为一个可以被外键有效引用的对象。

基于以上这两个用途,下面给出了我在设计物理层面的主键时所遵循的一些原则:

        1. 主键应当是对用户没有意义的。如果用户看到了一个表示多对多关系的连接表中的数据,并抱怨它没有什么用处,那就证明它的主键设计地很好。
        2. 主键应该是单列的,以便提高连接和筛选操作的效率。

             注:使用复合键的人通常有两个理由为自己开脱,而这两个理由都是错误的。其一是主键应当具有实际意义,然而,让主键具有意义只不过是给人为地破坏数据库提供了方便。其二是利用这种方法可以在描述多对多关系的连接表中使用两个外部键来作为主键,我也反对这种做法,理由是:复合主键常常导致不良的外键,即当连接表成为另一个从表的主表,而依据上面的第二种方法成为这个表主键的一部分,然,这个表又有可能再成为其它从表的主表,其主键又有可能成了其它从表主键的一部分,如此传递下去,越靠后的从表,其主键将会包含越多的列了。

        3. 永远也不要更新主键。实际上,因为主键除了惟一地标识一行之外,再没有其他的用途了,所以也就没有理由去对它更新。如果主键需要更新,则说明主键应对用户无意义的原则被违反了。

              注:这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。

        4. 主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。

        5. 主键应当有计算机自动生成。如果由人来对主键的创建进行干预,就会使它带有除了惟一标识一行以外的意义。一旦越过这个界限,就可能产生认为修改主键的动机,这样,这种系统用来链接记录行、管理记录行的关键手段就会落入不了解数据库设计的人的手中。

----------------------------------------------------------------------

 详谈关系数据库中的“键”(续1)

      (1)天然主键
               在现实生活中存在着许多看起来可以惟一地标识一行记录的值,如:身份证号码、汽车牌照号码等。数据库逻辑模式设计往往会使用这些天然的主键,尽管这些天然主键中没有哪一个是十分可靠的。
                可以让用户把它们当作查找和命名一行记录的“主键”,但绝不能把它们作为实际的主键。
                如果必须使用一个天然主键,则必须保证对于每一个引用了这个天然主键的外键都启用了级联更新选项,这样在更新主键时就不会破坏参照完整性了。
     (2)SQL Server的主键约束
                 SQL Server使用约束来维护主键和外键。约束的用途在于:确保新数据满足指定的要求,否则将拒绝相应的数据修改操作。
                 主键约束实际上是通过Unique约束(不是空置约束)以及聚集或者非聚集惟一索引来实现的。
                      注:主键应当是没有实际意义的、单列的、计算机生成的、不可编辑的,而且对于用户来说应当是不可见的。另外,防止用户查看和操作键是一个成功的数库开发人员所要达到的主要目标之一。
        企业管理器使用聚集索引创建主键,这种实现方法并不好。如果要使用企业管理器这个图形工具来创建物理模式,应当手工将主键索引重新设置为非聚集索引。在代码中,可以使用以下两种方式之一把某个(某些)列设置为主键:
  CREATE TABLE dbo.Guide (
     GuideID INT IDENTITY NOT NULL PRIMARY KEY NONCLUSTERED ,
     ... ...
 或者
     ALTER TABLE dbo.Guide ADD CONSTRAINT
           PK_Guide PRIMARY KEY NONCLUSTERED (GuideID)
           ... ...
      有两种类型最适合于做主键:标识列(IDNETITY)和全局惟一标识符列(GUID)。
       A. 使用IDENTITY。
            到目前为止,大多数广为使用的主键创建方法都与标识列的使用有关。当新的记录行插入到数据库中时,标识列都会为它们生成连续的整数。你还可以任意的设定标识列的种子值和增量值。
            标识列具有以下的优点:
                  a. 整数比GUID更容易人工识别和编辑。
                  b. 整数比GUID占用空间小而且快。当然,这样的性能差别只有当你循环执行数千个select语句才能显现出来。
            标识列的值是在插入新的记录行时由SQL Server创建的。除非将set identity_insert选项设置为true,否则,试图在标识列中插入数据或者更新标识列中的数据都会产生错误。
       B. 使用GUID。
            SQL Server的uniqueidentifier数据类型与COM的全局惟一标识符相对应。虽然标识列和GUID都是惟一的,但与标识列相比,GUID可以在更大范围内保证唯一性。它具有如下优点:
            a. 复制使用GUID主键的数据库时,不必额外作全面的检查。
            b. GUID值的随机性可以减少数据库的热点。
            c. GUID可以避免用户使用具有实际意义的主键,或者为主键赋予实际的意义。
            d. GUID可以避免这样的连接错误,即:查询时连接了错误的表,但系统依旧返回了结果。因为如果使用了GUID,这些表的记录行在键所对应的那些列上是不可能取同样的整数值的。
            e. GUID的值是用不完的。
            f. 可以使用多种方法来生成GUID的值,包括:使用列的默认值、select语句的表达式或者select语句之前的代码,因此,使用GUID编程要容易的多。此外,使用GUID可以避免使用标识列时会出现的数据修改问题。
      在下面的脚本中,将PorductID列的数据类型设置为uniqueidentitfier,并指定它不能够取空值。该列的rowguidcol属性被设置为true,这使得复制程序能够检测并使用它。它的默认值是新生成的uniqueidentifier。Product表将它作为主键,它使用了非聚集的惟一索引。
 CREATE TABLE dbo.Product (
    ProductID UNIQUEIDENTIFIER NOT NULL
          ROWGUIDCOL  DEFAULT (NEWID())
          PRIMARY KEY NONCLUSTERED,
          ... ...
 
---------------------------------------------------------------------

详谈关系数据库中的“键”(续)

 今天我们来讨论外键。
   从表通过指向主表的外键来与主表相关联。人们常犯的一种错误是:认为参照完整性是对于主键的约束。但实际上,参照完整性要求的是外键值必须引用有效的主键值,所以这项约束是对于外键的约束,而不是对于主键的约束。
在T-SQL脚本中,可以使用两种方法来声明完整性约束:既可以在创建表的代码中声明完整性约束,也可以在创建表之后再创建约束。其声明的格式如下:
  ForeignKeyColumn FOREIGN KEY REFERENCES PrimaryTable(PKID)
      可选的外键与强制的外键之间存在着很大的区别。一些关系的外键必须具有值,但对于其他一些关系就不必如此,无论外键有值或者没有值,其数据都是有效的。在物理层,这种差别是通过外键列能否为空体现出来的。如果外键是强制的,那么外键列就不能允许输入空值。相反,可选的外键,在相应的列上允许输入空值。对于具有复杂的可选性的关系,将需要通过Check约束或者触发器来全面地维护这种关系。
       由参照完整性所带来的一种复杂性是:如果从表中的记录引用了主表中的一行记录,那么RI(Referential Integrity)将阻止对这一行记录进行删除操作,除非从表中引用了它的记录都被删除了。否则,如果删除了主表中的这一行记录,而从表中的那些记录行仍旧指向这个刚被删除的记录的主键值,参照完整性就被破坏了。
       解决这个问题的一种方法就是做级联删除操作。它将把主表中的记录及其相关的从表中的记录一起删除,删除的顺序是:首先删除从表中的相关记录,然后再删除主表中的记录,因此它能够维护参照完整性。在T-SQL代码中启用级联删除选项的方法如下:
    FOREIGN KEY REFERENCES dbo.[TABLENAME] ON DELETE CASCADE
       在确定对于某个外键是否要采用级联删除选项时,可以使用以下由实践中总结出来的原则:
        1. 如果从表中的数据必须与主表中的数据结合在一起才有意义,一旦脱离了主表中的数据便毫无意义,那么应当使用级联删除。
        2. 如果从表中的数据具有它自己的含义,那么就不应该使用级联删除。
        3. 如果外键是可选的,那么永远也不要使用级联删除。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
数据库(表结构)设计技巧及注意事项
大数据量高并发访问数据库结构的设计
数据库设计的黄金经验(转)
数据库设计规范
利用Oracle数据库表完整性功能提高数据输入准确率
Mysql数据库外键基础知识和操作
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服