面试题:考虑并发情况下,轮流指定病人取药的药房窗口的存储过程。
写一个类似发放扑克牌的存储过程,医院药房有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&