Office中国论坛/Access中国论坛

标题: 数据一致性与有效性的问题 [打印本页]

作者: lgxysl    时间: 2002-10-12 21:25
标题: 数据一致性与有效性的问题
学数据库的人都知道,数据的一致性与有效性很重要,由于access没有触发器,要保证数据的一致性与有效性就成了一个问题,虽然可能通过定义表与表之间的关系和使用有效性规则解决一些问题,但是有些问题的解决则有些困难(至少对我而言是这样),例如:
有一个表,其中有一个字段是“科室” ,另一个字段是“姓名”,这两个都是必填的字段,而且都已经设置成“必填字段”,现在科室的值是“生产科”,姓名是“黄小二”,“黄小二”是“生产科”的员工,这没有问题,但是如果改变了这两值的其中的一个(例如“生产科”改成“销售科”),但另一个操作员忘了改变,这就变成“黄小二”是“销售科”的员工了,但“黄小二”并不是“销售科”的员工,“销售科”也没有“黄小二”这个人,这不是乱套了吗?这虽然是操作员录入时的错误,但怎样才能保证这样的错误不会发生呢?
还有,例如有一个表,有字段“购进价”与“销售价”,现在由于购进价提价了,操作员改变了“购进价”的值(变成10元),但忘了改变“销售价”的值(原为9元),这就变成“销售价”比“购进价”还小 ,这不就让公司赔本了吗?怎样才能保证这样的错误不发生呢?
再有,有一个表有字段为“已付款”和“付款日期”,如果“已付款”的值为“已付”,但“付款日期”将为必填,怎样才能保证“已付款”这“已付”时,但“付款日期”没有填的记录不能保存呢,而必须要求填写“付款日期”呢?
对于以上这些,我现在所能做到的只是提示操作员“记录不全”,但并不能阻止这样的记录的保存。请各位高手有何高见?
作者: gnoy    时间: 2002-10-12 21:45
问题很好,但都不是ACCESS的错。
1.如设为两个表。"科室","员工"此不成问题
2.根据ERP系统来看这应该不是问题。如果售价应该变动则一定会记得改因为你要修改发票,不改打不出正确发票,打不出发票收不到钱(我所指的是西方作业方式:INVOICE,CREDIT NOTE,DEBIT NOTE)。本人建议不变动以前记录,而是象西方做法一样有变动会有另外模块处理来调整收入。如果售价不需变动亏是正确的。如果什么都不记得那只有下岗
3.不是问题,ACCESS能作到

作者: lgxysl    时间: 2002-10-13 04:11
看来我们得再详细地讨论这个问题,先讨论第一个问题吧(以一个医院管理系统为例,为简化,只列出一些相关的字段):
1、科室表:
ID   名称
1    内科
2    外科
3   妇科

2、职员表(其中“所在科室ID”与科室表的“ID”相连接,是一对多的关系,实施参照完整性):
ID  姓名           所在科室ID
1   黄小二       2
2   李明           1
3   张天           3

3、住院病人管理表(“住院科室ID”与“科室表”的ID连接,一对多关系;“主治医生ID”与“职员表”的ID相连接,一对多关系)
ID   病人姓名   住院科室ID   主治医生ID
1    陈月明       2                     1
2    何天           1                     2

4、现在用一个窗体输入“住院病人管理表”中的记录。与“住院科室ID”相关连的为“组合框”控件,它的值来自一个查询,这个查询查出所有的“科室”及科室的ID,结合列为2,列数为2;与“主治医生ID”相关连的控件也是“组合框”,其值来自一个查询,这个查询查出所在与“住院科室ID”相关的医生的姓名及ID,结合列为2,列数为2。在第一次录入值的时候是没有问题的,因为“主治医生ID”的值都是与“住院科室ID”相关的,不会出现住院科室为“内科”而主治医生却是“外科”的医生的问题。但是如果录入了一次这两个值之后,操作人员更改了“住院科室ID”的值,使其变成“外科”,但又忘了更改“主治医生ID”的值,这就产生了一条无效的记录。例如改变了第2条记录的“住院科室ID”的值,使其由“1”(内科)变成“2”(外科),但没有改变“主治医生ID”的值“2”(李明)〈程序不会也不能自动改变这个值,因为这个值是不确定性的;也不能将这个值清空,因为是必填字段,清空这个值将会出错,我现在所能做到的是给操作员一个提醒,提醒其注意更改“主治医生ID”的值,但不能完全避免这样的记录的保存。〉,即:

ID   病人姓名   住院科室ID   主治医生ID
1    陈月明       2                     1
2    何天           2                     2

显然,第2条记录是无效的,因为“2”(李明)并不是科室“2”(外科)的职员。当然,发生这样的因原是操作员的失误,而且发生的可能性也很小,但是,作为一位严谨的数据库开发者,考虑这样的问题也是职责所在,我们应尽可能地保证数据库中的数据是有效的。请问,如何才能更好的避免这样的无效数据的产生呢?解决的办法可能很简单,但是我不知道,请你们详细地告诉我好吗?
作者: gnoy    时间: 2002-10-13 04:30
“但是如果录入了一次这两个值之后,操作人员更改了“住院科室ID”的值,使其变成“外科”,但又忘了更改“主治医生ID”的值”------------〉恕我直言,我的确看得不是太明白。有一点应该清楚再好的软件基本资料都是要人来输的。还有id如你所说操作人员可以更改,不明?----id应该是自动产生的
作者: lgxysl    时间: 2002-10-13 05:44
表的ID是自动生成,但连接的ID(例如“住院科室ID”、“主治医生ID)却是录入的,更确切地说,它们分在“科室表”与“职员表”中是自动生成,并且代表相应表中唯一的一条记录,但是它们在“住院病人管理表”中却是录入的,而且由于实施了参照完整性,只能录入
“科室表”与“职员表”中已自动生成了的ID值。明白吗?话说回头,你说得很对,数据是人录入的,不可避免地会产生错误,但把错误的发生率降到最低,则是做数据库的人的职责。
作者: lgxysl    时间: 2002-10-13 05:58
对于第二个问题,如果不作处理,并不是想象中的那么简单,因为销售的人并不是进货的人,而且对于一个联网的数据库来说,销售的人并不是一个,而且是多个,他们对货物的价格可能一无所知,货物是按照数据库中的“销售价”来售出的,发票也是按照这项数据来计算并打印的,打印发票的销售人员不可能知道所有货物价格的变动,从而也不知道货物的销售价和发票是否正确。如进货的人在录入数据的时候真的出错了,数据库又没有作相应的处理,那么后果将是难能想象的。还是以那个“医院管理系统”为例来详细讨论这个问题吧(为简化,只列相关的重要字段):

1、药品表
ID   品名  购进价  销售价
1   咳必清   5         8
2  病毒灵   0.5       0.7
……

2、药品购进明细(其中“药品ID”与“药品表”中的ID是一对多的关系,实施参照完整性)
ID   药品ID  进货价  进货日期
1   2            0.5             2002-8-1
2   3            7               2002-8-1
3   1            9               2002-8-1
……

3、药品售出明细(其中“药品ID”与“药品表”中的ID是一对多的关系,实施参照完整性;“销售价”通过查询“药品表”得到)
ID  药品ID  销售价  销售量 售出日期
1   2           0.7         5            2002-8-2
2   3           9           2           2002-8-2
3   1          8            3           2002-8-2

很显然,在2002-8-1日购进“1”(咳必清)的时候,药品提价了,这时应该修改“药品表”中的“购进价”,也要修改“销售价”,“购进价”可以写一段代码来自动修改,但销售价则不能,因为其是不确定性的(当然也可以设置一个利润比例来自动修改,但这样太疆化了),必须人工修改,但如果录入人员由于工作上的失误,忘了更新“销售价”,就会出现“上面药品售出明细”中显示的那样,“咳必清”已提价到9元,但销售人员仍按8元的价格售出“咳必清”,这将是医院重大的经济损失。
对于上面这个问题,我现在所能做到的是,(1)在“购进价”改变的时候提示操作员修改“销售价”;(2)在销售时如果发现有某种药品的的“销售价”比“购进价”还小或达不到某一个利润比例,则系统禁止这种药品的售出,但却不能完全禁止这样的无效数据的存在,如何才能做到完全禁止这样的无效的数据的保存呢?请高手指点迷津。

对于第三个问题,还请版主指点一下,详细说说如何用ACCESS禁止这样的问题的出现。谢谢。



[此贴子已经被作者于2002-10-12 21:49:13编辑过]




[此贴子已经被作者于2002-10-12 21:58:19编辑过]


作者: gnoy    时间: 2002-10-13 06:35
我认为你顶多改名称为什么还要改ID呢.
还是先解决容易的吧.第3个问题.你在设计表时设定"付款日期"为必填即可.
其它问题还是传例子解决吧.
作者: huangliu    时间: 2002-10-13 07:16
上述问题与Access没有触发器无关。
数据结构很重要。
例如:引用[在第一次录入值的时候是没有问题的,因为“主治医生ID”的值都是与“住院科室ID”相关的,不会出现住院科室为“内科”而主治医生却是“外科”的医生的问题。但是如果录入了一次这两个值之后,操作人员更改了“住院科室ID”的值,使其变成“外科”,但又忘了更改“主治医生ID”的值,这就产生了一条无效的记录。]
      通常,一个id对应的主要字段是不能(不允许修改)修改。对于某个人,某个事务,它的id是唯一的。如果科室变了名称,就新增加一个科室,然后把数据关联到相应的科室。
原有的科室及其id保留。只是可以停用,在目前的输入界面中不显示。如果原有的科室id在其他表中没有关联记录,可以在整理数据结构时去掉。id资源多着呢,不需要这么节省。

数据都有一个实效性。
例如:[咳必清”已提价到9元,但销售人员仍按8元的价格售出“咳必清”,这将是医院重大的经济损失]
在售出表中,销售价格是要保存的(不允许通过查询药品表得到)。对应每一笔销售,同一种药品都用它当时售出的价格。不然,药品调价后,售出表中的售出价格会有问题。


作者: lgxysl    时间: 2002-10-13 08:08
对呀,就是说是药品调价后要改销售价,不改就会出错,问题是:怎样防止调价了,但是操作员没有正确地改“销售价”。十分正确,数据是有时效性的,换句话说,我所说的正好就是怎样才保证数据有很好的“时效性”。单价是要查药品表得到了,不可能让销售人员去背药品的当前销售价,然后手工输入,现在所说的问题就是要保证他们查到的是很有“时效性”的正确的调价后的价格。
对于ID问题,可能你们还不太明白,一个病人,他要住院,他可能住“外科”,也可能住“内科”,还有可能要转科(这就是改科室的实例),例如“何天”这个病人,他得了“肺炎”,他住在“内科”(也就是说他的“住院科室ID”的值是“1”,“1”是“内科”的ID,它代表“内科”,明白吗?),现在他“肺炎”经检查原来是一个肿瘤引起的,要做“外科”手术切除, 那么他就要转科了,也就是说他的“住院科室ID”的值将改为“2”,“2”是“外科”的ID,“2”就代表“外科”,明白吗?但“住院科室ID”改成“2”之后,操作员没有改“主治医生ID”的值(当然这是操作员的错,一般不会出现这样的错误,但不能排除,例如操作员失恋了,心不在焉,偏偏就忘了),它的值仍是“2”,“2”是“李明”这个医生的ID,“2”就代表“李明”这位医生,从“职员表”可以看出,他是“内科”的医生,这就变成“何天”在“外科”住院,他的主治医生却是一个“内科”的医生,这不乱套了吗??

对于第三个问题,“付款日期”是不能改为必填的,因为在商品售出的时候,对方可能还没有付款(允许说信用的客户延期付款),如果付款日期为必填,则不能保存这条记录。对方还没有付款,付款日期填什么?没法填,但如果它又是必填的,所以记录就不能保存了。过了一些日子,对方付款了,这时付款日期就一定要填的了,但它又不是必填字段,不填也可以,这就有可能出现对方付了款,但付款日期却没有填,当然出现这种情况的可能性也很小,但录入员头晕眼花,也不是没有可能,怎么办???
作者: lgxysl    时间: 2002-10-13 08:14
怎样上传例子?
作者: txman    时间: 2002-10-13 08:28
我大致看了一下,其实你对医院这个的分析不够全面,表不合理。你至少建立5张表
1、病人表 2、住院表 3、科室医生表 4、科室名表 5、医生表。如果要跟踪治疗过程还要建立治疗变动表来记录病人转科和换医生。和住院表相关的是科室医生表
科室医生表包括:主键、科室名ID、医生ID。
另外,进货价和销售价是没有直接关系的,因为肯定有库存,这里有先进先出算法和加权平均算法两种这要根据财务决定预设一个利润因子是横简单的。
作者: gnoy    时间: 2002-10-13 18:44
"对于ID问题,可能你们还不太明白,一个病人,他要住院,他可能住“外科”,也可能住“内科”,还有可能要转科(这就是改科室的实例),例如“何天”这个病人,他得了“肺炎”,他住在“内科”(也就是说他的“住院科室ID”的值是“1”,“1”是“内科”的ID,它代表“内科”,明白吗?),现在他“肺炎”经检查原来是一个肿瘤引起的,要做“外科”手术切除, 那么他就要转科了,也就是说他的“住院科室ID”的值将改为“2”,“2”是“外科”的ID,“2”就代表“外科”,明白吗?但“住院科室ID”改成“2”之后,操作员没有改“主治医生ID”的值(当然这是操作员的错,一般不会出现这样的错误,但不能排除,例如操作员失恋了,心不在焉,偏偏就忘了),它的值仍是“2”,“2”是“李明”这个医生的ID,“2”就代表“李明”这位医生,从“职员表”可以看出,他是“内科”的医生,这就变成“何天”在“外科”住院,他的主治医生却是一个“内科”的医生,这不乱套了吗??"---------------------->所有的人都要你不要修改历史纪录,搞不懂你为什么还是要修改!!!!!你不可以增加吗?????你的思维怎么这么定势!!!!会计为什么会有调帐干嘛不跟你所说的直接改就是了。这才叫乱套嘛
第三个问题程序也是可以控制的嘛。当收款子段变动侯用程序强制收款日期不为空这对你来说很难吗
作者: txman    时间: 2002-10-13 21:05
老兄:你还没有看懂我楼上贴子的意思。我觉得你有一个错误的思维定势--“什么事情都要由数据结合型窗体来解决”。对于要牵涉Access“事务”处理的问题,最好不要把自己解决问题的手段局限于数据结合窗体。
“科室医生表包括”:主键(ID)、科室名ID、医生ID。
“住院表”:主键(ID)、科室医生表ID、病人ID
病人更改科室或更改医生,只变动科室医生表ID,不会有你说的问题。
至于是通过更改原始记录还是增加纪录来实现住院信息的变更,主要考虑数据量的大小和效率。这和酒店系统有点类似,按目前的硬件,当前台数据库大于2G(SYBASE SQL FOR SCO UNIX)就会影响使用。一张表过大了或者无法实现优化查询,查询速度就会慢。过程跟踪本身就是一系列的纪录,加表只不过多了一次修改,但却保存了一份最新的纪录,而且是最小数据量的纪录。当然最后采用那种方式当然由你的系统特点来决定。
    关于销售价问题还是另外讨论吧。

作者: goodidea    时间: 2002-10-13 23:44
文字太多了,飞速跳跃看了一遍,医生一定所在科就定了,在弄个科室字段显然多余,也加大处理难度。
作者: lgxysl    时间: 2002-10-15 15:33
goodidea老兄很有见地,但这样给查找病人带来一定的困难,例如,一个病人要交款,收款的操作员一般问病人:哪一个科,哪一床,他并不是问“哪一个医生治你的”,也不问”你的住院号是多少?”因为一个病人(或家属,大多数情况下是不知道主治医生姓名和自己的住院号的。所以说"科室"这个字段是必要的。
第一、三这两个问题我已经解决,以可以做到如果发现输入有错,无法保存该记录,也无法关闭窗体,强行关闭窗体窗体会自动再打开并回到出错的记录处。
对于第二个问题,当然,用加权平均法加一个利润因数是个好办法(我也是这样想的),但是领导们有领导们的想法,他们不想让数据库自动确定“销售价”,他们可能是有时想用“加权平均法”算, 有时想用“先进先出法”算,有时想用“后进先出法”算,有时用“移动加权平均法”算,反正是领导们说了算,他们定了之后就让操作员输入,我们现在讨论的不是会计问题,也不是领导们的决策问题,而是讨论在“销售价”是人工录入的情况下,怎样尽量防止操作员输入出错的问题。

作者: goodidea    时间: 2002-10-15 16:53
可以由程序找出 哪一个科,哪一床
可以由多名操作员重复输入然后进行比较
作者: zzcjp    时间: 2002-10-30 04:17
对于“科室”-“人员”问题,我采用标准表处理,可以避免重复或遗漏。标准表包含“科室名称”、“人员姓名”、“职务”三个字段。在工作窗口录入时,科室文本控件、人员姓名控件和职务控件设成组合框,组合框的行来源设为标准表的查询,然后在查询的准则中设置约束条件,如果科室名称不是“生产科”,在姓名的下拉列表中就不会出现“黄小二”。当“黄小二”调动科室时必须先修改标准表。这种方法可以补充"有效性规则"的不足,特别是用在输入客户名称时更有效。因为:“广东省建设银行”和“广东建设银行”、“广东建行”都是广东省建设银行,都是计算机就认为是三个单位,数据处理时就要串户了。
作者: zzcjp    时间: 2002-10-30 04:18
对于“科室”-“人员”问题,我采用标准表处理,可以避免重复或遗漏。标准表包含“科室名称”、“人员姓名”、“职务”三个字段。在工作窗口录入时,科室文本控件、人员姓名控件和职务控件设成组合框,组合框的行来源设为标准表的查询,然后在查询的准则中设置约束条件,如果科室名称不是“生产科”,在姓名的下拉列表中就不会出现“黄小二”。当“黄小二”调动科室时必须先修改标准表。这种方法可以补充"有效性规则"的不足,特别是用在输入客户名称时更有效。因为:“广东省建设银行”和“广东建设银行”、“广东建行”都是广东省建设银行,都是计算机就认为是三个单位,数据处理时就要串户了。




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3