| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5226 人关注过本帖
标题:求助:无法为更新定位行。一些值可能已在最后一次读取后已更改
只看楼主 加入收藏
boneden
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2013-9-25
结帖率:0
收藏
已结贴  问题点数:20 回复次数:8 
求助:无法为更新定位行。一些值可能已在最后一次读取后已更改
软件系统:中软酒店管理系统
数据库:SQL 2005 SP2

原因:
    account表添加update触发器后,对预定客房进行开房时出现“ 无法为更新定位行。一些值可能已在最后一次读取后已更改”,“存盘失败,请检查输入项目”。


  触发器代码:


    ALTER TRIGGER [dbo].[updateHTVC] ON [dbo].[account] FOR  UPDATE  
    AS
     if Update(acct_stus)
       Begin
         Declare @SN as varchar(50)
         Declare @State as char(1)
         Select @State=acct_stus From inserted
         Select @SN=acct_num From deleted
         Update HTVC Set HTVC.state=@State  Where HTVC.SN=@SN
        End

    其中HTVC表为新建表(存在于中软数据库中,但不是自带表,是另外新建的一张表格)

    现确定为该触发器的Update引起,因为单独把该条语句删除不会报错。

    HTVC表结构为:

    CREATE TABLE [dbo].[HTVC](

[SN] [char](9) NOT NULL,

[CustomerName] [varchar](60) NOT NULL,

[Sex] [char](2) NULL,

[CertificateNo] [varchar](40) NULL,

[TelphoneNo] [varchar](40) NULL,

[State] [char](1) NOT NULL,

[isCreate] [bit] NOT NULL CONSTRAINT [DF_HTVC_isCreate]  DEFAULT ((0))
     ) ON [PRIMARY]


    该表无主键,但有尝试将SN字段设为主键,仍然报错。


    请大虾们帮忙看看,非常感谢!!

[ 本帖最后由 boneden 于 2013-9-25 21:09 编辑 ]
搜索更多相关主题的帖子: 触发器 数据库 update account 酒店管理 
2013-09-25 21:08
303770957
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:838
专家分:2125
注 册:2005-9-10
收藏
得分:20 
我看了下你贴的代码,你的触发器代码没有问题,唯一不足的一点就是字段SN的数据类型和数据长度不一样,我建议最好是HTVC表中的SN和account表中的还有触发器中定义的SN变量的数据类型和数据长度保持一致。另外,我觉得出现“无法为更新定位行。一些值可能已在最后一次读取后已更改”的最可能原因是HTVC表没有主键,导致HTVC表中有重复的数据。不过,这样的提示信息我觉得不应该是sql server给出的。如果我没有错的话应该是软件给出的错误提示信息,这个信息并不直接来自于数据库。要是你的软件是用Delphi言语写的话,那么在使用ADOQuery对数据进行修改保存,在修改保存了第一次以后,如果再次进行修改保存,就会遇到“无法为更新定位行,一些值可能已在最后一次读取后已更改”的问题。

原因有这样几种:
1.在数据库设计时,为某些字段设置了默认值,在修改进行提交以后,数据库会自动修改对应字段的所有行的默认值,从而导致了数据库与数据集中数据的不一致,使ADOQuery无法对数据集进行定位。(这种情况很可能发生,因为你用了触发器修改了HTVC表中的数据。)
2.数据库对应的表没有主键,输入了重复的数据以后,数据库里有两条一样的数据,从而使ADOQuery无法对数据进行定位。
(这种情况也存在,因为你的HTVC表没有主键)

解决方法:
1.修改数据库设计,不再设置默认值,为数据库表定义主键,保证其唯一性。
2.在执行完ADOQuery.Post之后,执行ADOQuery.Refresh,对于设置默认值的情况可以解决。
具体原因还是要看你的代码了,因为你现在给的信息太少,我这里无法精确判断,只能给你点建议了。


♂ 死后定当长眠,生前何须久睡。♀
2013-09-26 09:33
boneden
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2013-9-25
收藏
得分:0 
回复 2楼 303770957
你给出的建议非常有参考意义!!

我再补充一些问题的细节:

    account表是中软酒店管理系统使用的数据表。
    HTVC表是另外搞的一个软件(C#写的)要用到的数据表。
    也就是说HTVC表中软系统根本不会去用,而出现问题是在操作中软系统的时候发生的。既然中软系统不会用到HTVC表,那就应该不是ADOQuery的问题了。

    HTVC表由account表的两个触发器(insert和update)和C#写的软件在维护。(注:C#写的软件没有运行,直接操作中软系统时就出现这个问题了)

    HTVC表的内容来自于account表的一个insert触发器生成的,这个触发器的代码如下:

        ALTER TRIGGER [dbo].[insertHTVC] ON [dbo].[account]
        FOR INSERT
         AS
          declare @SN as char(9)
          declare @CustomerName as varchar(40)
          declare @Sex as char(2)
          declare @CertificateNo as varchar(40)
          declare @TelphoneNo as varchar(40)
          select @SN=acct_num,@CustomerName=acct_nm,@Sex=sex_cd,@CertificateNo=crtf_num,@TelphoneNo=phone From inserted
          insert into HTVC (SN,CustomerName,Sex,CertificateNo,TelphoneNo) values(@SN,@CustomerName,@Sex,@CertificateNo,@TelphoneNo)
2013-09-26 19:39
boneden
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2013-9-25
收藏
得分:0 
其实account表有三个触发器SWcswebatg(中软自带的)、insertHTVC(另行增加的)、updateHTVC(另行增加的)

SWcswebatg
ALTER TRIGGER [dbo].[SWcswebatg] ON [dbo].[account] FOR UPDATE AS

BEGIN
      declare @acct_num char(9)
   
    if update(sw_update_flg) or update(sw_update_tm) --or update(confirm_flg)
        return

    declare stuscursor cursor for select i.acct_num from inserted i
        join deleted d on d.acct_num=i.acct_num
        and (d.acct_stus<>i.acct_stus) where i.csweb_flg='3' and i.acct_stus in ('0','4')
    open stuscursor

    fetch next from stuscursor into @acct_num
    while (@@FETCH_STATUS = 0)
    begin
        update account set confirm_flg = '2', sw_update_flg = '1', sw_update_tm = getdate() where csweb_flg = '3' and acct_num=@acct_num

        fetch next from stuscursor into @acct_num
    end

    close stuscursor
    deallocate stuscursor


    declare acctcursor cursor for select i.acct_num from inserted i
        join deleted d on d.acct_num=i.acct_num
        and (d.acct_stus<>i.acct_stus or d.acct_nm<>i.acct_nm or d.arr_dt<>i.arr_dt or d.dpt_dt<>i.dpt_dt
        or d.rm_typ<>i.rm_typ or d.rm_num<>i.rm_num or d.crtf_num<>i.crtf_num or d.confirm_flg<>i.confirm_flg
        or d.chkin_dt<>i.chkin_dt or d.chko_dt<>i.chko_dt) where i.csweb_flg='3'
    open acctcursor

    fetch next from acctcursor into @acct_num
    while (@@FETCH_STATUS = 0)
    begin
        update account set sw_update_flg = '1', sw_update_tm = getdate() where csweb_flg = '3' and acct_num=@acct_num

        fetch next from acctcursor into @acct_num
    end

    close acctcursor
    deallocate acctcursor
END


insertHTVC
ALTER TRIGGER [dbo].[insertHTVC] ON [dbo].[account]
FOR INSERT
AS
declare @SN as char(9)
declare @CustomerName as varchar(40)
declare @Sex as char(2)
declare @CertificateNo as varchar(40)
declare @TelphoneNo as varchar(40)
select @SN=acct_num,@CustomerName=acct_nm,@Sex=sex_cd,@CertificateNo=crtf_num,@TelphoneNo=phone From inserted
insert into HTVC (SN,CustomerName,Sex,CertificateNo,TelphoneNo) values(@SN,@CustomerName,@Sex,@CertificateNo,@TelphoneNo)


updateHTVC
ALTER TRIGGER [dbo].[updateHTVC] ON [dbo].[account]
FOR   UPDATE  
AS
if Update(acct_stus)
   Begin
      Declare @SN as varchar(50)
      Declare @State as char(1)
      Select @State=acct_stus From inserted
      Select @SN=acct_num From deleted
      Update HTVC Set HTVC.state=@State  Where HTVC.SN=@SN
   End
2013-09-26 19:50
303770957
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:838
专家分:2125
注 册:2005-9-10
收藏
得分:0 
你将你填加的触发器删除,将你要实现的功能写在中软系统的update的触发器中,insert触发器保留,我怀疑这两个触发器冲突了。我现在在长途车上有手机给你发贴不太方便,你先按我说的试试,不行明天再帮你看看。

♂ 死后定当长眠,生前何须久睡。♀
2013-09-26 20:08
boneden
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2013-9-25
收藏
得分:0 
回复 5楼 303770957
太感谢您了!!!!

这个方案我有试过,我用了3种方法:

  第1种:关闭SQL 2005 允许触发器激发其他触发器。
 
  第2种:在系统存储过程中设置updateHTVC触发器优先执行。

  第3种:删除updateHTVC触发器,将updateHTVC触发器的代码复制到SWcswebatg触发器中(试过,1、复制到最前面;2、复制到最后面)
2013-09-26 20:17
boneden
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2013-9-25
收藏
得分:0 
回复 5楼 303770957
“据我推测,你的HTVC表可能是另一个触发器产生的,而HTVC表的最后一个字段使用了DEFAULT约束,会导致新行(新的记录)在保存时被重新刷新,所以就造成你的update语句实际上不能定位到HTVC表的最新的那条记录行。”

   这是另一个网友回复的,你的意见呢?
2013-09-26 20:19
303770957
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:838
专家分:2125
注 册:2005-9-10
收藏
得分:0 
嗯,这个网友说得非常有道理,你把默认值去掉看看,这也是我在第一个帖子中提到的默认值得问题。

♂ 死后定当长眠,生前何须久睡。♀
2013-09-26 20:27
boneden
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2013-9-25
收藏
得分:0 
回复 8楼 303770957
恩,这个问题要过几天才有空测试,到时把结果向您汇报。

让您劳心了,祝您一路顺风!

非常谢谢!
2013-09-26 20:34
快速回复:求助:无法为更新定位行。一些值可能已在最后一次读取后已更改
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015850 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved