¿Hay una combinación de "LIKE" y "IN" en SQL?

340

En SQL I (lamentablemente) a menudo tengo que usar " LIKE" condiciones debido a bases de datos que violan casi todas las reglas de normalización. No puedo cambiar eso ahora. Pero eso es irrelevante para la pregunta.

Además, a menudo uso condiciones como WHERE something in (1,1,2,3,5,8,13,21)una mejor legibilidad y flexibilidad de mis declaraciones SQL.

¿Hay alguna forma posible de combinar estas dos cosas sin escribir sub-selecciones complicadas?

Quiero algo tan fácil como en WHERE something LIKE ('bla%', '%foo%', 'batz%')lugar de esto:

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

Estoy trabajando con SQl Server y Oracle aquí, pero estoy interesado si esto es posible en cualquier RDBMS.

selfawaresoup
fuente
1
Tienes que hacer y gustar o: Y (algo como '% thing%' o algo como '% thing%' o algo como '% thing%')
Cosmic Hawk
Ojalá tuviéramos like any/ like all: stackoverflow.com/questions/40475982/sql-like-any-vs-like-all de Teradata . (Para el registro, esto se solicitó en el foro de Oracle Community Ideas community.oracle.com/ideas/11592 )
William Robertson el
similar stackoverflow.com/q/1076097/125981
Mark Schultheiss

Respuestas:

196

No hay combinación de LIKE & IN en SQL, mucho menos en TSQL (SQL Server) o PLSQL (Oracle). Parte de la razón de esto es porque la búsqueda de texto completo (FTS) es la alternativa recomendada.

Las implementaciones FTS de Oracle y SQL Server admiten la palabra clave CONTAINS, pero la sintaxis sigue siendo ligeramente diferente:

Oráculo:

WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0

Servidor SQL:

WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')

La columna que está consultando debe estar indexada en texto completo.

Referencia:

Ponis OMG
fuente
11
Hola, con Oracle, debe crear índices de texto sin formato en las columnas en las que desea aplicar el operador "CONTAINS". Dependiendo de su volumen de datos, esto podría ser bastante largo.
Pierre-Gilles Levallois
18
Con SQL Server (al menos la versión 2008) el comentario de @Pilooz también se aplica, debe crear índices de texto completo.
Marcel
La longitud máxima es de 4000.
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
59

Si desea que su declaración sea fácilmente legible, puede usar REGEXP_LIKE (disponible desde Oracle versión 10 en adelante).

Una tabla de ejemplo:

SQL> create table mytable (something)
  2  as
  3  select 'blabla' from dual union all
  4  select 'notbla' from dual union all
  5  select 'ofooof' from dual union all
  6  select 'ofofof' from dual union all
  7  select 'batzzz' from dual
  8  /

Table created.

La sintaxis original:

SQL> select something
  2    from mytable
  3   where something like 'bla%'
  4      or something like '%foo%'
  5      or something like 'batz%'
  6  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

Y una consulta simple con REGEXP_LIKE

SQL> select something
  2    from mytable
  3   where regexp_like (something,'^bla|foo|^batz')
  4  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

PERO ...

No lo recomendaría yo mismo debido al rendimiento no tan bueno. Me quedaría con los varios predicados LIKE. Así que los ejemplos fueron solo por diversión.

Rob van Wijk
fuente
44
+1 buena ilustración del uso de REGEXP en 10 g. Sin embargo, tengo curiosidad si el rendimiento realmente sería mucho peor. Ambos requerirán escaneos completos de tabla y / o índice, ¿no?
DCookie
12
Cierto. Pero las expresiones regulares queman la CPU como loca, no E / S. Si es peor y cuánto peor es, depende de qué tan grande sea su lista de expresiones y si la columna está indexada o no, entre otras. Es solo una advertencia, para que el póster original no se sorprenda cuando comience a implementarlo.
Rob van Wijk
49

estás atrapado con el

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

a menos que llene una tabla temporal (incluya los comodines con los datos) y únase así:

FROM YourTable                y
    INNER JOIN YourTempTable  t On y.something LIKE t.something

pruébelo (usando la sintaxis de SQL Server):

declare @x table (x varchar(10))
declare @y table (y varchar(10))

insert @x values ('abcdefg')
insert @x values ('abc')
insert @x values ('mnop')

insert @y values ('%abc%')
insert @y values ('%b%')

select distinct *
FROM @x x
WHERE x.x LIKE '%abc%' 
   or x.x LIKE '%b%'


select distinct x.*  
FROM @x             x
    INNER JOIN  @y  y On x.x LIKE y.y

SALIDA:

x
----------
abcdefg
abc

(2 row(s) affected)

x
----------
abc
abcdefg

(2 row(s) affected)
KM.
fuente
Ok, esto funcionaría, pero no va en la dirección prevista de hacer que la declaración SQL sea más fácil de leer :)
selfawaresoup
10
en SQL vas por el uso del índice y el rendimiento. Solo use sangría y nombres para la legibilidad de SQL, cuando realiza otras modificaciones para la legibilidad solo se arriesga a cambiar el plan de ejecución (que afecta el uso y el rendimiento del índice). Si no tiene cuidado, puede cambiar fácilmente una consulta que se ejecuta instantáneamente a una muy lenta haciendo cambios triviales.
KM.
La primera declaración de esta respuesta es clave: (¿la mayoría?) Los sistemas e idiomas basados ​​en SQL no admiten lo que desea, no sin implementar soluciones alternativas. (En el servidor SQL, ¿ayudaría la indexación de texto completo?)
Philip Kelley
@Philip Kelley, ¿puede hacer la indexación de texto completo de SQL Server LIKE 'bla%' , que en el código de ejemplo del OP? o solo puede hacer LIKE '%bla%'búsquedas?
KM.
Sinceramente, no sé, nunca he usado la indexación FT. Lo lancé como una muestra de una posible solución que ya está incluida en el producto. Por lo que está haciendo (A o B o C), sospecho que no lo hace, estoy bastante seguro de que tomaría mucho esfuerzo determinar esto, y sé que está fuera del alcance de su pregunta original (sí SQL lo hace de forma nativa).
Philip Kelley
20

Con PostgreSQL existe la forma ANYo ALL:

WHERE col LIKE ANY( subselect )

o

WHERE col LIKE ALL( subselect )

donde la subselección devuelve exactamente una columna de datos.

Benoit
fuente
1
Son LIKE ANYy LIKE ALLcomunes a todos los dialectos SQL, es decir, parte del núcleo del lenguaje, o específicas de un dialecto?
Assad Ebrahim
1
@AssadEbrahim, no, son específicos. Oracle tiene = ANYo <> ALLfunciona solo en SQL, no en PLSQL, por ejemplo.
Benoit
Creo que esta es una sintaxis estándar (pero no muchos DBMS la han implementado)
ypercubeᵀᴹ
Para postgres ver stackoverflow.com/questions/2245536/…
rogerdpack
13

Otra solución, debería funcionar en cualquier RDBMS:

WHERE EXISTS (SELECT 1
                FROM (SELECT 'bla%' pattern FROM dual UNION ALL
                      SELECT '%foo%'        FROM dual UNION ALL
                      SELECT 'batz%'        FROM dual)
               WHERE something LIKE pattern)
mik
fuente
1
Pero es más feo que un conjunto de declaraciones OR
Fandango68
1
@ Fandango68, pero la unión de selecciones puede ser reemplazada por otra fuente de patrones como una tabla, una vista, etc.
mik
10

Sugeriría usar una función de usuario de TableValue si desea encapsular las técnicas Inner Join o temp table que se muestran arriba. Esto le permitiría leer un poco más claramente.

Después de usar la función de división definida en: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx

podemos escribir lo siguiente en base a una tabla que creé llamada "Fish" (int id, varchar (50) Name)

SELECT Fish.* from Fish 
    JOIN dbo.Split('%ass,%e%',',') as Splits 
    on Name like Splits.items  //items is the name of the output column from the split function.

Salidas

1 bajo
2 lucios
7 pescador
8 leucomas
Nerd famoso
fuente
1
Una fila se duplicará si coincide con muchas condiciones a la vez.
mik
7

Un enfoque sería almacenar las condiciones en una tabla temporal (o variable de tabla en SQL Server) y unirse a eso de esta manera:

SELECT t.SomeField
FROM YourTable t
   JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue
AdaTheDev
fuente
Una fila se duplicará si coincide con muchas condiciones a la vez.
mik
7

Use una unión interna en su lugar:

SELECT ...
FROM SomeTable
JOIN
(SELECT 'bla%' AS Pattern 
UNION ALL SELECT '%foo%'
UNION ALL SELECT 'batz%'
UNION ALL SELECT 'abc'
) AS Patterns
ON SomeTable.SomeColumn LIKE Patterns.Pattern
Alaska
fuente
1
Bueno, eso es exactamente lo que me gustaría evitar. Aunque funciona.
selfawaresoup
¿Por qué evitar esta solución? Funciona tan rápido como la solución aceptada y es igual de versátil.
Phil Factor
3
@PhilFactor Esta solución puede crear filas duplicadas.
Jakub Kania
5

Estoy trabajando con SQl Server y Oracle aquí, pero estoy interesado si esto es posible en cualquier RDBMS.

Teradata admite la sintaxis LIKE ALL / ANY :

TODAS las cadenas de la lista.
CUALQUIER cadena en la lista.

┌──────────────────────────────┬────────────────────────────────────┐
      THIS expression         IS equivalent to this expression  
├──────────────────────────────┼────────────────────────────────────┤
 x LIKE ALL ('A%','%B','%C%')  x LIKE 'A%'                        
                               AND x LIKE '%B'                    
                               AND x LIKE '%C%'                   
                                                                  
 x LIKE ANY ('A%','%B','%C%')  x LIKE 'A%'                        
                               OR x LIKE '%B'                     
                               OR x LIKE '%C%'                    
└──────────────────────────────┴────────────────────────────────────┘

EDITAR:

jOOQ versión 3.12.0 admite esa sintaxis:

Agregue operadores sintéticos [NO] COMO CUALQUIERA y [NO] COMO TODOS

Muchas veces, a los usuarios de SQL les gustaría poder combinar predicados LIKE e IN, como en:

SELECT *
FROM customer
WHERE last_name [ NOT ] LIKE ANY ('A%', 'E%') [ ESCAPE '!' ]

La solución es expandir manualmente el predicado al equivalente

SELECT *
FROM customer
WHERE last_name LIKE 'A%'
OR last_name LIKE 'E%'

jOOQ podría soportar un predicado sintético de este tipo.


PostgreSQL LIKE/ILIKE ANY (ARRAY[]):

SELECT *
FROM t
WHERE c LIKE ANY (ARRAY['A%', '%B']);

SELECT *
FROM t
WHERE c LIKE ANY ('{"Do%", "%at"}');

demostración de violín db <>


Snowflake también es compatible con LIKE CUALQUIERA / LIKE ALL :

COMO CUALQUIERA / TODO

Permite la coincidencia de cadenas entre mayúsculas y minúsculas en comparación con uno o más patrones.

<subject> LIKE ANY (<pattern1> [, <pattern2> ... ] ) [ ESCAPE <escape_char> ]

Ejemplo:

SELECT * 
FROM like_example 
WHERE subject LIKE ANY ('%Jo%oe%','T%e')
-- WHERE subject LIKE ALL ('%Jo%oe%','J%e')
Lukasz Szozda
fuente
4

incluso puedes probar esto

Función

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

Consulta

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+'%';
SimarjeetSingh Panghlia
fuente
4

Tengo una solución simple, que funciona en postgresql al menos, usando like anyseguido de la lista de expresiones regulares. Aquí hay un ejemplo, buscando identificar algunos antibióticos en una lista:

select *
from database.table
where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}')
mkomo
fuente
3

También me preguntaba por algo así. Acabo de probar usando una combinación de SUBSTRINGy INy es una solución efectiva para este tipo de problema. Pruebe la siguiente consulta:

Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz')
ssah
fuente
1
un problema con este enfoque es que pierdes la capacidad de usar un índice en t1.algo si existe ..
ShoeLace
1
esto nunca encontrará 'batz'
mik
3

En Oracle puede usar una colección de la siguiente manera:

WHERE EXISTS (SELECT 1
                FROM TABLE(ku$_vcnt('bla%', '%foo%', 'batz%'))
               WHERE something LIKE column_value)

Aquí he usado un tipo de colección predefinido ku$_vcnt, pero puedes declarar el tuyo así:

CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000);
mik
fuente
2

Para SQL Server, puede recurrir a Dynamic SQL.

La mayoría de las veces en tales situaciones tiene el parámetro de la cláusula IN basado en algunos datos de la base de datos.

El siguiente ejemplo es un poco "forzado", pero puede coincidir con varios casos reales encontrados en bases de datos heredadas.

Suponga que tiene una tabla de Personas donde los nombres de las personas se almacenan en un solo campo PersonName como FirstName + '' + LastName. Debe seleccionar todas las personas de una lista de nombres, almacenados en el campo NameToSelect en la tabla NamesToSelect , además de algunos criterios adicionales (como filtrado por género, fecha de nacimiento, etc.)

Puedes hacerlo de la siguiente manera

-- @gender is nchar(1), @birthDate is date 

declare 
  @sql nvarchar(MAX),
  @subWhere nvarchar(MAX)
  @params nvarchar(MAX)

-- prepare the where sub-clause to cover LIKE IN (...)
-- it will actually generate where clause PersonName Like 'param1%' or PersonName Like 'param2%' or ...   
set @subWhere = STUFF(
  (
    SELECT ' OR PersonName like ''' + [NameToSelect] + '%''' 
        FROM [NamesToSelect] t FOR XML PATH('')
  ), 1, 4, '')

-- create the dynamic SQL
set @sql ='select 
      PersonName
      ,Gender
      ,BirstDate    -- and other field here         
  from [Persons]
  where 
    Gender = @gender
    AND BirthDate = @birthDate
    AND (' + @subWhere + ')'

set @params = ' @gender nchar(1),
  @birthDate Date'     

EXECUTE sp_executesql @sql, @params,    
  @gender,  
  @birthDate
bzamfir
fuente
2

Puedo tener una solución para esto, aunque hasta donde sé, solo funcionará en SQL Server 2008. Descubrí que puedes usar el constructor de filas descrito en https://stackoverflow.com/a/7285095/894974 para unirte a una tabla 'ficticia' usando una cláusula like. Suena más complejo de lo que es, mira:

SELECT [name]
  ,[userID]
  ,[name]
  ,[town]
  ,[email]
FROM usr
join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%' 

Esto dará como resultado que todos los usuarios tengan direcciones de correo electrónico como las que se proporcionan en la lista. Espero que sea de utilidad para cualquiera. El problema me había estado molestando por un tiempo.

Lijadora
fuente
1
Eso es interesante. Sin embargo, tenga en cuenta que esto solo debe usarse en una tabla pequeña, ya que la instrucción like no puede usar índices. Esta es la razón por la cual la búsqueda de texto completo, aunque es más difícil de configurar inicialmente, es la mejor opción si tiene muchos datos.
HLGEM
2

A partir de 2016, SQL Server incluye una STRING_SPLIT función . Estoy usando SQL Server v17.4 y conseguí que esto funcione para mí:

DECLARE @dashboard nvarchar(50)
SET @dashboard = 'P1%,P7%'

SELECT * from Project p
JOIN STRING_SPLIT(@dashboard, ',') AS sp ON p.ProjectNumber LIKE sp.value
marca
fuente
1

Esto funciona para valores separados por comas

DECLARE @ARC_CHECKNUM VARCHAR(MAX)
SET @ARC_CHECKNUM = 'ABC,135,MED,ASFSDFSF,AXX'
SELECT ' AND (a.arc_checknum LIKE ''%' + REPLACE(@arc_checknum,',','%'' OR a.arc_checknum LIKE ''%') + '%'')''

Evalúa a:

 AND (a.arc_checknum LIKE '%ABC%' OR a.arc_checknum LIKE '%135%' OR a.arc_checknum LIKE '%MED%' OR a.arc_checknum LIKE '%ASFSDFSF%' OR a.arc_checknum LIKE '%AXX%')

Si desea que use índices, debe omitir el primer '%'carácter.

David F Mayer
fuente
1

En Oracle RBDMS puede lograr este comportamiento usando REGEXP_LIKE función .

El siguiente código probará si la cadena tres está presente en la expresión de lista uno | dos | tres | cuatro | cinco (en el que el símbolo de tubería " | " significa operación lógica OR).

SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('three', 'one|two|three|four|five');

RESULT
---------------------------------
Success !!!

1 row selected.

La expresión anterior es equivalente a:

three=one OR three=two OR three=three OR three=four OR three=five

Entonces tendrá éxito.

Por otro lado, la siguiente prueba fallará.

SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('ten', 'one|two|three|four|five');

no rows selected

Hay varias funciones relacionadas con las expresiones regulares (REGEXP_ *) disponibles en Oracle desde la versión 10g. Si usted es un desarrollador de Oracle y le interesa este tema, este debería ser un buen comienzo Uso de expresiones regulares con la base de datos Oracle .

abrittaf
fuente
1

Puede ser que pienses la combinación como esta:

SELECT  * 
FROM    table t INNER JOIN
(
  SELECT * FROM (VALUES('bla'),('foo'),('batz')) AS list(col)
) l ON t.column  LIKE '%'+l.Col+'%'

Si ha definido el índice de texto completo para su tabla de destino, entonces puede usar esta alternativa:

SELECT  * 
FROM    table t
WHERE CONTAINS(t.column, '"bla*" OR "foo*" OR "batz*"')
Humayoun_Kabir
fuente
Gracias. Esta debería ser la respuesta aceptada de la OMI. No todos tienen un índice de texto completo definido (lo que sea que eso signifique). Sus primeras sugerencias funcionan de maravilla. Incluso puede poner los comodines en los valores de la tabla temporal en lugar de concatenar en LIKE.
The Fool
0

No hay respuesta como esta:

SELECT * FROM table WHERE something LIKE ('bla% %foo% batz%')

En Oracle no hay problema.

Hong Van Vit
fuente
0

En Teradata puedes usar LIKE ANY ('%ABC%','%PQR%','%XYZ%'). A continuación se muestra un ejemplo que ha producido los mismos resultados para mí.

--===========
--  CHECK ONE
--===========
SELECT *
FROM Random_Table A
WHERE (Lower(A.TRAN_1_DSC) LIKE ('%american%express%centurion%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%bofi%federal%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%american%express%bank%fsb%'))

;
--===========
--  CHECK TWO
--===========
SELECT *
FROM Random_Table  A
WHERE Lower(A.TRAN_1_DSC) LIKE ANY 
('%american%express%centurion%bank%',
'%bofi%federal%bank%',
'%american%express%bank%fsb%')
Piyush Verma
fuente
0

Sé que es muy tarde, pero tuve una situación similar. Necesitaba un operador "Me gusta" para un conjunto de procedimientos almacenados que tengo, que aceptan muchos parámetros y luego los usa para agregar datos de múltiples sistemas RDBMS, por lo tanto, ningún truco específico de RDBMS funcionaría, sin embargo, el procedimiento almacenado y cualquier función se ejecutará en MS SQL Server, por lo que podemos usar T-SQL para la funcionalidad de generar las declaraciones SQL completas para cada RDBMS, pero la salida debe ser bastante independiente de RDBMS.

Esto es lo que se me ocurrió por el momento para convertir una cadena delimitada (como un parámetro que entra en un procedimiento almacenado) en un bloque de SQL. Lo llamo "Liquen" por "ME GUSTA". ¿Consíguelo?

Lichen.sql

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =======================================================================
-- Lichen - Scalar Valued Function
-- Returns nvarchar(512) of "LIKE IN" results.  See further documentation.
-- CREATOR: Norman David Cooke
-- CREATED: 2020-02-05
-- UPDATED:
-- =======================================================================
CREATE OR ALTER FUNCTION Lichen 
(
    -- Add the parameters for the function here
    @leadingAnd bit = 1,
    @delimiter nchar(1) = ';',
    @colIdentifier nvarchar(64),
    @argString nvarchar(256)
)
RETURNS nvarchar(512)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @result nvarchar(512)

    -- set delimiter to detect (add more here to detect a delimiter if one isn't provided)
    DECLARE @delimit nchar(1) = ';'
    IF NOT @delimiter = @delimit 
        SET @delimit = @delimiter


    -- check to see if we have any delimiters in the input pattern
    IF CHARINDEX(@delimit, @argString) > 1  -- check for the like in delimiter
    BEGIN  -- begin 'like in' branch having found a delimiter
        -- set up a table variable and string_split the provided pattern into it.
        DECLARE @lichenTable TABLE ([id] [int] IDENTITY(1,1) NOT NULL, line NVARCHAR(32))
        INSERT INTO @lichenTable SELECT * FROM STRING_SPLIT(@argString, ';')

        -- setup loop iterators and determine how many rows were inserted into lichen table
        DECLARE @loopCount int = 1
        DECLARE @lineCount int 
        SELECT @lineCount = COUNT(*) from @lichenTable

        -- select the temp table (to see whats inside for debug)
        --select * from @lichenTable

        -- BEGIN AND wrapper block for 'LIKE IN' if bit is set
        IF @leadingAnd = 1
            SET @result = ' AND ('
        ELSE
            SET @result = ' ('

        -- loop through temp table to build multiple "LIKE 'x' OR" blocks inside the outer AND wrapper block
        WHILE ((@loopCount IS NOT NULL) AND (@loopCount <= @lineCount))
        BEGIN -- begin loop through @lichenTable
            IF (@loopcount = 1) -- the first loop does not get the OR in front
                SELECT @result = CONCAT(@result, ' ', @colIdentifier, ' LIKE ''', line, '''') FROM @lichenTable WHERE id = @loopCount
            ELSE  -- but all subsequent loops do
                SELECT @result = CONCAT(@result, ' OR ', @colIdentifier, ' LIKE ''', line, '''') FROM @lichenTable WHERE id = @loopCount
            SET @loopcount = @loopCount + 1     -- increment loop
        END -- end loop through @lichenTable

        -- set final parens after lichenTable loop
        SET @result = CONCAT(@result, ' )')
    END  -- end 'like in' branch having found a delimiter
    ELSE -- no delimiter was provided
    BEGIN   -- begin "no delimiter found" branch
        IF @leadingAnd = 1 
            SET @result = CONCAT(' AND ', @colIdentifier, ' LIKE ''' + @argString + '''')
        ELSE
            SET @result = CONCAT(' ', @colIdentifier, ' LIKE ''' + @argString + '''')
    END     -- end "no delimiter found" branch

    -- Return the result of the function
    RETURN @result
END  -- end lichen function

GO

La detección del delimitador posiblemente esté planificada, pero por ahora es un punto y coma por lo que puede ingresarla defaultallí. Probablemente hay errores en esto. los@leadingAnd parámetro es solo un valor de bit para determinar si desea colocar un "Y" al frente del bloque para que encaje perfectamente con otras adiciones de la cláusula WHERE.

Ejemplo de uso (con delimitador en argString)

SELECT [dbo].[Lichen] (
   default        -- @leadingAND, bit, default: 1
  ,default        -- @delimiter, nchar(1), default: ';'
  ,'foo.bar'      -- @colIdentifier, nvarchar(64), this is the column identifier
  ,'01%;02%;%03%' -- @argString, nvarchar(256), this is the input string to parse "LIKE IN" from
)
GO

Devuelve un nvarchar (512) que contiene:

 AND ( foo.bar LIKE '01%' OR foo.bar LIKE '02%' OR foo.bar LIKE '%03%' ) 

También omitirá el bloque si la entrada no contiene un delimitador:

Ejemplo de uso (sin delimitador en argString)

SELECT [dbo].[Lichen] (
   default        -- @leadingAND, bit, default: 1
  ,default        -- @delimiter, nchar(1), default: ';'
  ,'foo.bar'      -- @colIdentifier, nvarchar(64), this is the column identifier
  ,'01%'          -- @argString, nvarchar(256), this is the input string to parse "LIKE IN" from
)
GO

Devuelve un nvarchar (512) que contiene:

 AND foo.bar LIKE '01%'

Continuaré trabajando en esto, así que si he pasado por alto algo (evidentemente obvio o no), siéntanse libres de comentar o comunicarse.

NDC
fuente
-3

hacer esto

WHERE something + '%' in ('bla', 'foo', 'batz')
OR '%' + something + '%' in ('tra', 'la', 'la')

o

WHERE something + '%' in (select col from table where ....)
Nikolay Hristov
fuente
1
¿Cómo va a funcionar eso? El LHS es una cadena con un% y, por lo tanto, ese% no es un comodín
Darius X.