Reputation: 405
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)
);
I've created a procedure to fetch the fields which have AMT in their name. But the procedure shows error while executing, I can not figure out why is this error generating.
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;
/
error is
ORA-00904: "TEST_CASE": invalid identifier
ORA-06512: at "***.CHK_AMT", line 11
ORA-06512: at line 2
How can I solve this error??
Upvotes: 0
Views: 121
Reputation: 1234
Add some single quotes around vtbl to your dynamic statement , so it becomes :-
tblsqlstr := 'Select COLUMN_NAME from user_tab_columns where table_name= '''|| vtbl ||''' and COLUMN_NAME like upper(''%AMT%'')' ;
This means that when your code is run, if vtbl has a value table_a, the statement that is actually run will be 'table_a' rather than table_a.
N.B. Take care not to make this procedure public, as it is vulnerable to sql injection. Ideally you should use a bind variable instead. Example below :-
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;
Upvotes: 2
Reputation: 231651
Unless you have a particular reason for using dynamic SQL, it's much easier to use static SQL. It's also generally easier to use implicit cursors unless you have some reason that explicit cursors are advantageous. Since your code snippet doesn't show any need to use dynamic SQL or explicit cursors, it can be simplified to
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;
The specific error you're getting is the result of concatenating the vtbl
variable into your dynamic SQL statement. If you're going to concatenate the string together like that, you would need to put a single quote before and after the variable in the string and you would have to escape any single quotes in the table name (of course, it's likely there are any single quotes in a table name). If you must use dynamic SQL, you would be much better served using bind variables instead
tblsqlstr := 'Select COLUMN_NAME
from user_tab_columns
where table_name= :1
and COLUMN_NAME like upper(''%AMT%'')' ;
OPEN tblcursor for tblsqlstr using vtbl;
In addition to being more efficient and avoiding the potential for SQL injection attacks, that avoids the need to escape the data in your local variables and it avoids the need to add extra quotes to the string.
Upvotes: 2