【唠叨两句】简单说一说一个最长用的数据表SysUser【系统用户表】
我相信几乎每一个用到用户登录的系统中都要有这样一个系统用户表吧,当然表的名字可能有所不同,但其代表的意义应该算是都一样的吧。
在我看来这个表是比较特殊的,我说它特殊有如下这么几项原因:
(1)一般情况下:SysUser表的主键对于用户而言是可见的,并且是系统用户自己任意添加的(在这里排除数据表对与该数据列的约束)。
而其他类型的表呢?主键一般是没有必要让用户看到的,而且其主键值一般是不受 人为操控的。 还有一点主键列通常使用的有: 启用递增的标识列,DateTime.Now.Ticks,Guid等等。
(2)在系统中,用户名就相当于代表了现实生活中一个真实的用户的身份,尤其是在一些管理系统、商务系统等等中,系统用户的每一个操作都是承担着相应的责任的,所以SysUser表中的记录是不可以随意删除的,否则当系统出现问题时,追查数据、及相关责任人时 都会遇到困难的。
基于以上的所述原因,让我们在看一个小例子,现比如有如下一个SysUser表,该表要被多个机构所共用:
UserID: 主键 char(20)用户名
UserName: char(20)用户真实姓名
OrganizationID: char(30)所属机构ID号,该ID号为DateTime.Now.Ticks.ToString();
UserPhone: char(20)用户电话
PassWord: char(20)用户密码
IsUsed: bit 是否可用,删除的时候其实是将该字段设为 False
由于这里的主键只有UserID这一列,删除记录并不是使用的DELETE 语句,而只是将IsUsed字段改成了False,所以在这样的表结构下就回产生一个问题就是:删除一个用户名之后、再添加一个相同的用户名就会报主键约束。而且两个不同的机构之间也不能有相同的用户名。
面对这个很现实的问题,这样的软件交不了工,还得改。唉,也只能怪当时没能把这些问题考虑到。
由于这个软件的相当多的一部分编码工作已经做完了,所以要是在这种情况下去更改数据库结构,哇塞,那简直就是将一颗大树连根把起,这样做很不现实,所以要想办法降低软件的改动量。
刚遇到这个问题时、我的思考过程是如下的:
(1)将UserID,OrganizationID,IsUsed三列弄成一个主键列,但是这样做也是有问题的,比如这种情况:已经有一个UserID 为 “AAA”OrganizationID 为 “18个8”的用户被删除,现在有添加了一个UserID为“AAA”OrganizationID 为 “18个8”的用户,但是这个用户一旦被删除就会违反主键约束。
(2)增加一个ID列作为主键,但是这样还是有问题的,因为这样做UserID就不能作为其他表的外键使用了。
(3)将UserID和OrganizationID设成主键列。删除时 使用DELETE 删除数据,但是同时要用另外的一张表来保存UserID 的历史记录,即某一个UserID对应的真实姓名、创建时间、每一次的修改时间、删除时间,注意这张表中数据只允许添加不允许修改和删除。但是这样做还是于上述的(3)无任何差别,同样改变了主键列,导致外键失效。
(4)经过上面的思考已经能够明确,SysUser这个表的主键列不能改动,但是还要解决上述的两个问题:【删除一个用户名之后、再添加一个相同的用户名就会报主键约束。而且两个不同的机构之间也不能有相同的用户名。】
慢慢想来,其实这些问题可以转化为如何实现“用户所见【用户名】和数据库实际保存【用户名】相分离”,再具体一点就是【在此以UserID 为 AAA 机构编号为 “18个8”为例】:
如何将AAA经过一个特定规则转化成其他数据然后保存到数据库中,
再深度思考一下我们可以这样做:将UserID长度改成60,保存数据时UserID列实际保存的数据是
“UserID【长度不固定、但是可以计算出来】”+“OrganizationID【18位、长度固定】”+“一个顺序的四位编号【4位、长度固定】”,读取数据时UserID还是读取用户所见的真是UserID。
其中的“四位顺序编号”是用回来解决相同机构中相同UserID的问题,即同一个机构中第一次出现的“AAA”,默认给他分配“0001”,同一个机构第二次的“AAA”给他分配“0002”,依次类推。【四位的顺序编号、分配最好还要借助一个表去完成,这个表的机构是UserID【用户所见用户名、主键】,OrganizationID【机构编号、主键】,Index【四位顺序编号】】
这样以来就做到了“用户所见和数据库保存相分离”,这样做只需要改动“相关的UserID列的读写即可”,改动算是比较小的,可以解决上述问题。
嘿嘿…… 大侠们见效喽,如果您还有更好的想法和建议,还望多多指教哦…