谈谈数据库设计——避免多义性

发表于:2013-4-15 09:22

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:十三燕    来源:51Testing软件测试网采编

  避免数据库表或字段具有多种意思。

  先来看一个糟糕的设计,以下将分析由数据库字段两意性引发的惨案。

图1

  图中两张表,表示入库申请和实际入库出库,由于入库和出库行为非常相似,所以只用了一张表并用单据类别区分入库和出库。

  表面没什么问题,只要在程序中判断单据类别就能使用。

  但实际开发过程当中问题远不止这些。

  1、看申请单据ID

  由于入库时需要申请,所以这里有个申请单据ID。但出库不需要申请,入库时有特殊情况不需要申请直接入库的,所以这两种情况是没有申请单据ID的。

  怎么处理?有申请单据ID就插入ID这个没有问题,不需要申请时呢?将这列设置成允许为空,并设默认值为0。

  这时看似问题解决了,其实还差一点。如果程序中出现BUG,比如连续按多次保存,将可能再入库时插入多次重复的记录。

  这破坏了一张申请单据只能对应一张实际入库单据的规则。

  由于出库单据的申请单据ID列都为默认值0,或者是null,所以没办法给该列添加唯一约束,结论是没办法在数据库的设计中就表现出两单据的1对1关系,必须要在程序中,所有涉及的地方都明确地判断,不然可能会造成数据的不正确性。

  虽然无法保证程序中所有用到的地方都体现两张单据1对1的关系,可以退一步求其次,用另一种方法来保证这个入库操作插入时不会重复插入。

  解决办法是在单据编号中建立唯一约束,这样就能解决。

  另外值得一提的是,这样设计没办法建立外键约束,外键索引(Oracle和MSSQLSERVER在建立外键时会自动加上外键索引,这里不能建立外键,只能手动添加索引),因为ID=0在申请单据表中找不到相对应的意思。前面说到在程序中要明确地判断,就是要判断这个ID为0是什么意思,到底是去找申请单据ID=0的记录呢?还是表示他没有通过申请直接入库的?比如在查询所有直接入库时需要加入where 申请单据ID = 0 ,除非在申请单据表中事先存在ID=0的数据,但还是需要判断这个单据的意思是表示没有单据。

  2、再看单据编号

  这里的单据编号其实有两个意思,入库单据编号和出库单据编号。

  前面提到给该列建立唯一约束,来保证数据的完整性。但是建立唯一约束以后,单据编号中就需要有一部分能区分入库与出库的标示,不然可能出现撞号,这将让单据编号的规则变的更加复杂。

  例如,入库单据编号为20121212001,意思是2012年12月12日第一个入库的单据,填写第一个出库单据时撞上了,得给编号留一位作为标示符,比如I20121212001,O201212001。

  单据编号的真正意思,取决于单据类别这个字段。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号