关于并发问题的测试
						
				
		
		
				
						
						
				 
		
				
						    在论坛上看到有人讨论并发的这个问题,因为平时主要是处理数据仓库,所以对并发的问题一直没有怎么注意,记录一下:
				
		
		
				
				 
		
				
				 
		
				
						
								--第一段:
						
				
		
		
				create or replace procedure Delete_Pno(v_Pno varchar2) is
  v_state varchar2(20);
begin
  begin
    select state into v_state from P_Table where Pno = v_Pno;
  exception
    when no_data_found then
      dbms_output.put_line('Pno:' || v_Pno || 'not exists.');
      return;
  end;
		
		
				  if v_state = 'N' then
    delete from P_Table where Pno = v_Pno;
    dbms_output.put_line('Pno:' || v_Pno || 'delete success.');
  else
    dbms_output.put_line('Pno:' || v_Pno || 'has been checked.');
  end if;
		
		
				
				
				
						commit;
				
		
		
				
				
				
				
				
						exception
				
		
		
				
				
				
				
				
						  when others then
				
		
		
				
				
				
				
				    rollback;
end;
		
		
				
						
								--
								如果在 select state into v_state 之后,如果发生了状态变化,或者单证删除,都会发生并发性错误。
						
				
		
		
				
						
								--需要在select into 语句后面加上forupdate,这样就可以锁住该信息而防止其被修改或删除。
						
				
		
		
				
						
						
				 
		
				
						
						
				 
		
				
						
								--第二段:
						
				
		
		
				create or replace procedure Delete_Pno(v_Pno varchar2) is
  v_state varchar2(20);
begin
  delete from P_Table
   where Pno = v_Pno
     and state = 'N';
  if sql%rowcount > 0 then
    dbms_output.put_line('Pno:' || v_Pno || 'delete success.');
  else
    begin
      select state into v_state from P_Table where Pno = v_Pno;
    exception
      when no_data_found then
        dbms_output.put_line('Pno:' || v_Pno || 'not exists.');
        return;
    end;
    dbms_output.put_line('Pno:' || v_Pno || 'has been checked.');
  end if;
		
		
				
						
								
								
								
										commit;
								
						
						
								
								
								
								
								
										exception
								
						
						
								
								
								
								
								
										  when others then
								
						
						
								
								
								
								
								
										    rollback;
										
end;
						
				
		 
		
				
						--先删除必然需要删除的,然后再判断是不存在还是无需删除,这样不会出现并发错误。
				
		
		
				
				 
		
				
				 
		
				
						
								--第三段
						
				
		
		
				create or replace procedure Delete_Pno(v_Pno varchar2) is
  v_state varchar2(20);
begin
  delete from P_Table where Pno = v_Pno returning state into v_state;
  if sql%rowcount > 0 then
    if v_state = 'N' then
      dbms_output.put_line('Pno:' || v_Pno || 'delete success.');
    else
      rollback;
      dbms_output.put_line('Pno:' || v_Pno || 'has been checked.');
      return;
    end if;
  else
    dbms_output.put_line('Pno:' || v_Pno || 'not exists.');
  end if;
		
		
				
						
								
								
								
										commit;
								
						
						
								
								
								
								
								
										exception
								
						
						
								
								
								
								
								
										  when others then
								
						
						
								
								
								
								
								
										    rollback;
										
end;
						
				
		 
		
				
						--用returning返回状态,如果状态是'N'则删除,否则回滚,这样也不会有并发的问题。
				
		
		
				
				 
		
				
				 
		
				
						
						
				 
		
				
						    要注意delete from P_Table where Pno = v_Pno returning state into v_state;语句属于OUT BIND
				
		
		
				
						    就好比是update ... set () = (select ...) 一样,语句和自己的子句之间,是不会造成并发的不一致性的。