主键
必要性: 有些朋友可能不提倡数据库表必须要主键
![](/icons/46378dou.gif)
但在我
![](/icons/46378de.gif)
研究中
![](/icons/46378dou.gif)
觉得每个表都应该具有主键
![](/icons/46378dou.gif)
不管是单主键还是双主键
![](/icons/46378dou.gif)
主键
![](/icons/46378de.gif)
存在就代表着表结构
![](/icons/46378de.gif)
完整性
![](/icons/46378dou.gif)
表
![](/icons/46378de.gif)
记录必须得有唯
![](/icons/46378yi.gif)
区分
![](/icons/46378de.gif)
字段
![](/icons/46378dou.gif)
主键主要是用于其他表
![](/icons/46378de.gif)
外键关联
![](/icons/46378dou.gif)
本记录
![](/icons/46378de.gif)
修改和删除
![](/icons/46378dou.gif)
当我们没有主键时
![](/icons/46378dou.gif)
这些操作会变
![](/icons/46378de.gif)
非常麻烦
主键
无意义性: 我强调主键不应该具有实际
![](/icons/46378de.gif)
意义
![](/icons/46378dou.gif)
这可能对于
![](/icons/46378yi.gif)
些朋友来说不太认同
![](/icons/46378dou.gif)
比如订单表吧
![](/icons/46378dou.gif)
会有“订单编号”字段
![](/icons/46378dou.gif)
而这个字段呢在业务实际中本身就是应该具有唯
![](/icons/46378yi.gif)
性
![](/icons/46378dou.gif)
具有唯
![](/icons/46378yi.gif)
标识记录
![](/icons/46378de.gif)
功能
![](/icons/46378dou.gif)
但我是不推荐采用订单编号字段作为主键
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
![](/icons/46378yinwei.gif)
具有实际意义
![](/icons/46378de.gif)
字段
![](/icons/46378dou.gif)
具有“意义更改”
![](/icons/46378de.gif)
可能性
![](/icons/46378dou.gif)
比如订单编号在刚开始
![](/icons/46378de.gif)
时候我们
![](/icons/46378yi.gif)
切顺利
![](/icons/46378dou.gif)
后来客户说“订单可以作废
![](/icons/46378dou.gif)
并重新生成订单
![](/icons/46378dou.gif)
而且订单号要保持原订单号
![](/icons/46378yi.gif)
致”
![](/icons/46378dou.gif)
这样原来
![](/icons/46378de.gif)
主键就面临危险了
![](/icons/46378dou2.gif)
因此
![](/icons/46378dou.gif)
具有唯
![](/icons/46378yi.gif)
性
![](/icons/46378de.gif)
实际字段也代表可以作为主键
![](/icons/46378dou2.gif)
因此
![](/icons/46378dou.gif)
我推荐是新设
![](/icons/46378yi.gif)
个字段专门用为主键
![](/icons/46378dou.gif)
此主键本身在业务逻辑上不体现
![](/icons/46378dou.gif)
不具有实际意义
![](/icons/46378dou2.gif)
而这种主键在
![](/icons/46378yi.gif)
定
![](/icons/46378chengxu.gif)
增加了复杂度
![](/icons/46378dou.gif)
所以要视实际系统
![](/icons/46378de.gif)
规模大小而定
![](/icons/46378dou.gif)
对于小项目
![](/icons/46378dou.gif)
以后扩展不会很大
![](/icons/46378de.gif)
话
![](/icons/46378dou.gif)
也查允许用实际唯
![](/icons/46378yi.gif)
![](/icons/46378de.gif)
字段作主键
![](/icons/46378de.gif)
主键
选择 我们现在在研究
![](/icons/46378yi.gif)
下
![](/icons/46378dou.gif)
应该采用什么来作表
![](/icons/46378de.gif)
主键比较合理
![](/icons/46378dou.gif)
申明
![](/icons/46378yi.gif)
下
![](/icons/46378dou.gif)
主键
![](/icons/46378de.gif)
设计没有
![](/icons/46378yi.gif)
个定论
![](/icons/46378dou.gif)
各人有各人
![](/icons/46378de.gif)
思路方法
![](/icons/46378dou.gif)
哪怕同
![](/icons/46378yi.gif)
个
![](/icons/46378dou.gif)
在区别
![](/icons/46378de.gif)
项目中
![](/icons/46378dou.gif)
也会采用区别
![](/icons/46378de.gif)
主键设计原则
第
:编号作主键 此思路方法就是采用实际业务中
![](/icons/46378de.gif)
唯
![](/icons/46378yi.gif)
字段
![](/icons/46378de.gif)
“编号”作为主键设计
![](/icons/46378dou.gif)
这在小型
![](/icons/46378de.gif)
项目中是推荐这样做
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
![](/icons/46378yinwei.gif)
这可以使项目比较简单化
![](/icons/46378dou.gif)
但在使用中却可能带来
![](/icons/46378yi.gif)
些麻烦
![](/icons/46378dou.gif)
比如要进行“编号修改”时
![](/icons/46378dou.gif)
可能要涉及到很多相关联
![](/icons/46378de.gif)
其他表
![](/icons/46378dou.gif)
就象黎叔说
![](/icons/46378de.gif)
“后果很严重”;还有就是上面提到
![](/icons/46378de.gif)
“业务要求允许编号重复时”
![](/icons/46378dou.gif)
我们再那么先知
![](/icons/46378dou.gif)
都无法知道业务将会修改成什么?
第 2:自动编号主键 这种思路方法也是很多朋友在使用
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
就是新建
![](/icons/46378yi.gif)
个ID字段
![](/icons/46378dou.gif)
自动增长
![](/icons/46378dou.gif)
非常方便也满足主键
![](/icons/46378de.gif)
原则
![](/icons/46378dou.gif)
优点是:数据库自动编号
![](/icons/46378dou.gif)
速度快
![](/icons/46378dou.gif)
而且是增量增长
![](/icons/46378dou.gif)
聚集型主键按顺序存放
![](/icons/46378dou.gif)
对于检索非常有利;数字型
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
占用空间小
![](/icons/46378dou.gif)
易排序
![](/icons/46378dou.gif)
在
![](/icons/46378chengxu.gif)
中传递也方便;如果通过非系统增加记录(比如手动录入
![](/icons/46378dou.gif)
或是用其他工具直接在表里插入新记录
![](/icons/46378dou.gif)
或老系统数据导入)时
![](/icons/46378dou.gif)
非常方便
![](/icons/46378dou.gif)
不用担心主键重复问题
![](/icons/46378dou2.gif)
缺点:其实缺点也就是来自其优点
![](/icons/46378dou.gif)
就是
![](/icons/46378yinwei.gif)
自动增长
![](/icons/46378dou.gif)
在手动要插入指定ID
![](/icons/46378de.gif)
记录时会显得麻烦
![](/icons/46378dou.gif)
尤其是当系统和其他系统集成时
![](/icons/46378dou.gif)
需要数据导入时
![](/icons/46378dou.gif)
很难保证原系统
![](/icons/46378de.gif)
ID不发生主键冲突(前提是老系统也是数字型
![](/icons/46378de.gif)
);如果其他系统主键不是数字型那就麻烦更大了
![](/icons/46378dou.gif)
会导致修改主键数据类型了
![](/icons/46378dou.gif)
这也会导致其他相关表
![](/icons/46378de.gif)
修改
![](/icons/46378dou.gif)
后果同样很严重;就算其他系统也是数字型
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
在导入时
![](/icons/46378dou.gif)
为了区分新老数据
![](/icons/46378dou.gif)
可能想在老数据主键前统
![](/icons/46378yi.gif)
加
![](/icons/46378yi.gif)
个“o”(old)来表示这是老数据
![](/icons/46378dou.gif)
那么自动增长
![](/icons/46378de.gif)
数字型又面临
![](/icons/46378yi.gif)
个挑战
第 3:Max加![](/icons/46378yi.gif)
由于自动编号存在那些问题
![](/icons/46378dou.gif)
所以有些朋友就采用自己生成
![](/icons/46378dou.gif)
同样是数字型
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
只是把自动增长去掉了
![](/icons/46378dou.gif)
采用在Insert时
![](/icons/46378dou.gif)
读取Max值后加
![](/icons/46378yi.gif)
![](/icons/46378dou.gif)
这种思路方法可以避免自动编号
![](/icons/46378de.gif)
问题
![](/icons/46378dou.gif)
但也存在
![](/icons/46378yi.gif)
个效率问题
![](/icons/46378dou.gif)
如果记录非常大
![](/icons/46378de.gif)
话
![](/icons/46378dou.gif)
那么Max
![](/icons/46378kh.gif)
也会影响效率
![](/icons/46378de.gif)
;更严重
![](/icons/46378de.gif)
是并发性问题
![](/icons/46378dou.gif)
如果同时有两人读到相同
![](/icons/46378de.gif)
Max后
![](/icons/46378dou.gif)
加
![](/icons/46378yi.gif)
后插入
![](/icons/46378de.gif)
ID值会重复
![](/icons/46378dou.gif)
这已经是有经验教训
![](/icons/46378de.gif)
了
![](/icons/46378dou2.gif)
[Page]
第 4:自制加![](/icons/46378yi.gif)
考虑Max加
![](/icons/46378yi.gif)
![](/icons/46378de.gif)
效率后
![](/icons/46378dou.gif)
有人采用自制加
![](/icons/46378yi.gif)
![](/icons/46378dou.gif)
也就是建
![](/icons/46378yi.gif)
个特别
![](/icons/46378de.gif)
表
![](/icons/46378dou.gif)
字段为:表名
![](/icons/46378dou.gif)
当前序列值
![](/icons/46378dou2.gif)
这样在往表中插入值时
![](/icons/46378dou.gif)
先从此表中找到相应表
![](/icons/46378de.gif)
最大值后加
![](/icons/46378yi.gif)
![](/icons/46378dou.gif)
进行插入
![](/icons/46378dou.gif)
有人可能发现
![](/icons/46378dou.gif)
也可能会存在并发处理
![](/icons/46378dou.gif)
这个并发处理
![](/icons/46378dou.gif)
我们可以采用lock线程
![](/icons/46378de.gif)
方式来避免
![](/icons/46378dou.gif)
在生成此值
![](/icons/46378de.gif)
时
![](/icons/46378dou.gif)
先Lock
![](/icons/46378dou.gif)
取到值以后
![](/icons/46378dou.gif)
再unLock出来
![](/icons/46378dou.gif)
这样不会有两人同时生成了
![](/icons/46378dou2.gif)
这比Max加
![](/icons/46378yi.gif)
![](/icons/46378de.gif)
速度要快多了
![](/icons/46378dou2.gif)
但同样存在
![](/icons/46378yi.gif)
个问题:在和其他系统集成时
![](/icons/46378dou.gif)
脱离了系统中
![](/icons/46378de.gif)
生成思路方法后
![](/icons/46378dou.gif)
很麻烦保证自制表中
![](/icons/46378de.gif)
最大值和导入后
![](/icons/46378de.gif)
保持
![](/icons/46378yi.gif)
致
![](/icons/46378dou.gif)
而且数字型都存在上面讲到
![](/icons/46378de.gif)
“o”老数据
![](/icons/46378de.gif)
导入问题
![](/icons/46378dou2.gif)
因此在“自制加
![](/icons/46378yi.gif)
”中可以把主键设为
![](/icons/46378zifu.gif)
型
![](/icons/46378de.gif)
![](/icons/46378dou2.gif)
![](/icons/46378zifu.gif)
型
![](/icons/46378de.gif)
自制加
![](/icons/46378yi.gif)
我倒是蛮推荐
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
应该
![](/icons/46378zifu.gif)
型主键可以应付很多我们意想不到
![](/icons/46378de.gif)
情况
第 5:GUID主键 目前
![](/icons/46378yi.gif)
个比较好
![](/icons/46378de.gif)
主键是采用GUID
![](/icons/46378dou.gif)
当然我是推荐主键还是
![](/icons/46378zifu.gif)
型
![](/icons/46378de.gif)
![](/icons/46378dou.gif)
但值由GUID生成
![](/icons/46378dou.gif)
GUID是可以自动生成
![](/icons/46378dou.gif)
也可以
![](/icons/46378chengxu.gif)
生成
![](/icons/46378dou.gif)
而且键值不可能重复
![](/icons/46378dou.gif)
可以解决系统集成问题
![](/icons/46378dou.gif)
几个系统
![](/icons/46378de.gif)
GUID值导到
![](/icons/46378yi.gif)
起时
![](/icons/46378dou.gif)
也不会发生重复
![](/icons/46378dou.gif)
就算有“o”老数据也可以区分
![](/icons/46378dou.gif)
而且效率很高
![](/icons/46378dou.gif)
在.NET里可以直接使用
![](/icons/46378System.gif)
.Guid.NewGuid
![](/icons/46378kh.gif)
进行生成
![](/icons/46378dou.gif)
在SQL里也可以使用 NewID
![](/icons/46378kh.gif)
生成
优点是: 同 IDENTITY 列相比
![](/icons/46378dou.gif)
uniqueident
![](/icons/46378if.gif)
ier 列可以通过 NewID
![](/icons/46378hanshu.gif)
提前得知新增加
![](/icons/46378de.gif)
行 ID
![](/icons/46378dou.gif)
为应用
![](/icons/46378chengxu.gif)
![](/icons/46378de.gif)
后续处理提供了很大方便
![](/icons/46378dou2.gif)
便于数据库移植
![](/icons/46378dou.gif)
其它数据库中并不
![](/icons/46378yi.gif)
定具有 IDENTITY 列
![](/icons/46378dou.gif)
而 Guid 列可以作为
![](/icons/46378zifu.gif)
型列转换到其它数据库中
![](/icons/46378dou.gif)
同时将应用
![](/icons/46378chengxu.gif)
中产生
![](/icons/46378de.gif)
GUID 值存入数据库
![](/icons/46378dou.gif)
它不会对原有数据带来影响
![](/icons/46378dou2.gif)
便于数据库
![](/icons/46378chushi.gif)
化
![](/icons/46378dou.gif)
如果应用
![](/icons/46378chengxu.gif)
要加载
![](/icons/46378yi.gif)
些
![](/icons/46378chushi.gif)
数据
![](/icons/46378dou.gif)
IDENTITY 列
![](/icons/46378de.gif)
处理方式就比较麻烦
![](/icons/46378dou.gif)
而 uniqueident
![](/icons/46378if.gif)
ier 列则无需任何处理
![](/icons/46378dou.gif)
直接用 T-SQL 加载即可
![](/icons/46378dou2.gif)
便于对某些对象或常量进行永久标识
![](/icons/46378dou.gif)
如类
![](/icons/46378de.gif)
ClassID
![](/icons/46378dou.gif)
对象
![](/icons/46378de.gif)
例子标识
![](/icons/46378dou.gif)
UDDI 中
![](/icons/46378de.gif)
联系人、服务接口、tModel标识定义等
缺点是: GUID 值较长
![](/icons/46378dou.gif)
不容易记忆和输入
![](/icons/46378dou.gif)
而且这个值是随机、无顺序
![](/icons/46378de.gif)
![](/icons/46378dou2.gif)
GUID
![](/icons/46378de.gif)
值有 16 个字节
![](/icons/46378dou.gif)
和其它那些诸如 4 字节
![](/icons/46378de.gif)
整数相比要相对大
![](/icons/46378yi.gif)
些
![](/icons/46378dou2.gif)
这意味着如果在数据库中使用 uniqueident
![](/icons/46378if.gif)
ier 键
![](/icons/46378dou.gif)
可能会带来两方面
![](/icons/46378de.gif)
消极影响:存储空间增大;索引时间较慢
延伸阅读
最新评论