触发器更新引发的异常'无法为更新行集定位:一些值可能已在最后读取后改变', 该怎么修改触发...

来源:百度文库 编辑:神马文学网 时间:2024/04/29 07:53:24
有两个表,     报价单,   订单表,     报价单有一个bit字段 <是否接单> 记录本报价单是否接到订单;订单表中有一个字段 <对应报价单号> 记录本订单对应报价单号.  
在删除订单时需要修改对应报价单的是否接单字段.
在订单表中定义如下触发器:
CREATE   TRIGGER   tg_订单_Del   ON   [dbo].[订单]  
for     DELETE  
AS
update   报价表
set   是否接单=0
where   报价单号=
                                    (select   对应报价单号
                    from   deleted)
GO
在订单有报价单对应时运行正常.
但当订单没有对应的报价单时(直接下的订单,或对应报价单已经被删除).   将出现 '无法为更新行集定位:一些值可能已在最后读取后改变 '的异常,   我是使用事务进行更新的.

在问专家上看到的回答是:
由于所修改的记录与数据库所存在的记录冲突,导致更改失败(如其他用户已将记录删除),如果没有触发器,其实程序发生警告信息给Errors集合,但不终止程序运行,也不会出实时错误提示。如果你加上触发器,你所进行批更新包括从Deleted表中记录,即所有删除的记录,所有的更新请求都不存在(或已被其它用户删除),所以出现实时运行错误。

对于我的情况,   select   对应报价单号   from   deleted   将是NULL值,   但这并不影响Update语句的执行啊??

请高手解疑!
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
回复次数:10
  • chd2001
  • (重启失败)
  • 等 级:
#1楼 得分:5回复于:2004-12-24 16:01:22 跟其他字段有关把。
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
精华推荐:关于循环导入excel文件到SQL Server 2005
  • vinsonshen
  • (阿呢陀佛,一切皆空(帐号雪藏))
  • 等 级:
  • 3

#2楼 得分:18回复于:2004-12-24 16:06:11 改成这样试试:
CREATE   TRIGGER   tg_订单_Del   ON   [dbo].[订单]  
for     DELETE  
AS
if   exists   (select   *   from   deleted)
update   报价表
set   是否接单=0
where   报价单号=
                                    (select   对应报价单号
                    from   deleted)
GO
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
精华推荐:三个字段两两相同取的其一
  • Liroyal
  • (胡姬花)
  • 等 级:
#3楼 得分:2回复于:2004-12-24 16:09:06 update   a   set   a.是否接单=0   from   报价表   a,   deleted   b   where   a.报价单号=b.对应报价单号
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
精华推荐:关于left outer join和*=互换的问题
  • 98049522
  • (Napoleon Bonapa)
  • 等 级:
#4楼 得分:0回复于:2004-12-24 19:28:48 这个我当然知道:
update   a   set   a.是否接单=0   from   报价表   a,   deleted   b   where   a.报价单号=b.对应报价单号

在我的应用中使用触发器更好
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
精华推荐:请高手帮写一条SQL语句或存储过程.
  • qiliu
  • (痴心求学)
  • 等 级:
#5楼 得分:5回复于:2004-12-24 19:49:09 由于所修改的记录与数据库所存在的记录冲突,导致更改失败(如其他用户已将记录删除),如果没有触发器,其实程序发生警告信息给Errors集合,但不终止程序运行,也不会出实时错误提示。如果你加上触发器,你所进行批更新包括从Deleted表中记录,即所有删除的记录,所有的更新请求都不存在(或已被其它用户删除),所以出现实时运行错误。

不知道为什么?
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
精华推荐:求SQL语句大全,
  • qiliu
  • (痴心求学)
  • 等 级:
#6楼 得分:0回复于:2004-12-24 19:54:32 但是确实存在,如果同时操作因为不存在产生的这个无法定位的情况。
其他的还不知道;
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
  • lipkissnow
  • (雨水,我在傘中央)
  • 等 级:
#7楼 得分:20回复于:2004-12-24 20:27:49 update   报价表   set   是否接单=0   where   报价单号=         (select   对应报价单号     from   deleted)
就樓主的這條語句來講后面用等號與(select   对应报价单号     from   deleted)相連就不委.因為后面查到的一個集合.改成update   报价表   set   是否接单=0   where   报价单号   in     (select   对应报价单号     from   deleted)好些,當然對一條記錄可以.如果是多條記錄就會產生數據混亂.
至於為什麼會產生樓主所說的問題.樓主為什麼不走另一條路呢.
你有說過訂單有對應報價單時不會錯.那麼我定義一個   變量取得當前訂單的報價單號.不就行了嗎.如下:
CREATE   TRIGGER   tg_订单_Del   ON   [dbo].[订单]  
for     DELETE  
AS
declare   @報價單號       int  

select   @報價單號=報價單號   from   deleted
if   @報價單號   is   not     null   or   @報價單號 <> ' '     --條件根據樓主自行定義

update   报价表   set   是否接单=0   where   报价单号=         (select   对应报价单号     from   deleted)
GO

--上面只是針對單條記錄.如果是多條記錄同時進行.最好還是用游標.    

--以上意見僅供參考
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
  • 98049522
  • (Napoleon Bonapa)
  • 等 级:
#8楼 得分:0回复于:2004-12-25 15:07:00 按照   vinsonshen(猪骨褒咸鱼-> 味道没得顶)   使用的语句:
CREATE   TRIGGER   tg_订单_Del   ON   [dbo].[订单]  
for     DELETE  
AS
if   exists   (select   *   from   deleted)
update   报价表
set   是否接单=0
where   报价单号=
                                    (select   对应报价单号
                    from   deleted)
GO
使用照样出错,   但是如果在if内加上一个select语句便可以了
if   exists   (select   *   from   deleted)
                  select   '执行到这 '
update   报价表
set   是否接单=0
where   报价单号=
                                    (select   对应报价单号
                    from   deleted)
猜想:MSSQL事务检测触发器是否成功执行是根据判断返回值的,   如果没有对应的报价单,那么触发器内的update语句的影响行是0,   而有对应的报价单,   触发器内的update影响行是1.   这就导致了有对应报价单时删除可以成功执行,没有时事务会回滚.
另外   这条语句if   exists   (select   *   from   deleted)   总是为真的.
把它改为:if   exists   (select   对应报价单号   from   deleted)   ,而订单中这个字段为空,但语句结果还是为真,   不知道是为什么?
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
  • 98049522
  • (Napoleon Bonapa)
  • 等 级:
#9楼 得分:0回复于:2004-12-25 15:07:46 lipkissnow(雨水,我在傘中央)     的方法应该是类似的了
  • 对我有用[0]
  • 丢个板砖[0]
  • 引用
  • 举报
  • 管理
  • TOP
  • 98049522
  • (Napoleon Bonapa)
  • 等 级:
#10楼 得分:0回复于:2004-12-27 09:16:54 使用这样的方法解决了:
CREATE   TRIGGER   tg_订单_Del   ON   [dbo].[订单]  
for     DELETE  
AS
    --if   exists   (select   对应报价单号   from   deleted)
    --begin
        select   对应报价单号   from   deleted
        --select   '存在 '
        update   报价表
            set   是否接单=0
        where   报价单号=
                    (select   对应报价单号
                    from   deleted)
    --end