-1

我在使用动态 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;
4

1 回答 1

1

您已经真正强调了这个问题:

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

您不能动态引用游标列。您正在创建一个带有 value 的字符串'rec1.SHIP_FROM_ACCOUNT_ORG_CODE';没有机制来评估它代表什么。例如,您不能尝试从 dual 中动态选择它,因为rec1它不在 SQL 调用的范围内,即使是动态的。

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

处理此问题的最简单方法是,如果临时表中有相当少量的列可能显示为rec2.data_element值,则使用 case 表达式根据值将适当的实际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;
...

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

curr_sql字符串保持不变,所有改变的是您正在绑定相关列中的实际值,rec1而不是您正在形成的永不空字符串。

于 2016-09-09T17:09:57.127 回答