9

I am using dynamic cursor for fetching data. Query that is being executed looks similar to:

query := 'SELECT column1, column2 
          FROM my_table 
          WHERE column1 LIKE ''%:bv1%''';

And the cursor itself is executed like this:

OPEN my_cursor FOR query USING my_var1;

I also tried to check the query and print it:

... WHERE column1 LIKE '%:bv1%' ...

so apostrophes are escaped, but the cursor fetches no data. Is it even possible to use bind variables in LIKE clause and if yes, what did I do wrong?

3 Answers 3

11

This is a subtle one. It's often useful to start with a static statement, get that right, then convert it to dynamic SQL.

In non-dynamic SQL we might do it like this:

 SELECT column1, column2 
 FROM my_table 
 WHERE column1 LIKE '%' || local_var || '%'; 

The dynamic equivalent is

query := 'SELECT column1, column2 
          FROM my_table 
          WHERE column1 LIKE ''%''||:bv1||''%'' ';
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it works now. I did it exactly how you said - going from static statement to dynamic, I just had no idea i still need to use || operators in dynamic query.
1

Take the bind variable out of the string:

VARIABLE mycursor REFCURSOR;
VARIABLE bv1 VARCHAR2;

BEGIN
  :bv1 := 'X'; -- set the bind variable
END;
/

DECLARE
  query VARCHAR2(200) := 'SELECT * FROM DUAL WHERE DUMMY LIKE :value';
BEGIN
  OPEN :mycursor FOR query USING '%' || :bv1 || '%';
END;
/

PRINT mycursor;

Output

MYCURSOR
--------
DUMMY
-----
X

2 Comments

This would very probably also work, but the solution above is more useful for my needs. Thanks anyway :)
Thanks, used this and for some reason my very limited testing had this solution performing slightly better than the accepted answer.
-1

Just for anyone else who happens to be passing, you can also put the % wildcard in the bind-string itself:

DECLARE
   cursor_ SYS_REFCURSOR;
   qry_ VARCHAR2(2000) := q'[
with cat_names as (
select 'Bobby' names from dual union
select 'Tracy' names from dual union
select 'Jack' names from dual union
select 'Barnet' names from dual union
select 'Sally' names from dual union
select 'Bruce' names from dual
)
select c.names
from   cat_names c
where  c.names LIKE :var]';

   var_  VARCHAR2(20) := 'B%';
   name_ VARCHAR2(50);

BEGIN
   OPEN cursor_ FOR qry_ USING var_;
   LOOP
      FETCH cursor_ INTO name_;
      EXIT WHEN cursor_%NOTFOUND;
      Dbms_Output.Put_Line (name_);
   END LOOP;
   CLOSE cursor_;
END;

And the output is:

Barnet
Bobby
Bruce

This solution is more dynamic than the accepted answer, because it gives your user/client-application the choice of whether to use a % match, and not every search has to be done on the whole string. Depending on your data-set and table structure, this could drastically hit your performance because a preceding % on a search string (such as the enforced %:bv1% in the accepted answer) normally means the optimizer can't use an index.

Disclaimer: Tested in Oracle 19 only!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.