91

I want to write an SQL statement like below:

select * from tbl where col like ('ABC%','XYZ%','PQR%');

I know it can be done using OR. But I want to know is there any better solution.

peterh
  • 11,875
  • 18
  • 85
  • 108
Madhu
  • 5,686
  • 9
  • 37
  • 53

10 Answers10

69

This is a good use of a temporary table.

CREATE TEMPORARY TABLE patterns (
  pattern VARCHAR(20)
);

INSERT INTO patterns VALUES ('ABC%'), ('XYZ%'), ('PQR%');

SELECT t.* FROM tbl t JOIN patterns p ON (t.col LIKE p.pattern);

In the example patterns, there's no way col could match more than one pattern, so you can be sure you'll see each row of tbl at most once in the result. But if your patterns are such that col could match more than one, you should use the DISTINCT query modifier.

SELECT DISTINCT t.* FROM tbl t JOIN patterns p ON (t.col LIKE p.pattern);
Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Excellent. Exactly what I needed to remove hard-coded values from my code. My string masks are stored in a configuration table. The old code had each one hard-coded. This was not an elegant solution for changing values and would require change control protocols if I had any new values. I didn't know you could use the syntax "ON (my_field LIKE my_mask). Thanks. – Shari W Sep 12 '19 at 17:47
  • Yep! You can use any expression you want as the join condition. Most people use a simple equality comparison, but that's not a limitation. – Bill Karwin Sep 12 '19 at 18:33
59

Oracle 10g has functions that allow the use of POSIX-compliant regular expressions in SQL:

  • REGEXP_LIKE
  • REGEXP_REPLACE
  • REGEXP_INSTR
  • REGEXP_SUBSTR

See the Oracle Database SQL Reference for syntax details on this functions.

Take a look at Regular expressions in Perl with examples.

Code :

    select * from tbl where regexp_like(col, '^(ABC|XYZ|PQR)');
stefannebesnak
  • 730
  • 5
  • 4
  • 2
    Oracle can certainly use an index for `LIKE 'ABC%'` but I don't believe it can use an index for REGEX operations (unless it's a funcion based index) – symcbean Jan 22 '14 at 21:34
  • 1
    This is the best approach... Thanks for sharing. It was really helpful, though it was an old post. – NIK Aug 27 '20 at 05:11
  • This looks interesting, I will look into it, I was wondering how to edit regexp_like if its we have %ABC% , %XYZ% and %PQR% – Pavn Aug 31 '22 at 14:57
48

Here is an alternative way:

select * from tbl where col like 'ABC%'
union
select * from tbl where col like 'XYZ%'
union
select * from tbl where col like 'PQR%';

Here is the test code to verify:

create table tbl (col varchar(255));
insert into tbl (col) values ('ABCDEFG'), ('HIJKLMNO'), ('PQRSTUVW'), ('XYZ');
select * from tbl where col like 'ABC%'
union
select * from tbl where col like 'XYZ%'
union
select * from tbl where col like 'PQR%';
+----------+
| col      |
+----------+
| ABCDEFG  |
| XYZ      |
| PQRSTUVW |
+----------+
3 rows in set (0.00 sec)
Asaph
  • 159,146
  • 25
  • 197
  • 199
11
select * from tbl where col like 'ABC%'
or col like 'XYZ%'
or col like 'PQR%';

This works in toad and powerbuilder. Don't know about the rest

akjoshi
  • 15,374
  • 13
  • 103
  • 121
KathMania
  • 129
  • 1
  • 2
6

This might help:

select * from tbl where col like '[ABC-XYZ-PQR]%'

I've used this in SQL Server 2005 and it worked.

Eric
  • 317
  • 4
  • 7
5

I also had the same requirement where I didn't have choice to pass like operator multiple times by either doing an OR or writing union query.

This worked for me in Oracle 11g:

REGEXP_LIKE (column, 'ABC.*|XYZ.*|PQR.*'); 
Dharmesh Porwal
  • 1,406
  • 2
  • 12
  • 21
asad
  • 59
  • 1
  • 1
0

Even u can try this

Function

CREATE  FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20))
RETURNS @Strings TABLE
(   
  position int IDENTITY PRIMARY KEY,
  value varchar(8000)  
)
AS
BEGIN

DECLARE @index int
SET @index = -1

WHILE (LEN(@text) > 0)
  BEGIN 
    SET @index = CHARINDEX(@delimiter , @text) 
    IF (@index = 0) AND (LEN(@text) > 0) 
      BEGIN  
        INSERT INTO @Strings VALUES (@text)
          BREAK 
      END 
    IF (@index > 1) 
      BEGIN  
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))  
        SET @text = RIGHT(@text, (LEN(@text) - @index)) 
      END 
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index))
    END
  RETURN
END

Query

select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
0

If your parameter value is not fixed or your value can be null based on business you can try the following approach.

DECLARE @DrugClassstring VARCHAR(MAX);
SET @DrugClassstring = 'C3,C2'; -- You can pass null also

---------------------------------------------

IF @DrugClassstring IS NULL 
    SET @DrugClassstring = 'C3,C2,C4,C5,RX,OT'; -- If null you can set your all conditional case that will return for all
SELECT dn.drugclass_FK , dn.cdrugname
FROM drugname AS dn
INNER JOIN dbo.SplitString(@DrugClassstring, ',') class ON dn.drugclass_FK = class.[Name] -- SplitString is a a function

SplitString function

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
ALTER FUNCTION [dbo].[SplitString](@stringToSplit VARCHAR(MAX),
                                   @delimeter     CHAR(1)      = ',')
RETURNS @returnList TABLE([Name] [NVARCHAR](500))
AS
     BEGIN

         --It's use in report sql, before any change concern to everyone

         DECLARE @name NVARCHAR(255);
         DECLARE @pos INT;
         WHILE CHARINDEX(@delimeter, @stringToSplit) > 0
             BEGIN
                 SELECT @pos = CHARINDEX(@delimeter, @stringToSplit);
                 SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1);
                 INSERT INTO @returnList
                        SELECT @name;
                 SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos);
             END;
         INSERT INTO @returnList
                SELECT @stringToSplit;
         RETURN;
     END;
Mohammad Atiour Islam
  • 5,380
  • 3
  • 43
  • 48
0

I had to add all to Asaph's answer to make it work.

select * from tbl where col like 'ABC%'
union all
select * from tbl where col like 'XYZ%'
union all
select * from tbl where col like 'PQR%';
Toni
  • 1,555
  • 4
  • 15
  • 23
-1

SELECT * From tbl WHERE col LIKE '[0-9,a-z]%';

simply use this condition of like in sql and you will get your desired answer

Harry Sandal
  • 43
  • 11