- SQL code
------------------------/****** 建表******/------------------------if object_id('p') is not nulldrop table pgocreate table p(name nvarchar(20) not null,ver nvarchar(20) not null,active bit null,constraint [pk_p] primary key(name,ver))go------------------------/****** 建触发器******/------------------------create trigger p_updon pfor updateasif update(active) and (select count(1) from inserted)>1begin rollback tran; raiserror('每次只能更新一条',11,1); return;endif update(active)begin update p set active=0 from inserted i where i.name=p.name and i.ver<>p.ver and isnull(i.active,0)=1;endgo------------------------/****** 测试数据******/------------------------insert into p values('p1','a',0);insert into p values('p1','b',1);insert into p values('p1','c',0);go------------------------
要求:
1.如何更新,让两条数据的active同时为1,并如何可避免这种问题发生???
2.如果去掉此句,让两条数据的active同时为1,并如何可避免这种问题发生???
前提:请不要禁用此触发器
- SQL code
if update(active) and (select count(1) from inserted)>1begin rollback tran; raiserror('每次只能更新一条',11,1); return;end
------解决方案--------------------
- SQL code
第一个问题update p set name='p2',ver='f',active=1 where name='p1' and ver='c'select * from p--下面这样的算不算?/*name ver active-------------------- -------------------- ------p1 a 0p1 b 1p2 f 1(3 行受影响)*/--如果对,要避免的话 把 and isnull(i.active,0)=1;--去掉,因为一次只能更新一行,那么它跟定的把0的更新成1才会出现两行--所以你只需要把更新的那一行在更新一遍(更新为0),就行了。
------解决方案--------------------
------解决方案--------------------
1.有主键还能出现两个为1的情况吗?你的隔离级别是默认的吗?
如果是读已提交的话 有可能出问题
2.你的操作是对的啊 先判断一下
------解决方案--------------------
关键是你没有考虑插入情况,触发器如下修改
- SQL code
------------------------/****** 建触发器******/------------------------ALTER trigger p_updon pfor update,INSERTasif update(active) and (select count(1) from inserted)>1begin rollback tran; raiserror('每次只能更新一条',11,1); return;endif update(active)begin update p set active=0 from inserted i where i.name=p.name and i.ver<>p.ver and isnull(i.active,0)=1;endgo