客人表
客人编号 ...
001
002
销售表
客人编号  商品  价格  是否已结帐
001    苹果  10    0(否)
001     梨  10    0(否)
002    香蕉    10       1(是)
要实现下面的功能:
1、可以多人同时向销售表中加记录,即给客人下帐。
2、只可以一个人给该客人结帐,如果没任何人给客人下账和结帐,则:
(1)锁定该客人,此时任何人不可以给该客人下账和进入结帐状态。
(2)查询出该客人消费内容,客人确认了,则可以进行结帐,在此要很长时间。
(3)客人确认后,把是否结帐改为是,客人不确认则返回,解除锁定。
3、如果正在结帐,任何人都不可以向销售表中给该客人下账。
4、如果有人正在给客人下账,则任何人都不可以给客人结帐。
请问还要加什么标志字段或是什么临时表?

解决方案 »

  1.   

    SQL Server锁类型  1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。  2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。  3. PAGLOCK:指定添加页锁(否则通常可能添加表锁)。    4. READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上操作。。    5. READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作。   6. READUNCOMMITTED:等同于NOLOCK。   7. REPEATABLEREAD:设置事务为可重复读隔离性级别。   8. ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。    9. SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。    10. TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。     11. TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。    12. UPDLOCK :指定在读表中数据时设置更新 锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。可以在操作的时候用锁,你参考一下。
      

  2.   

    -->邹建
    设table1(A,B,C)   
      A         B         C   
      a1       b1       c1   
      a2       b2       c2   
      a3       b3       c3   
        
      1)排它锁   
      新建两个连接   
      在第一个连接中执行以下语句   
      begin   tran   
            update   table1   
            set   A='aa'   
            where   B='b2'   
            waitfor   delay   '00:00:30'     --等待30秒   
      commit   tran   
      在第二个连接中执行以下语句   
      begin   tran   
            select   *   from   table1   
            where   B='b2'         
      commit   tran   
        
      若同时执行上述两个语句,则select查询必须等待update执行完毕才能执行即要等待30秒   
        
      2)共享锁   
      在第一个连接中执行以下语句   
      begin   tran   
            select   *   from   table1   holdlock   -holdlock人为加锁   
            where   B='b2'     
            waitfor   delay   '00:00:30'     --等待30秒   
      commit   tran   
        
      在第二个连接中执行以下语句   
      begin   tran   
            select   A,C   from   table1   
            where   B='b2'     
            update   table1   
            set   A='aa'   
            where   B='b2'         
      commit   tran   
        
      若同时执行上述两个语句,则第二个连接中的select查询可以执行   
      而update必须等待第一个连接中的共享锁结束后才能执行   即要等待30秒   
        
      3)死锁   
      增设table2(D,E)   
      D         E   
      d1       e1   
      d2       e2   
      在第一个连接中执行以下语句   
      begin   tran   
            update   table1   
            set   A='aa'   
            where   B='b2'     
            waitfor     delay   '00:00:30'   
            update   table2   
            set   D='d5'   
            where   E='e1'     
      commit   tran   
              
      在第二个连接中执行以下语句   
      begin   tran   
            update   table2   
            set   D='d5'   
            where   E='e1'     
            waitfor     delay   '00:00:10'   
            update   table1   
            set   A='aa'   
            where   B='b2'       
      commit   tran   
        
      同时执行,系统会检测出死锁,并中止进程   
        
        
      --------------------------------------------------------------   
      SET   IMPLICIT_TRANSACTIONS     ON   --用户每次必须显式提交或回滚。否则当用户断开连接时,   
                                                                  --事务及其所包含的所有数据更改将回滚   
        
      SET   IMPLICIT_TRANSACTIONS     OFF   --自动提交模式。在自动提交模式下,如果各个语句成功   
                                                                    --完成则提交。   
    --锁定记录,只允许单用户修改的例子:   
        
      --创建测试环境   
      --创建测试表--部门表   
      create   table   部门(departmentid   int,name   varchar(10))   
        
      --记录锁定表   
      create   table   lock(departmentid   int,dt   datetime)   
        
      go   
      --因为函数中不可以用getdate,所以用个视图,得到当前时间   
      create   view   v_getdate   as   select   dt=getdate()   
      go   
      --创建自定义函数,判断记录是否锁定   
      create   function   f_chk(@departmentid   int)   
      returns   bit   
      as   
      begin   
      declare   @re   bit,@dt   datetime   
      select   @dt=dt   from   v_getdate   
      if   exists(select   1   from   lock   where   departmentid=@departmentid   
      and   datediff(ss,dt,@dt)<5)   
      set   @re=1   
      else   
      set   @re=0   
      return(@re)   
      end   
      go   
        
      --数据处理测试   
      if   dbo.f_chk(3)=1   
      print   '记录被锁定'   
      else   
      begin   
      begin   tran   
      insert   into   lock   values(3,getdate())   
      update   部门   set   name='A'   where   departmentid=3   
      delete   from   lock   where   departmentid=3   
      commit   tran   
      end   
        
      --删除测试环境   
      drop   table   部门   
      drop   view   v_getdate   
      drop   function   f_chk