是否可以使用表变量重写此过程

时间:2010-10-27 07:39:27

标签: sql oracle

我有一个使用na光标的简单删除程序。我在某处读过,表格变量应该优先于游标。

CREATE OR REPLACE PROCEDURE SMTAPP.LF_PLAN_VYMAZ (Str_oz varchar2, Num_rok number, Num_mesiac number, Str_s_trc_id varchar2) IS
    var_LF_PLAN_ID Number(20);
    cursor cur_plan is select id from lp_plan where lf_plan_id=var_LF_PLAN_ID;
BEGIN
   select ID into var_LF_PLAN_ID from lf_plan where oz=Str_oz and rok=Num_rok and mesiac=Num_mesiac and s_trc_id=Str_s_trc_id;
   for c1 in cur_plan loop
        delete from LP_PLAN_DEN where lp_plan_id=c1.id;
   end loop;
   delete from LP_PLAN where lf_plan_id=var_LF_PLAN_ID;
   delete from LP_PLAN_HIST where LF_PLAN_ID=var_LF_PLAN_ID;
   delete from LF_PLAN where id=var_LF_PLAN_ID;
END;

2 个答案:

答案 0 :(得分:2)

我不知道“table var”是什么(我觉得它是一个SQL Server术语?)但我不会在这里使用游标,我会这样做:

CREATE OR REPLACE PROCEDURE SMTAPP.LF_PLAN_VYMAZ 
   (Str_oz varchar2, Num_rok number, Num_mesiac number, Str_s_trc_id varchar2)
IS
    var_LF_PLAN_ID Number(20);
BEGIN
   select ID into var_LF_PLAN_ID
   from lf_plan
   where oz=Str_oz and rok=Num_rok and mesiac=Num_mesiac
   and s_trc_id=Str_s_trc_id;

   delete from LP_PLAN_DEN where lp_plan_id in 
      (select id from lp_plan where lf_plan_id=var_LF_PLAN_ID);
   delete from LP_PLAN where lf_plan_id=var_LF_PLAN_ID;
   delete from LP_PLAN_HIST where LF_PLAN_ID=var_LF_PLAN_ID;
   delete from LF_PLAN where id=var_LF_PLAN_ID;
END;

编辑:“表格变量”确实是SQL Server concept

我会按照上面的说明对此进行编码,但是由于您特别希望了解如何使用集合执行此操作,因此以下是另一种使用集合的方法:

CREATE OR REPLACE PROCEDURE SMTAPP.LF_PLAN_VYMAZ 
   (Str_oz varchar2, Num_rok number, Num_mesiac number, Str_s_trc_id varchar2)
IS
    var_LF_PLAN_ID Number(20);
    TYPE id_table IS TABLE OF lp_plan.id%TYPE;
    var_ids id_table_type;
BEGIN
   select ID into var_LF_PLAN_ID
   from lf_plan
   where oz=Str_oz and rok=Num_rok and mesiac=Num_mesiac
   and s_trc_id=Str_s_trc_id;

   select id from lp_plan 
   bulk collect into var_ids
   where lf_plan_id=var_LF_PLAN_ID;

   forall i in var_ids.FIRST..var_ids.LAST
     delete from LP_PLAN_DEN where lp_plan_id = var_ids(i);

   delete from LP_PLAN where lf_plan_id=var_LF_PLAN_ID;
   delete from LP_PLAN_HIST where LF_PLAN_ID=var_LF_PLAN_ID;
   delete from LF_PLAN where id=var_LF_PLAN_ID;
END;

这可能不如前一种方法那样好。

答案 1 :(得分:0)

也许与问题的关键点没有直接关系,但是......

在大多数情况下,托尼建议我这样做;但如果我发现自己处于需要光标版本的情况下,那么可以根据每个已删除的行进行其他处理,我会使用FOR UPDATEWHERE CURRENT OF功能:

CREATE OR REPLACE PROCEDURE SMTAPP.LF_PLAN_VYMAZ (Str_oz varchar2, Num_rok number,
    Num_mesiac number, Str_s_trc_id varchar2)
IS
    var_LF_PLAN_ID Number(20);
    cursor cur_plan is
        select id from lp_plan where lf_plan_id=var_LF_PLAN_ID for update;
BEGIN
    select ID into var_LF_PLAN_ID
    from lf_plan
    where oz=Str_oz and rok=Num_rok and mesiac=Num_mesiac and s_trc_id=Str_s_trc_id;

    for c1 in cur_plan loop
        delete from LP_PLAN_DEN where current of cur_plan;
    end loop;

    delete from LP_PLAN where lf_plan_id=var_LF_PLAN_ID;
    delete from LP_PLAN_HIST where LF_PLAN_ID=var_LF_PLAN_ID;
    delete from LF_PLAN where id=var_LF_PLAN_ID;
END;

这会锁定你感兴趣的行,并且可以使删除的意图更清晰。