2012-10-09 85 views
0
CREATE TABLE TEST_CASE 
    (
    ID NUMBER(19,2), 
    CURRENCY_TYPE VARCHAR2(30), 
    PAIDAMT NUMBER(19,2), 
    RECVDAMT NUMBER(19,2), 
    AMTDUE NUMBER, 
    TRANSACTION_DATE VARCHAR2(30) 
); 

光標我創建了一個程序來獲取其具有AMT在其名稱中的字段。 但執行過程中顯示錯誤,我想不通爲什麼這個 錯誤產生。麻煩內部程序

create or replace procedure chk_amt 
(
    vtbl varchar2 
) 
as 
tblcursor sys_refcursor; 
tblsqlstr varchar2(1000); 
importedrows VARCHAR2(1000); 
BEGIN 
    tblsqlstr := 'Select COLUMN_NAME from user_tab_columns where table_name= '|| vtbl ||' and COLUMN_NAME like upper(''%AMT%'')' ; 
    OPEN tblcursor for tblsqlstr; 
loop 
fetch tblcursor into importedrows; 
DBMS_OUTPUT.PUT_LINE(importedrows); 
EXIT WHEN tblcursor%NOTFOUND; 
end loop; 
CLOSE tblcursor; 
end; 
/

誤差

ORA-00904: "TEST_CASE": invalid identifier 
ORA-06512: at "***.CHK_AMT", line 11 
ORA-06512: at line 2 

我怎樣才能解決這個錯誤?

回答

2

各地的vtbl一些單引號添加到您的動態語句,所以它變成: -

tblsqlstr := 'Select COLUMN_NAME from user_tab_columns where table_name= '''|| vtbl ||''' and COLUMN_NAME like upper(''%AMT%'')' ; 

這意味着,當你的代碼運行,如果VTBL有一個值表-A,即實際運行會的聲明是'table_a'而不是table_a。

N.B.注意不要公開這個過程,因爲它很容易被sql注入。理想情況下,您應該使用綁定變量。示例如下: -

CREATE OR REPLACE PROCEDURE chk_amt(vtbl VARCHAR2) AS 
tblcursor SYS_REFCURSOR; 
tblsqlstr VARCHAR2(1000); 
importedrows VARCHAR2(1000); 
BEGIN 
tblsqlstr := 'Select COLUMN_NAME from user_tab_columns where table_name= :val_bnd and COLUMN_NAME like upper(''%AMT%'')'; 
OPEN tblcursor FOR tblsqlstr USING vtbl; 
LOOP 
    FETCH tblcursor 
     INTO importedrows; 
    dbms_output.put_line(importedrows); 
    EXIT WHEN tblcursor%NOTFOUND; 
END LOOP; 
CLOSE tblcursor; 
END; 
2

除非您有使用動態SQL的特殊原因,否則使用靜態SQL要容易得多。使用隱式遊標通常也更容易,除非你有某些原因明確的遊標是有利的。由於您的代碼段不顯示任何需要使用動態SQL或顯式遊標,它可以簡化爲

create or replace procedure chk_amt 
(
    vtbl varchar2 
) 
as 
BEGIN 
    FOR columns IN (SELECT column_name 
        FROM user_tab_columns 
        WHERE table_name = vtbl 
        AND column_name LIKE '%AMT%') 
    LOOP 
    DBMS_OUTPUT.PUT_LINE(columns.column_name); 
    END LOOP; 
end; 

你得到特定的錯誤是串接vtbl變量到您的動態SQL語句的結果。如果你要將字符串連接在一起,那麼你需要在字符串中的變量之前和之後放一個單引號,並且你必須避免表名中的任何單引號(當然,這很可能是表名中的任何單引號)。如果必須使用動態SQL,你會好得多使用綁定變量服代替

tblsqlstr := 'Select COLUMN_NAME 
       from user_tab_columns 
       where table_name= :1 
        and COLUMN_NAME like upper(''%AMT%'')' ; 
OPEN tblcursor for tblsqlstr using vtbl; 

除了被更加高效,避免了SQL注入攻擊的可能性,即避免了需要逃避本地數據它避免了需要向字符串添加額外的引號。