三层结构采用ADO遇到的关于日期时间类型默认值的问题?(50分)

  • 主题发起人 主题发起人 doggo
  • 开始时间 开始时间
D

doggo

Unregistered / Unconfirmed
GUEST, unregistred user!
问题的环境:
三层结构,
中间层为ActiveX Library + Transactional Object(Requires a transaction),
通过DCOM连接,访问数据库的接口为ADO 2.5,后台数据库为sql server 7.0。
ADO采用Microsoft OLE DB Provider for ODBC Drivers。


问题:
数据库中有一个表A,表中又一个字段FModifyDT为DateTime类型,创建表时对该字段
指定默认值为CURRENT_TIMESTAMP(也就是getdate()),在客户端添加一条记录一切正常,
随后对该记录随意进行修改,然后用ApplyUpdates(0)进行保存时报错,出错信息为“键列
信息不足,操作影响到多行”。即便重新启动客户端应用程序对于这条记录进行修改,
都会报错。后来发现只要通过sql server的Enterprise Manager对于FModifyDT的值随便
修改一下(例如简单的修改一下秒,数值不变都可以,只要执行一次存盘操作)保存后再
通过客户端应用程序进行修改就一切正常了。另外在增加新记录时给FModifyDT指定一个值
也不会出问题。
经过试验在两层的C/S结构中不会出现类似的问题。
 
对于这个问题,大致分析如下:
SQL Server的表,需要一个列作为键列,用于确定行的唯一性。
如果是在sql server中编辑,其时间是毫秒级的,所以行值重复的可能性几乎为零。通过程序就不一样了,可能只精确到了秒。
这样会造成多行的值相同。SQL SERVER是把数据当作一个整体来处理的,所以这一个update操作会影响所有与输入时间相同的列,默认情况下会报错。

你可以通过添加一个identity性质的id列来解决唯一性的问题
 
十分抱歉出错信息写错了,应该是“该记录已经被其他用户修改”。
我目前也的确是用一个identity来做唯一性标识。我也怀疑是否是因为通过getdate()得到
的时间实际上达到毫秒级,但客户端只能表示到秒而造成数据不同似的Delphi认为数具被
修改过了,而报错。但是应该如何避免这用情况?
 
你可以格式化一下时间,使之具有相同的精度。或者不使用sql的时间默认值,改为全部由Delphi写入,这样就能防止精度的不同造成的麻烦。
 
我解决了,果然是因为sql server中datetime类型可以保存到毫秒的原因。
在客户端由于只能够显示处理到秒,所以会自动把毫秒的数据切除,但在执行update
或delete操作时由于没有了毫秒数据而使得字段比较是找不到相对应的记录,因此会
报“记录已经被其他用户修改的错”。
目前我的解决的方法有两个:
1.选择updatemode为upWhereKeyOnly,这样就不会比较datetime字段的数据了。不过
有的时候不能够满足要求。
2.如果时间要求的精度不是特别高的话可以在服务器端生成默认日期时强制把毫秒数
据去掉。例如我现在在生成datetime的默认值时不再直接用getdate(),而换成
dateadd(ms,-DATEPART(ms,getdate()),getdate())。(不知道是否有更好的方法)
至于采用哪种方式就看你的情况和喜好了。

 
后退
顶部