2016-02-11 80 views
1

我有一個邏輯來實現我必須使用動態sql(列名和where子句決定在飛)。因此,在這裏我的遊標(​​)具有動態sql,並且有3個遊標字段(emp_id,emp_name,dept)。ORACLE:與動態查詢光標 - 拋出錯誤「無效標識符」的遊標字段

WHERE子句中使用這些遊標字段我試圖在循環內執行另一個動態sql .Bt oracle無法識別遊標字段並拋出錯誤,如「ORA-00904:"EMP_REC"."EMP_ID": invalid identifier"雖然我能夠輸出emp_rec.emp_id通過DBMS_OUTPUT

注意:請不要對代碼質量,這是不實際的代碼 這只是用來說明問題發表意見,我不能實際的代碼後,由於 一些合規相關的東西。

DECLARE 
    emp_ref_cursor sys_refcursor; 
    v_sql varchar2(3900); 

    TYPE emp_rec_type IS RECORD (emp_id number,emp_name varchar2(100),dept_id varchar2(100)); 
    emp_rec emp_rec_type; 

    v_dept_id number:='1234'; 

    v_dob varchar2(100); 
    v_desig varchar2(100); 

    x_dynamic_col_1 varchar2(100):='dob'; --dynamic column(based on some condition) 
    x_dynamic_col_2 varchar2(100):='designation'; --dynamic column(based on some condition) 
    x_dynamic_col_3 varchar2(100):='emp_id'; --dynamic column(based on some condition) 

BEGIN 
    v_sql:='SELECT emp_id,emp_name,dept FROM employee WHERE dept_id=' || v_dept_id; 

    OPEN emp_ref_cursor FOR v_sql; 
     LOOP 
       FETCH emp_ref_cursor INTO emp_rec; 
       exit WHEN emp_ref_cursor%NOTFOUND; 


       stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || ' 
         FROM employee A 
         WHERE emp_id=emp_rec.' || x_dynamic_col_3; 

       DBMS_OUTPUT.PUT_LINE(stmt); 
       --Prints the SQL query as expected 

       DBMS_OUTPUT.PUT_LINE('emp_rec.emp_id:'||emp_rec.emp_id); 
       --Displays the value!!! 

       execute immediate stmt into v_dob, v_desig; 
       --But why is it saying emp_rec.emp_id is invalid identifier?? 
    END LOOP;    
END; 

回答

2

您有emp_rec定義爲本地PL/SQL變量。 PL/SQL數據不在動態SQL執行的範圍內。執行它時,就像您試圖運行語句一樣 - 在單獨的SQL上下文中單獨顯示dbms_output。如果你這樣做,很顯然emp_rec不存在查詢。

你提到它,你就需要使用綁定變量:

WHERE emp_id=:dynamic_col_3'; 

然後與執行:

execute immediate stmt using emp_rec.emp_id; 

但你不能在using使用x_dynamic_col_3局部變量條款。因爲 - 無論如何 - 在這個例子中 - 查詢也需要改變,以使用不同的表列是動態記錄字段改變 - 這似乎並不是太多的問題。但你說where條款也將隨時改變。在這種情況下,您可以在執行程序之前將另一個局部變量設置爲相關的x字段。

+0

非常感謝,它確實有效。 – AnonymousCoder

1

您有錯誤地使用EXECUTE IMMEDIATE。您不需要將INTO子句放入SQL查詢中。用這個代替:

  stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || ' 
        FROM employee A 
        WHERE emp_id=emp_rec.' || x_dynamic_col_3; 

      execute immediate stmt into v_dob, v_desig; 
+0

的確如此,但是與OP得到的錯誤並不真正相關? –

+0

是的,我同意,但這不是一個真正的工作代碼(僅用於演示目的)。我的問題是@AlexPoole解釋的。雖然修正它。 – AnonymousCoder