Decode360's Blog

业精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

  BlogJava :: 首页 :: 新随笔 :: 联系 ::  :: 管理 ::
  302 随笔 :: 26 文章 :: 82 评论 :: 0 Trackbacks
    在论坛上看到有人讨论并发的这个问题,因为平时主要是处理数据仓库,所以对并发的问题一直没有怎么注意,记录一下:
 
 
--第一段:
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 ...) 一样,语句和自己的子句之间,是不会造成并发的不一致性的。
 




-The End-

posted on 2009-01-30 22:22 decode360-3 阅读(160) 评论(0)  编辑  收藏 所属分类: SQL Dev

只有注册用户登录后才能发表评论。


网站导航: