2016-09-09 2 views
-1

У меня возникают проблемы с динамическим sql, проблема - это (я думаю) чтение и настройка глобальной переменной. Вот то, что у меня есть, и любая помощь вообще очень ценится. Пожалуйста, дайте мне знать, если вам нужны данные таблицы, хотя я включил данные в комментарии.Oracle PL/SQL dynamic if statement global vars

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'; нет механизма для оценки того, что это представляет. Вы не можете, например, попытаться динамически выбрать это из dual, потому что rec1 не имеет возможности для SQL-вызова даже динамически.

Когда вы связываете это строковое значение, оно никогда не будет равно null. Вы используете эту строку, а не значение внешнего курсора, которое она представляет, и по существу вы не можете этого сделать.

Самого простой способ справиться с этим, если у вас есть достаточно небольшое количество столбцов в промежуточной таблице, которые могут появиться в качестве значения rec2.data_element, чтобы использовать выражение случая, чтобы назначить соответствующее фактическое значение 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, а не с нулевой строкой, которую вы формировали.

+0

Спасибо Алекса, я читал где-то, что глобальные переменные может ссылаться на то, как мне нужно, чтобы у вас было какое-то мнение о том, как я могу это достичь? –

+0

@oracle_of - глобальная (но может быть локальная) переменная 'curr_data_element' может ссылаться так, как вы показали, и использовала переменную связывания. Эта часть в порядке. Проблема заключается в том, что содержит эта переменная. У вас не может быть переменной, которая по существу является указателем на другую переменную PL/SQL. Не существует механизма для оценки строки, содержащей имя переменной PL/SQL. –