2016-09-09 2 views
-1

동적 SQL에 문제가 있습니다. 문제는 전역 변수를 읽고 설정하는 것입니다. 여기에 내가 가진 것이 있고 어떤 도움도 크게 감사합니다. 메모에 데이터를 포함 시켰지만 테이블 데이터가 필요한지 알려주십시오.Oracle PL/SQL 동적 if 문 글로벌 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

뿐만 아니라 DDL 문제 ... 후 테이블을 시켰지 – XING

+0

문제, – 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 열 값을 할당 할 경우 식을 사용하는 것입니다 당신은 가능성이 있지만, 모음을 통해 여분의 노력이 가치가되지 않을 수 할 수있는 열이 많은 경우

... 
    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; 
... 

: 변수는 rec2.data_element 값을 기준으로합니다.

curr_sql 문자열이 동일하게 유지되며 변경중인 것은 널 문자열이 아닌 널 rec1 열의 실제 값을 바인딩한다는 것입니다.

+0

감사 알렉스의 코드 내에서 내 의견을 참조하십시오, 어디 선가 읽고 있었다 포스트 테이블 DDL뿐만 아니라 –

+0

@oracle_of - 전역 변수 (그러나 지역 변수 일 수 있음) 변수'curr_data_element'는 앞에서 보았 듯이 참조 될 수 있으며, 바인드 변수를 사용합니다. 그 부분은 괜찮습니다. 문제는 해당 변수에 포함되어 있습니다. 기본적으로 다른 PL/SQL 변수에 대한 포인터 인 변수를 가질 수 없습니다. PL/SQL 변수 이름을 포함하는 문자열을 평가하는 메커니즘은 없습니다. –