SQL Server 对表的主键设计问题及解决办法
来源:asp之家 发布时间:2010-06-07 13:29:00
关于数据库的逻辑设计,是一个很广泛的问题。本文主要针对开发应用中遇到在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”中反映为数据库中的一行。
猜你喜欢
- 本文摘自 《深度学习原理与PyTorch实战》我们将从预测某地的共享单车数量这个实际问题出发,带领读者走进神经网络的殿堂,运用PyTorch
- 导言结束前面的几节,我们已经探讨过了如何使用GridView、DetailsView和FormView控件来显示数据。这些控件简单地操作提供
- 看知乎的时候发现了一个 “如何正确地吐槽” 收藏夹,里面的一些神回复实在很搞笑,但是一页一页地看又有点麻烦,而且每次都要打开网页,于是想如果
- 幸运草又名四叶草,一般指四叶的苜蓿、或车轴草。在十万株苜蓿草中,你可能只会发现一株是四叶草,机会率大约是十万分之一。因此四叶草是国际公认的幸
- 本文帮你六步改善SQL Server安全规划全攻略。一、什么是SQL注入式攻击所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的
- 1.创建应用django-admin startproject cloudmscd cloudmspython manage.py star
- 前言本文介绍的主要内容是 Redux-Toolkit 在 React + TypeScript 大型应用中的实践,主要解决的问题是使用 cr
- 原来的语句是这样的: select sum(sl0000) from xstfxps2 where dhao00 in ( select d
- 一、为什么要进行包管理?python中的三方包琳琅满目,提供了各种各样的功能,使得我们免于自己去手写很多代码。比如,我们在测试接口的时候,我
- odeJs 微信公众号功能开发,移动端 H5页面调用微信的支付功能。这几天根据公司的需要使用 node 和 h5页面调用微信的支付功能完成支
- 小程序miniso的一个发布内容截图功能,话不多,先上代码wxml文件:<view class="cut-1-1 t-c {
- 本文用163邮箱进行了测试,python用的是3.8版本进行的测试1.设置邮箱,如下图所示2.设置过程如下图所示:设置完成后,添加如下代码:
- 前言这是俺写的第一篇关于python的博客,分享一下我所整合的python中的随机数函数,就当作是自己的一个笔记,也可以供像我一样的pyth
- 数据库和操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操
- 本文实例讲述了python实现根据图标提取分类应用程序,分享给大家供大家参考。具体方法如下:#!/usr/bin/python # -*-
- 本文实例讲述了MySql数据库基础知识点。分享给大家供大家参考,具体如下:数据库基本操作1)创建数据库基本语法: create databa
- 本文实例讲述了PHP抓取及分析网页的方法。分享给大家供大家参考,具体如下:抓取和分析一个文件是非常简单的事。这个教程将通过一个例子带领你一步
- 在分析python的参数传递是如何进行的之前,我们需要先来了解一下,python变量和赋值的基本原理,这样有助于我们更好的理解参数传递。py
- 本文介绍了vue生成随机验证码的示例代码,分享给大家,具体如下:样式自调,最终效果如图:实现效果:点击右边input框会自动切换,如果输入的
- 不错,这个是一个文章详细页,没有左右两栏布局,不过这里我重点要讲的是合理的布局,在稍后的文章中我会详细的介绍浮动元素。好,回到刚才的话题,大