日期:2014-05-17  浏览次数:20588 次

面试题:考虑并发情况下,轮流指定病人取药的药房窗口的存储过程。
写一个类似发放扑克牌的存储过程,医院药房有6个窗口,病人交费的时候,
轮流指定取药窗口。要考虑并发问题和锁的问题。

表结构如下:

DrugRoomWindow(--表:药房窗口表,用以记录窗口开放状态和被选中状态
WindowID int ,--药房窗口号
WindowName nvarchar(20),--药房窗口名称
,IsActive bit ,--是否开放(高峰期6个窗口都开放,但其它时候可能只开放部分窗口)
IsSelected bit--选中状态
)

=============================================================
我写的存储过程如下,请问对表进行加锁,这样操作对吗?谢谢!
=============================================================

create procedure uspGetNextWindow
as
   select 1 from DrugRoomWindow with(TABLOCKX) --加锁使其它进程不能对表DrugRoomWindow进行读和写

   set @CurrentWindowID=(select top 1 WindowID from DrugRoomWindow where IsSelected=1)--当前排到哪个窗口      
   if @CurrentWindowID is null 
set @CurrentWindowID=1 --解决DrugRoomWindow初使状态所用记录的IsSelected=0的情况      
         
   set @NextWindowID=(select top 1 WindowID from DrugRoomWindow where WindowID>@CurrentWindowID and IsActive=1 
   and IsSelected<>1 order by WindowID)      
         
   if @NextWindowID is null      
   begin        
        --print '没有比它大的窗口,则取比当前窗口号小的最小窗口号'      
set @NextWindowID=(select top 1 WindowID from DrugRoomWindow 
where WindowID<@CurrentWindowID and IsActive=1 and IsSelected<>1 order by WindowID)       
   end           
end      
      
----------2、更新-----
set xact_abort on 
begin trans
update DrugRoomWindow set IsSelected=1 where WindowID=@NextWindowID      
update DrugRoomWindow set IsSelected=0 where WindowID<>@NextWindowID        
commit  
----------3、输出结果           
select * from DrugRoomWindow where WindowID=@NextWindowID--输出  
------解决方案--------------------
上面你已经使用了事务处理,再加上异常处理就可以了
begin try

end try
begin catch


end catch
------解决方案--------------------


--DROP TABLE DrugRoomWindow;
create table DrugRoomWindow(--表:药房窗口表,用以记录窗口开放状态和被选中状态
WindowID int ,--药房窗口号
WindowName nvarchar(20),--药房窗口名称
 IsActive bit ,--是否开放(高峰期6个窗口都开放,但其它时候可能只开放部分窗口)
IsSelected BIT,--选中状态
OrderNum INT, /*优选顺序*/
UseCount INT NOT NULL DEFAULT 0  
)
GO
INSERT INTO [dbo].[DrugRoomWindow] ([WindowID],[WindowName]
,[IsActive],[IsSelected],[OrderNum]) 
SELECT 10,'窗口10',1,0,10 union all
SELECT 20,'窗口20',1,0,20 union all
SELECT 30,'窗口30',1,0,30 union all
SELECT 40,'窗口40',1,0,40 union&