2016-09-09 24 views
-1

動的SQLに問題があります。問題はグローバル変数を読み込んで設定しています。ここに私が持っているものがあり、どんな助けも非常に高く評価されます。コメントにデータを含めても、テーブルデータが必要な場合はお知らせください。Oracle PL/SQLの動的if文グローバル変数

CREATE OR REPLACE PACKAGE data_load 
    IS 
     curr_rec   NUMBER; 
     curr_rule   VARCHAR2(200); 
     curr_sql   VARCHAR2(4000); 
     curr_sql_two  VARCHAR2(4000); 
     curr_data_element VARCHAR2 (200); 
     curr_rule_text VARCHAR2(200); 
     curr_error_code VARCHAR2(10); 
     curr_error_flag VARCHAR2(10); 
     curr_flag_val  NUMBER; 
     v_check   NUMBER; 
     v_ID    NUMBER; 
     cur_hdl   INT ; 
     rows_processed NUMBER; 
     PROCEDURE check_rules; 
    END data_load; 

パッケージ本体:

create or replace PACKAGE BODY data_load IS 
     PROCEDURE check_rules IS 
     CURSOR c1 
     IS 
      SELECT * FROM STAGING_TABLE where rownum < 3; 
     CURSOR c2 
     IS 
      SELECT * FROM ERROR_CODES WHERE rule_text IS NOT NULL AND status =1; 
     BEGIN 
     FOR rec1 IN c1 
     LOOP 
      FOR rec2 IN c2 
      LOOP 
      curr_data_element := 'rec1.'||rec2.data_element; --- this results in value "rec1.SHIP_FROM_ACCOUNT_ORG_CODE" without quotes 
      curr_rule_text := rec2.rule_text; --- this value is "is not null" without quotes 
      curr_error_flag := rec2.error_flag; --this value is "FLAG_03" without quotes 
      curr_flag_val  := to_number(rec2.error_code); --- this value is 31 
      curr_sql :='begin if :curr_data_element '||curr_rule_text||' then update table_with_column_FLAG_03 set '||curr_error_flag ||' = 0; else update table_with_column_FLAG_03 set '||curr_error_flag ||' = '||curr_flag_val||'; end if; end;'; 
      dbms_output.put_line(curr_sql); -- results in "begin if :curr_data_element is null then update table_with_column_FLAG_03 set FLAG_03 = 0; else update table_with_column_FLAG_03 set FLAG_03 = 31; end if; end;" 
      EXECUTE IMMEDIATE curr_sql USING curr_data_element ; -- this always updates the column with 31 even when curr_data_element/ rec1.SHIP_FROM_ACCOUNT_ORG_CODE is null and that's the problem 
      COMMIT; 
      END LOOP; 
      curr_rec := curr_rec+1; 
     END LOOP; 
     dbms_output.put_line(curr_rec); 
     END check_rules; 
    END data_load; 
+0

WATS問題...ポストテーブルのDDLだけでなく – XING

+0

ポストテーブルのDDLだけでなく – Abhijeet

+0

私は広告テーブルのDDLがしますが、問題のコード内 –

答えて

1

あなたはすでに本当に問題を強調しました:

curr_data_element := 'rec1.'||rec2.data_element; --- this results in value "rec1.SHIP_FROM_ACCOUNT_ORG_CODE" without quotes 

あなたは動的カーソルの列を参照することはできません。値'rec1.SHIP_FROM_ACCOUNT_ORG_CODE'の文字列を作成しています。それが表すものを評価する仕組みはありません。たとえば、rec1がSQLコールのスコープ内にない場合でも、動的に選択することはできません。

この文字列値をバインドすると、決してnullになることはありません。その文字列を使用していますが、それが表す外部カーソルの値ではなく、本質的にその文字列を使用することはできません。あなたはrec2.data_element値として表示される場合がありますステージング表の列の合理的に数が少ない場合

これに対処するための最も簡単な方法は、curr_data_elementに適切な実際のrec1列値を割り当てるためにcase式を使用することです変数、rec2.data_element値に基づいて:あなたは列の多くを持っている場合

... 
    BEGIN 
    FOR rec1 IN c1 
    LOOP 
     FOR rec2 IN c2 
     LOOP 
     curr_data_element := 
      case rec2.data_element 
      when 'SHIP_FROM_ACCOUNT_ORG_CODE' then rec1.SHIP_FROM_ACCOUNT_ORG_CODE 
      when 'ANOTHER_COLUMN' then rec1.ANOTHER_COLUMN 
      -- when ... -- repeat for all possible columns 
      end;    
     curr_rule_text := rec2.rule_text; 
... 

あなたは潜在的にコレクションを経由してそれを行うことができますが、それは余分な労力価値がないかもしれません。

curr_sqlの文字列は同じままです。変更しているのは、あなたが形成していたヌル文字列ではなく、rec1列の実際の値をバインドしていることだけです。

+0

おかげでアレックスを私のコメントを参照してください、私はグローバル変数ができることをどこかで読んでいましたどのように私がそれを達成するかもしれないかについて意見がありますか? –

+0

@ oracle_of - グローバル変数(ただしローカル変数)の変数 'curr_data_element'は、あなたが示したように参照することができ、バインド変数を使用します。その部分はOKです。問題は、その変数に含まれるものです。基本的に別のPL/SQL変数へのポインタである変数は使用できません。 PL/SQL変数名を含む文字列を評価するメカニズムはありません。 –