日期:2014-05-18  浏览次数:20473 次

请帮解决两个(也是4个)问题,每个100分,谢谢!
SQL code

------------------------
/******
    建表
******/
------------------------
if object_id('p') is not null
drop table p
go
create 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_upd
on p
for update
as
if update(active) and (select count(1) from inserted)>1
begin
    rollback tran;
    raiserror('每次只能更新一条',11,1);
    return;
end
if 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;
end
go
------------------------
/******
    测试数据
******/
------------------------
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)>1
begin
    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                    0
p1                   b                    1
p2                   f                    1

(3 行受影响)

*/
--如果对,要避免的话 把   and isnull(i.active,0)=1;
--去掉,因为一次只能更新一行,那么它跟定的把0的更新成1才会出现两行
--所以你只需要把更新的那一行在更新一遍(更新为0),就行了。

------解决方案--------------------
探讨
可能要求太多了,呵呵,就一个要求吧

模拟出来让两个active同时为一的情况就可以了,另外都不需要回答了,
其他另开帖解决,谢谢!

------解决方案--------------------
1.有主键还能出现两个为1的情况吗?你的隔离级别是默认的吗?
如果是读已提交的话 有可能出问题

2.你的操作是对的啊 先判断一下
------解决方案--------------------
关键是你没有考虑插入情况,触发器如下修改

SQL code
------------------------
/******
    建触发器
******/
------------------------
ALTER trigger p_upd
on p
for update,INSERT
as
if update(active) and (select count(1) from inserted)>1
begin
    rollback tran;
    raiserror('每次只能更新一条',11,1);
    return;
end
if 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;
end
go