一个购票程序.
需要实现选座功能.
需求为,当用户输入要购买的票数时,
自动为其选出同一排的连位.
如当用户输入5张票.
系统返回1排1-5号座位.
此时要锁定这5个座位,避免被其它人选中.表结构为
排,号,是否被选中.
========================
我想到最傻的办法,是从第一个座位开始判断,如果第一个是空,就锁定.判断第二个.如果不空.解锁前面锁定的.这样直到找到合适的.连位.
但是这样效果太差.而且这个程序是在线使用的.如果用的人多,系统负担会很大.
请教有没有什么高效点的办法.

解决方案 »

  1.   

    表结构为 
    排,号,是否被选中. create table tb (排  int not null, 号 int not null,选中 nvarchar(10),not null, 
    constraint PK primary key clustered (排,号) )
      

  2.   


    create table tb (排  int not null, 号 int not null,选中 nvarchar(10) not null, 
    constraint PK primary key clustered (排,号) )
      

  3.   

    我有个实现的方式,我觉得还是可以的,
    先建立一个存储过程:
    CREATE PROCEDURE searchSeat
    @rowNo int---参数1,表示排号
    @seatNums int---参数2,座位数量
    @offsetSeat int---参数3,最大的被选中的座位号
    AS 
       DECLARE @maxBooked int
       BEGIN
           SELECT @maxBooked=MAX(座位号) FROM (SELECT TOP @ffsetSeat,@seatNums FROM 表 WHERE 排号=@rowNo 
                  AND 选中=是 ORDER BY (座位号) ASC) tmp -----
           IF(@maxBooked=0)---表示有满足数量的连续座位没有被选中。
                    UPDATE 表 SET 选中=是 WHERE 座位号>=@ffsetSeat AND 座位号<@ffsetSeat+@eatNums AND 
                  排号==@rowNo
                  SELECT @maxBooked
           ELSE---表示没有足够数量的连续位子
                   SELECT @maxBooked----把最大的被选中的位子号返回,座位下一轮查询的参数返回。
            END
        END
    下面详细的解释一下:
        三个参数:第一个,表示排号,从一开始;第二个,表示输入的座位数量,假设为5,第三个,表示最大的被选中的座位号,从0开始。
        这样,用户输入5,你就用程序调用存储过程,EXEC searchSeat 1,5,1
        存储过程执行,从第一排开始,从座位号为1开始,去往下数5个,也就是选出1,2,3,4,5这5个座位,从中选出被选中的最大的那个座位号,假如是4,那么存储过程就返回4,你的应用程序就接到4,然后,你就知道,在第一排,4之前是没有满足的了,下一次你的应用程序就调用存储过程EXEC searchSeat 1,5,5;第二个5是4+1得到的,因为4被定了啊、这样你就从5开始再往下数5个,也就是5,6,7,8,9.这样就完成了一个循环。
    如果恰好有满足数量的连续座位,那么存储过程就返回0,并且自动给你锁定了。
    这个思路还行吧。SELECT TOP @ffsetSeat,@seatNums 就是说从@ffsetSeat开始,往下数@seatNums这么多个。不知道这么写对不对。
         
      

  4.   

    不要遍历,能步进就步进,就像SELECT TOP @ffsetSeat,@seatNums 。
      

  5.   


    这不是最傻的方法,这是最好的办法.你可以暂时锁定这五个位子,直到这五个位子被确定,否则解锁这五个位子供其他用户使用.目前的航空和铁路定票就是这么干的.至于如何锁,可以参考下面的方法.1 如何锁一个表的某一行A 连接中执行SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transelect * from tablename with (rowlock) where id=3waitfor delay '00:00:05'commit tranB连接中如果执行update tablename set colname='10' where id=3 --则要等待5秒update tablename set colname='10' where id<>3 --可立即执行2 锁定数据库的一个表SELECT * FROM table WITH (HOLDLOCK) 
    注意: 锁定数据库的一个表的区别SELECT * FROM table WITH (HOLDLOCK) 
    其他事务可以读取表,但不能更新删除SELECT * FROM table WITH (TABLOCKX) 
    其他事务不能读取表,更新和删除
      

  6.   

    表与测试数据:booked=1表示座位被定了
    drop table seatTable
    create table seatTable (id int identity(1,1),rowid int ,seatid int,booked int)
    insert into seatTable values (1,1,0)
    insert into seatTable values (1,2,0)
    insert into seatTable values (1,3,0)
    insert into seatTable values (1,4,0)
    insert into seatTable values (1,5,0)
    insert into seatTable values (1,6,0)
    insert into seatTable values (1,7,0)
    insert into seatTable values (1,8,0)
    insert into seatTable values (1,9,0)
    insert into seatTable values (1,10,0)
    insert into seatTable values (1,11,0)
    insert into seatTable values (1,12,0)
    insert into seatTable values (1,13,0)
    insert into seatTable values (1,14,0)
    insert into seatTable values (1,15,0)
    insert into seatTable values (1,16,0)
    存储过程:
    DROP PROCEDURE searchSeat
    CREATE PROCEDURE searchSeat 
    @rowNos int,---参数1,表示排号 
    @seatNumss int,---参数2,座位数量 
    @offsetSeats int---参数3,最大的被选中的座位号 
    AS 
      DECLARE @sqlQuery VARCHAR(3000)
      BEGIN 
          SET @sqlQuery='SELECT MAX(seatid) FROM ('
          SET @sqlQuery=@sqlQuery+'select top '+str(@seatNumss)
          SET @sqlQuery=@sqlQuery+' * from seatTable where seatid not in ('
          SET @sqlQuery=@sqlQuery+'select top '
          SET @sqlQuery=@sqlQuery+str(@offsetSeats)
          SET @sqlQuery=@sqlQuery+' seatid from seatTable where rowid=1 ORDER BY (seatid) ASC)'
          SET @sqlQuery=@sqlQuery+' ) tmp where booked=1 '
          SET @sqlQuery=@sqlQuery+'IF(0=0) '
          SET @sqlQuery=@sqlQuery+'BEGIN'
          SET @sqlQuery=@sqlQuery+' UPDATE seatTable SET booked=1 WHERE seatid>='
          SET @sqlQuery=@sqlQuery+str(@offsetSeats+1)
          SET @sqlQuery=@sqlQuery+' AND seatid<='
          SET @sqlQuery=@sqlQuery+str(@offsetSeats+@seatNumss)
          SET @sqlQuery=@sqlQuery+'  AND rowid=1 '
          SET @sqlQuery=@sqlQuery+'END'
          EXEC(@sqlQuery)
     END 
    执行:
    exec searchSeat 1,6,10
      

  7.   

    谢谢楼上各位的热心回复.
    kanon_lgt你的方法很好.不过不是太适用于票务,也怪我没有说清情况.dawugui老大的,我还在研究.
    请教一下,如果我同时有100个人在选同一个区域.
    按车票的说话,同时有100个人在选同一列车.
    用这个处理方法.前端是不是会有排队的情况?