3

PL/SQLでデータ変換/処理を行っていますが、パッケージから重複コードを排除したいと考えています。これは関連するコード部分です。

表関数の入力タイプ:

type t_legs_cur is ref cursor return legs%rowtype;  

1 つのレコードを処理する手順:

procedure discontinuity_rule(p_leg in out nocopy legs%rowtype) as
begin
  null; --business logic here
end discontinuity_rule;

カーソルを反復処理し、カーソル内の各行を処理し、出力 (存在する場合) をパイプ処理する表関数:

function apply_discontinuity_rule(p_cur t_legs_cur)
  return t_legs pipelined
  order p_cur by (/* some fields */)    
  parallel_enable (partition p_cur by range (/* some fields */))
as
  v_leg legs%rowtype;
begin
  loop
    fetch p_cur into v_leg;
    exit when p_cur%notfound;

    discontinuity_rule(v_leg); --call back

    if v_leg.id is not null then
      pipe row (v_leg);
    end if;

  end loop;
end apply_discontinuity_rule;

変換/処理にはいくつかのステップがあります。たとえば、次の選択を実行して、いくつかの処理を行い、特定の順序でいくつかのルールを適用します。

select * from table(trip_rules.generate_trips_from_legs(cursor(
  select * from table(trip_rules.apply_5_legs_rule(cursor(
    select * from table (trip_rules.apply_previous_city_rule(cursor(
      select * from table (trip_rules.apply_backhaul_rule(cursor(
        select * from table(trip_rules.apply_connection_time_rule(cursor(
          select * from table(trip_rules.apply_discontinuity_rule(cursor(
            select * from table(trip_rules.generate_legs_from_input(cursor(
              select * from INPUT_DATA
            )))
          )))
        )))
      )))
    )))
  )))
)));

これはすべてうまくいきますが、唯一の問題は、私の trip_rule パッケージに多くのapply_*_rule関数が含まれていることです。それらはすべて例に似ていますapply_discontinuity_rulediscontinuity_rule唯一の違いは、コールバックする実際のプロシージャ ( ) です。

だから、私の質問は、どうすればapply_*関数のコードをコピーするのを避けることができるかということです. これを行うためのよりエレガントな方法はありますか?大きなifを使用します:if p_rule_name == 'discontinuity_rule' then

function apply_rule(p_cur t_legs_cur, p_rule_name in varchar2)
  return t_legs pipelined
  order p_cur by (/* some fields */)    
  parallel_enable (partition p_cur by range (/* some fields */))
as
  v_leg legs%rowtype;
begin
  loop
    fetch p_cur into v_leg;
    exit when p_cur%notfound;

    if p_rule_name == 'discontinuity_rule' then
      discontinuity_rule(v_leg);
    elsif p_rule_name == 'other_rule' then
      other_rule(v_leg);
    elsif p_rule_name == 'totally_other_rule' then
      totally_other_rule(v_leg);
    -- and so on...
    end if;

    if v_leg.id is not null then
      pipe row (v_leg);
    end if;

  end loop;
end apply_rule;

また、プロシージャ名を使用して匿名の PL/SQL ブロックをオンザフライで作成し、動的 ​​SQL として実行できることも理解しています。自分のパフォーマンスを犠牲にせずに、ちゃんとできるだろうか。どんなアイデアでも大歓迎です。

4

1 に答える 1

4

巨大な IF ステートメントは重複コードではありません。

確かに似ている部分はあるのですが、これは……

elsif p_rule_name == 'other_rule' then
    other_rule(v_leg);

...これとまったく同じではありません...

elsif p_rule_name == 'totally_other_rule' then
    totally_other_rule(v_leg); 

動的 PL/SQL は、本当に代替手段がない場合を除き、避けるべきものです。ここではその必要はありません。

于 2012-10-19T13:01:00.833 に答える