Oracle PL / SQL动态if语句全局变量

时间:2016-09-09 16:37:43

标签: oracle global-variables execute-immediate

我遇到动态sql问题,问题是(我认为)读取和设置全局变量。这里有我所拥有的,非常感谢任何帮助。如果您需要表数据,请告诉我,尽管我已将数据包含在评论中。

 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;

1 个答案:

答案 0 :(得分: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'的字符串;没有机制来评估代表什么。例如,您不能尝试从dual中动态选择,因为rec1不在SQL调用的范围内,甚至是动态的。

绑定该字符串值时,它永远不会为null。您正在使用该字符串,而不是它所代表的外部游标中的值,基本上您不能这样做。

处理此问题的最简单方法是,如果临时表中的列数相当少,可能显示为rec2.data_element值,则使用case表达式来指定适当的实际{{1 {/ 1}}变量的列值,基于 rec1值:

curr_data_element

如果你有很多专栏,你可以通过一个系列来做到这一点,但这可能不值得额外的努力。

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; ... 列的实际值,而不是你正在形成的永远空字符串。