sqlserver主键设计的注意点

在设计主键的时候往往需要考虑以下几点:

1.无意义性:此处无意义是从用户的角度来定义的。这种无意义在一定程度上也会减少数据库的信息冗余。常常有人称呼主键为内部标识,为什么会这样称呼,原因之一在于“内部”,所谓内部从某种程度上来说就是指表记录,从大的范围来说就是数据库,如果你在设计的时候选择了对用户来说有意义的信息来作为主键,那么迟早会面对用户提出对这块信息进行更新的需求,那么你就违背了它应有的静态。

2.静态性:主键除了唯一地标识一条记录及外键的关联外,应不再考虑其他的意义,最理想的状态就是在产生后不再变动,所以在主键值产生后应考虑不对他进行更新等操作。如果进行了更新操作那么至少说明这块信息对于用户来说是有一定的意义,那么你就违背了应有的无意义性。(对数据进行整合等操作时可能需要对主键进行处理,这样做是为了保证数据库的完整性——记录的唯一,不在此考虑范围之内。)
无意义性往往可以决定其静态性。

3.简短性:既包含主键组成字段数量要少,还包含主键中单个字段存储类型简短,一般采用整形;对于前者主要考虑的是外键关联的因素;对于后者主要考虑的是性能。主键的简短对表的关联便捷性及检索的性能有极大的帮助。

看看下面具有缺陷的“主生产计划表”主键设计方案(MsSQL):


代码如下:

--主表
CREATE TABLE PP_MPSHeader(
  BillNo VARCHAR(20) NOT NULL PRIMARY KEY,
  PlanDate DATETIME NOT NULL
)
--从表
CREATE TABLE PP_MPSBody(
  BillNo VARCHAR(20) NOT NULL,
  LineNumber SMALLINT NOT NULL,
  ProductID INT NOT NULL,
  ProductQty DECIMAL(18,2) NOT NULL,
PRIMARY KEY(BillNo,LineNumber)
)
--设置外键
ALTER TABLE PP_MPSBody
ADD CONSTRAINT FK_PP_MPSHeader_MPSBody FOREIGN KEY(BillNo) REFERENCES PP_MPSHeader(BillNo)

这是典型的主从表结构。主表记录什么时候下达哪个单号的主计划,从表记录的是此计划生产哪些产品各多少数量,通过BillNo进行关联。当用户在下达一份主生产计划后,很可能会发现由于粗心大意输错了BillNo中计划单号信息,那么在他修改单号时,代码编写者需要在代码中控制从表的单号跟随主表的单号进行变动,否则单据将在外键的约束下无法保存,如果没有外键的约束,那么数据将失去其完整性。

如果按照上面的3个注意点,解决方案如下(MsSQL):


代码如下:

--主表
CREATE TABLE PP_MPSHeader(
  BillId INT PRIMARY KEY,
  BillNo VARCHAR(20) NOT NULL,
  PlanDate DATETIME NOT NULL
)
--从表
CREATE TABLE PP_MPSBody(
  BillId INT PRIMARY KEY,
  LineNumber SMALLINT NOT NULL,
  ProductID INT NOT NULL,
  ProductQty DECIMAL(18,2) NOT NULL,
PRIMARY KEY(BillId,LineNumber)
)
--设置外键
ALTER TABLE PP_MPSBody
ADD CONSTRAINT FK_PP_MPSHeader_MPSBody FOREIGN KEY(BillId) REFERENCES PP_MPSHeader(BillId)

现在,主从表通过BillId进行关联,当产生一份生产计划时,生成一个BillId,对于用户来说根本没有意义,在随后单据信息的改动中也不会出现上面的主从信息协调问题。同时从表的信息量小于上面的缺陷设计。因为原外键BillNo的长度从20个字节变成了现在的BillId4个字节,减少了信息的冗余。

这样的例子其实很多,比如:
有的设计原材料表时,使用零部件图号作为主键,那就意味着采购、生产、销售等等相关表中都会出现零部件图号的外键信息,当零部件图号信息发生变动时,这些所有先关的信息都需要跟着变动,这种缺陷如果不从根本上解决,那么你可能需要写个零部件图号变动处理过程,来批量处理这些问题,在处理的过程中可能你还得考虑处理的顺序问题……;
有的设计,使用身份证件号作为人员表的主键,但是身份证后来从15位变成了18位,这就意味着人员表中每个人的人员身份证信息都需要变动,如果你是某个社保机构此应用程序的设计人员,那么你就需要更新上百万条记录;那些所有由人员表通过身份证件号外联出去的信息记录将会以亿计数,那么也许余生你就不需要做其他工作了。

所以选择无意义的键值来作为主键的一部分,也是从长远意义上来避免类似这种改动的发生。

(0)

相关推荐

  • 如何获取SqlServer2005表结构(字段,主键,外键,递增,描述)

    1.获取表的基本字段属性 复制代码 代码如下: --获取SqlServer中表结构 SELECT syscolumns.name,systypes.name,syscolumns.isnullable,syscolumns.length FROM syscolumns, systypes WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id('你的表名') 运行效果 2.如果还想要获取字段的描述

  • Oracle数据完整性和锁机制简析

    本课内容属于Oracle高级课程范畴,内容略微偏向理论性,但是与数据库程序开发和管理.优化密切相关:另外本课的部分内容在前面章节已经涉及,请注意理论联系实际. 事务 事务(Transaction)从 通讯的角度看:是用户定义的数据库操作序列,这些操作要么全做.要么全不做,是不可分割的一个工作单元.事务控制语句称为TCL,一般包括Commit和Rollback. 事务不是程序,事务和程序分属两个概念.在RDBMS中,一个事务可以有一条SQL语句.一组SQL语句或者整个程序:一个应用程序又通常包含多

  • 深入Mysql,SqlServer,Oracle主键自动增长的设置详解

    1.把主键定义为自动增长标识符类型MySql在mysql中,如果把表的主键设为auto_increment类型,数据库就会自动为主键赋值.例如: 复制代码 代码如下: create table customers(id int auto_increment primary key not null, name varchar(15));insert into customers(name) values("name1"),("name2");select id fr

  • 详解SQL Server数据库架构和对象、定义数据完整性

    前言 本节我们继续SQL之旅,本节我们如题来讲讲一些基本知识以及需要注意的地方,若有不妥之处,还望指出,简短的内容,深入的理解. 数据库架构和对象 数据库包含架构,而架构又包含对象,架构可以看做是表.视图.存储过程等对象的容器.架构是一个命名空间,它被用做对象名称的前缀,比如在Cnblogs的架构中有一个名称为Blogs的表,此时我们用架构式限定式名称(即两部分式对象名称)所以Blogs表示为Cnblogs.Blogs.如果我们引用对象时省略了架构名称,SQL Server将会检查对象是否存在用

  • SQLServer主键和唯一约束的区别

    首先说明一点,主键又称主键约束,它也是一种约束,看下它和唯一约束的创建语法: alter table Person add constraint PK_Id primary key (Id) alter table Person add constraint UQ_Name unique (Name) 主键和唯一约束都要求字段值唯一,除此外,它们还有如下区别: ·同一张表只能有一个主键,但能有多个唯一约束: ·主键字段值不能为NULL,唯一约束字段值可以为NULL: ·主键字段可以做为其他表的外

  • SQLSERVER实现更改表名,更改列名,更改约束代码

    废话不多说了,具体详情如下所示: 1.修改表名 格式:sp_rename tablename,newtablename sp_rename tablename,newtablename 2.修改字段名 格式:sp_rename 'tablename.colname',newcolname,'column' sp_rename 'tablename.colname',newcolname,'column' 3.添加字段 格式:alter table table_name add new_colum

  • SQLServer导出sql文件/表架构和数据操作步骤

    很多朋友问到sql server数据库"生成脚本",只导出了数据库的sql脚本,而表里的数据依然没有导出来.很简单,看教程: 注:我这里用的SQLServer2008,其它版本应该差不多. 一.选中要导出的数据库–>任务–>生成脚本(或者在任务里面有生成脚本这个选项,好好找找能找到的!) 二.出现"生成和发布脚本"窗口,点击下一步 三.选择要编写脚本的数据库对象,全部导出选第一个,如果你想导出部分数据勾选    第二个就好了 四.出现这个画面后点击&qu

  • SQLSERVER聚集索引和主键(Primary Key)的误区认识

    很多人会把Primary Key和聚集索引搞混起来,或者认为这是同一个东西.这个概念是非常错误的. 主键是一个约束(constraint),他依附在一个索引上,这个索引可以是聚集索引,也可以是非聚集索引. 所以在一个(或一组)字段上有主键,只能说明他上面有个索引,但不一定就是聚集索引. 例如下面: 复制代码 代码如下: USE [pratice] GO CREATE TABLE #tempPKCL ( ID INT PRIMARY KEY CLUSTERED --聚集索引 ) ---------

  • sqlserver 因为选定的用户拥有对象,所以无法除去该用户的解决方法

    现象: 把之前备份的数据库还原到现在的SQL数据库中,现在要把数据库中的用户删除掉,结果却提示: 因为选定的用户拥有对象,所以无法除去该用户 解决办法: 1.打开企业管理器,展开服务器,右键点击本地服器,属性: 打开SQL Server 属性(配置)窗口 2.选择常规窗口 选择 服务器设置窗口,将 允许对系统目录直接进行修改 选上,确定. 4.展开数据库,看到数据库系统表 sysusers ,右键--打开表--返回所有行: 5.选择数据库中要删除的用户,找到相关行,点右键 删除: 选择是, 最后

  • sqlserver数据库主键的生成方式小结(sqlserver,mysql)

    主键的生成方式主要有三种: 一. 数据库自动生成 二. GUID 三. 开发创建 严格讲这三种产生方式有一定的交叉点,其定位方式将在下面进行讲解. 第一种方式,主要将其定位在自增长的标识种子:可以设置起始数值,及增长步长.其优点在于使用时完全将并发任务交于数据库引擎管理,你不用担心存在多用户使用的时候会产生两个相同的ID的情况.其缺点也在于此,多数的数据库不提供直接获取标识ID的方式,对于开发人员来说产生ID的方式是透明的,开发人员几乎无法干预此项.对于数据的迁移也不是很方便. 由于存在上面的利

  • 小议sqlserver数据库主键选取策略

    因为主键可以唯一标识某一行记录,所以可以确保执行数据更新.删除的时候不会出现张冠李戴的错误.当然,其它字段可以辅助我们在执行这些操作时消除共享冲突,不过就不在这里讨论了.主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致.所以数据库在设计时,主键起到了很重要的作用. 常见的数据库主键选取方式有: 自动增长字段 手动增长字段 UniqueIdentifier "COMB(Combine)"类型 一.自动增长型字段 很多数据库设计者喜欢使用自动增长型字段,因为它使用简单.

  • SQLServer2005 批量查询自定义对象脚本

    object_definition的官方参考 http://msdn.microsoft.com/zh-cn/library/ms176090.aspx 以下代码可以批量查看或者导出视图.存储过程.触发器和函数的脚本 复制代码 代码如下: select name , xtype , object_definition (id ) from sysobjects where xtype in ('V' , 'P' , 'TR' , 'IF' , 'TF' , 'FN' ) order by xty

随机推荐