Reputation: 121
I want to check if a query has bind variables with specified names. As I have a procedure, which process queries. These queries can have bind variables. Dependend on a bind variable name I wish to bind different values. I can use for example INSTR method like below:
IF INSTR(mySELECT, ':n1') > 0 THEN
DBMS_SQL.BIND_VARIABLE (myCursorId, 'n1', n1);
END IF;
IF INSTR(mySELECT ,':n2') > 0 THEN
DBMS_SQL.BIND_VARIABLE (myCursorId, 'n2', n2);
END IF;
But I think it is not the best way of doing it. Can someone give me a better one?
Upvotes: 2
Views: 684
Reputation: 9875
DBMS_SQL.BIND_VARIABLE
raises ORA-01006: bind variable does not exist
if the bind is missing. So you can call the function and trap the exception if it's likely the bind variables are not present:
declare
cur number;
sql_stmt varchar2(100);
res number;
procedure bind ( bind_name varchar2, bind_value int ) as
non_existent_bind exception;
pragma exception_init ( non_existent_bind, -1006 );
begin
dbms_sql.bind_variable ( cur, bind_name, bind_value );
exception when non_existent_bind then
dbms_output.put_line ( 'Missing bind ' || bind_name );
end bind;
begin
cur := dbms_sql.open_cursor;
sql_stmt := q'!select ':this_bind_does_not_exist', :n1 from dual where 1 = :n2!';
dbms_sql.parse ( cur, sql_stmt, dbms_sql.native );
bind ( 'n1', 1 );
bind ( 'n2', 2 );
bind ( 'this_bind_does_not_exist', 3 );
res := dbms_sql.execute ( cur );
dbms_sql.close_cursor ( cur );
end;
/
Missing bind this_bind_does_not_exist
Using instr
or similar is unsafe; a matching string could exist elsewhere in the statement, e.g. as a literal.
That said, the question suggests you have dynamic SQL that adds binds as necessary. Instead of trapping the exception you could keep track of which binds have been added, for example:
declare
...
has_n1 boolean := false;
begin
...
if n1 is not null then
sql_stmt := sql_stmt || ' and c1 = :n1';
has_n1 := true;
end if;
...
dbms_sql.parse ( cur, sql_stmt, dbms_sql.native );
...
if has_n1 then
dbms_sql.bind_variable ( cur, 'n1', n1 );
end if;
...
Or always include the bind in the statement, with an always true comparison when you want to ignore it:
if n1 is not null then
sql_stmt := sql_stmt || ' and c1 = :n1';
else
sql_stmt := sql_stmt || ' and :n1 is null';
end if;
...
dbms_sql.parse ( cur, sql_stmt, dbms_sql.native );
...
dbms_sql.bind_variable ( cur, 'n1', n1 );
Upvotes: 2
Reputation: 168470
I want to check if a query has bind variables.
If you just want to check if the query has bind variables then execute it and catch the exception if there are variables that are not bound:
DECLARE
NOT_ALL_VARIABLES_BOUND EXCEPTION;
PRAGMA EXCEPTION_INIT(NOT_ALL_VARIABLES_BOUND, -1008);
BEGIN
EXECUTE IMMEDIATE 'SELECT :n1 FROM DUAL';
DBMS_OUTPUT.PUT_LINE('No bind variables');
EXCEPTION
WHEN NOT_ALL_VARIABLES_BOUND THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
Outputs:
ORA-01008: not all variables bound
and
DECLARE
NOT_ALL_VARIABLES_BOUND EXCEPTION;
PRAGMA EXCEPTION_INIT(NOT_ALL_VARIABLES_BOUND, -1008);
BEGIN
EXECUTE IMMEDIATE 'SELECT '':n1'' FROM DUAL';
DBMS_OUTPUT.PUT_LINE('No bind variables');
EXCEPTION
WHEN NOT_ALL_VARIABLES_BOUND THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
Outputs:
No bind variables
Upvotes: 2