网络编程
位置:首页>> 网络编程>> 数据库>> SQL Server 对表的主键设计问题及解决办法

SQL Server 对表的主键设计问题及解决办法

 来源:asp之家 发布时间:2010-06-07 13:29:00 

标签:SQL,Server,主键设计,解决办法

关于数据库的逻辑设计,是一个很广泛的问题。本文主要针对开发应用中遇到在MS SQL Server上进行表设计时,对表的主键设计应注意的问题以及相应的解决办法。

主键设计现状和问题

关于数据库表的主键设计,一般而言,是根据业务需求情况,以业务逻辑为基础,形成主键。

比如,销售时要记录销售情况,一般需要两个表,一个是销售单的概要描述,记录诸如销售单号、总金额一类的情况,另外一个表记录每种商品的数量和金额。对于第一个表(主表),通常我们以单据号为主键;对于商品销售的明细表(从表),我们就需要将主表的单据号也放入到商品的明细表中,使其关联起来形成主从关系。同时该单据号与商品的编码一起,形成明细表的联合主键。这只是一般情况,我们稍微将这个问题延伸一下:假如在明细中,我们每种商品又可能以不同的价格方式销售。有部分按折扣价格销售,有部分按正常价格销售。要记录这些情况,那么我们就需要第三个表。而这第三个表的主键就需要第一个表的单据号以及第二个表的商品号再加上自身需要的信息一起构成联合主键;又或者其他情况,在第一个主表中,本身就是以联合方式构成联合主键,那么也需要在从表中将主表的多个字段添加进来联合在一起形成自己的主键。

数据冗余存储:随着这种主从关系的延伸,数据库中需要重复存储的数据将变得越来越庞大。或者当主表本身就是联合主键时,就必须在从表中将所有的字段重新存储一次。

SQL复杂度增加:当存在多个字段的联合主键时,我们需要将主表的多个字段与子表的多个字段关联以获取满足某些条件的所有详细情况记录。

程序复杂度增加:可能需要传递多个参数。

效率降低:数据库系统需要判断更多的条件,SQL语句长度增加。同时,联合主键自动生成联合索引

WEB分页困难:由于是联合主键方式(对于多数的子表),那么在WEB页面上要进行分页处理时,在自关联时,难于处理。

解决方案

从上面,我们已经看到现有结构存在着相当多的弊端,主要是导致程序复杂、效率降低并且不利于分页。

为解决上述问题,本文提出:当应用系统后台数据库表间存在主从关系时,数据库表额外增加一非业务字段作为主键,该字段为数值型;或者当该表需要在应用中进行分页查询时,也应考虑如此设计。一般地,我们也可以几乎为任何表增加一个与业务逻辑无关的字段作为该表的主键字段。

由于该字段要作为表的主键,那么其首要条件是要保证在该表中要具有唯一性。同时,结合SQL Server数据库自身的特性,可以为其建立一个自增列:


以下为引用的内容:

create TABLE T_PK_DEMO
(
U_ID  BIGINT NOT NULL IDENTITY(1,1),
--唯一标识记录的ID
COL_OTHER VARchar(20) NOT NULL ,
--其他列
CONSTRAINT PK_T_PK_DEMO PRIMARY KEY NONCLUSTERED
(U_ID)--定义为主键
)


但是,SQL Server中的自增列却存在一个比较尴尬的事实,那就是该字段一旦定义和使用,用户无法直接干预该字段的值,完全由数据库系统自身控制:

完全数据库系统控制,用户无法修改值

在数据库的发布和订阅时,使用自增列会比较麻烦

恢复部分数据时,使用自增列会比较麻烦

该列的值必须在插入数据后才能获取

鉴于此,建议不以自增列的方式来定义,而是参考Oracle数据库系统中序列,在SQL Server系统中实现类似Oracle数据库系统序列功能。这个具体在下面的小节中介绍。我们只需要按照普通字段的定义方式修改表定义为:


以下为引用的内容:

create TABLE T_PK_DEMO
(
U_ID  BIGINT NOT NULL ,--唯一标识记录的ID
COL_OTHER VARchar(20) NOT NULL ,--其他列
CONSTRAINT PK_T_PK_DEMO PRIMARY KEY NONCLUSTERED (U_ID)--定义为主键
)


参照Oracle序列的功能,我们需要在SQL Server数据库中创建一个新表,以管理序列值:


以下为引用的内容:

create TABLE T_DB_SEQ
(
SEQ_NAMEVARchar(50) NOT NULL ,--序列名称
SEQ_OWNER  VARchar(50) NOT NULL DEFAULT ’DBO’,
--序列所有者(SYSTEM_USER)
SEQ_CURRENT BIGINT NOT NULL DEFAULT 0,--序列当前值
SEQ_MIN BIGINT NOT NULL DEFAULT 0,--序列最小值
SEQ_MAX BIGINT NOT NULL DEFAULT 0,--序列最小值
SEQ_MAX BIGINT NOT NULL DEFAULT 0,--序列最大值
SEQ_STEPINT NOT NULL DEFAULT 1,--序列增长步长
IF_CYCLEINT NOT NULL DEFAULT 0,--是否循环(0,不循环;1,循环)
CONSTRAINT T_DB_SEQ PRIMARY KEY CLUSTERED
(SEQ_NAME,SEQ_OWNER)--主键
)


应用系统为需要创建自增列的表创建一个序列名称,在表“T_DB_SEQ”中反映为数据库中的一行。



0
投稿

猜你喜欢

  • 我想让一片文章,每到3000字就分到下一条插入到数据库,求高手  <%Dim Content Conte
  • MySQL数据库线程缓冲池的相关知识是本文我们主要要介绍的内容,MySQL数据库支持线程缓存,在多线程连接模式下,如果连接断开后,将这个线程
  • 一看,C盘只有不到2M可用空间,一查原因,sqlserver安装路径下的log目录文件占了好大,5G多, 于是上网搜了下,解决了: 把与sq
  • 分享人:月漓作为交互设计师,你是否在一个项目中花费大量的时间来沟通、修改、明确需求?其实这些前期工作(设计原型前)是我们和PD、运营、开发之
  • 那么在集合函数中它有什么用呢 ?假设数据库有一张表名为student的表。如果现在要你根据这张表,查出江西省男女个数,广东省男生个数,浙江省
  •     Dreamweaver MX 2004的强大功能以及更加完善的人性化设置已经深受大家喜爱。在此笔者就谈
  • 关于中大型开发b/s开发中的缓存(cache),我的一些看法,有不正确的或者是有笔误的地方,请指正。thanks首先,应该了解基本的,对于缓
  • 今天在 经纬 同学blog看到的。有这么一段代码:<ul id="demo"><li>
  • 求英文字母、数字、下划线、汉字的js正则表达式英文字母或数字或下划线,英文字母数字下划线是:/^\w+$/汉字的是:/^[\u0391-\u
  • 在学习与运用ASP中,response对象涉及到的方面也比较多,想全部都掌握也并非一两天的事,我也是最近才发现response对象中居然有这
  • 如果视图定义包括条件(譬如 WHERE 子句)并且其意图是确保任何引用该视图的 INSERT 或 UPDATE 语句都应用 WHERE 子句
  • 使用css2.1实现多重背景、多重边框效果在单个HTML元素上利用CSS2.1实现拥有3张背景图片和2张内容图效果,或者多重边框的效果。这种
  • 在CSS规范中有一个渲染对象的概念,通常用一个盒子(box, rectangle)来表示。mozilla通过一个叫frame的对象对盒子进行
  • 第一次写这类文章,有点儿紧张有点儿新奇有点儿痛苦,来CDC实习2个月啦,每天除了工作就是体验体验再体验,因为之前做了一些有关规范的工作,突然
  • 可用下列函数来产生你需要的东西,将它们发送给用户就可以啦:<%response.write makePassword(16)
  • 在域环境下我没配置成果,也许是域用户的原因,因为我在生产环境下搞的,更改域用户需要重启SQLServer ,所以这个方法放弃了,只能用证书形
  • 下面是我已经证实可用的自动备份的方法. 1、打开企业管理器->管理->sql server代理 2、新建一个作业,作业名称随便取
  • asp ajax json教程首先用ACCESS建json.mdb的库,然后建一个表t_jsontable,字段如下:jt_id,jt_na
  • 如何用POP3接收电子邮件?POP3大行其道,我看见朋友已经用Jmail和POP3接收邮件了。该如何做?以Jmail4.1为例,我们演示一下
  • 是否看见大站的广告都是放在内容中间实现文字环绕的呢,一般普通小站广告只能放在内容开头或者结尾,也许大站的cms系统带这个功能吧,我们小站常用
手机版 网络编程 asp之家 www.aspxhome.com