¿Cómo hacer un LIKE insensible a mayúsculas y minúsculas en una base de datos sensible a mayúsculas y minúsculas?


11

Mi proveedor requiere que la base de datos del almacén de datos distinga entre mayúsculas y minúsculas, pero necesito hacer consultas que no distingan entre mayúsculas y minúsculas.

En una base de datos que distingue entre mayúsculas y minúsculas, ¿cómo escribiría esto para que no distinga entre mayúsculas y minúsculas?

    Where Name like '%hospitalist%'

Respuestas:


17

Puede agregar una nueva clasificación a su consulta de selección para encontrar mayúsculas o minúsculas.

-- Case sensitive example
SELECT *
FROM TABLE 
WHERE Name collate SQL_Latin1_General_CP1_CS_AS like '%hospitalist%'

-- Case insensitive example
SELECT *
FROM TABLE 
WHERE Name collate SQL_Latin1_General_CP1_CI_AS like '%hospitalist%'

Solo tenga en cuenta los problemas de rendimiento que esto podría presentar. Deberá escanear el índice agrupado para ajustar / encontrar los valores cuando realice la clasificación. La forma en que está escribiendo la LIKEpieza también hace que la consulta no sea sargable.

Aprendí el truco de cotejo de las clases del seminario SELECT de Kendra Little . Puede encontrar información adicional de colación de Ben Snaidero de MS SQL Tips.

MSDN en Intercalar.


@stom Hay dos métodos. Ya sea a) Mueva los problemas de rendimiento al tiempo de procesamiento y no al selecttiempo. Puede hacer esto creando una nueva columna con un subconjunto de los datos transformados y luego indexándolos, generalmente durante los momentos en que ejecutaría ETL. Esto tendría un costo de mantenimiento y no es un gran método. B) Puede hacer que la consulta de búsqueda sea discutible o sargable. Cambiar la consulta para que sea SELECT * FROM TABLE WHERE VALUE LIKE %hospitalisto SELECT * FROM TABLE WHERE VALUE LIKE hospitalist%funcionaría. Aparte de eso, está buscando hardware o características para aumentar la velocidad en un mal diseño.
Shaulinator

14

Si bien puede usar una función escalar como SUPERIOR o INFERIOR y puede volver a clasificar la columna para que ya no sea sensible a mayúsculas y minúsculas, todos estos enfoques requieren que la conversión de datos se realice contra los datos base, lo que nunca permitirá una búsqueda de índice. También está liderando su LIKE con un comodín, por lo que esto no es una gran preocupación para usted en este escenario de todos modos, pero si alguna vez quiso buscar la parte izquierda de una cadena de manera eficiente Y permitir el optimizador para buscar a través de un índice, puede especificar su cadena con corchetes ([]) de la siguiente manera:

SELECT *
FROM TABLE 
WHERE Name LIKE '[hH][oO][sS][pP][iI][tT][aA][lL][iI][sS][tT]%'

Este ejemplo ( enlace dbfiddle aquí ) hace un mejor trabajo al mostrar lo que quiero decir:

CREATE TABLE #tmp_cohellation_fun
(
        ID  INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    ,   myValue VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
)

-- Garbage values to represent data you don't want
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3;

-- Sprinkle a little bit of good data
INSERT INTO #tmp_cohellation_fun
        (myValue)
VALUES  ('Apple')
    ,   ('apple')

-- Another healthy helping of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3;

-- Some more good data
INSERT INTO #tmp_cohellation_fun
        (myValue)
VALUES
        ('aPple')
    ,   ('APPLE')
    ,   ('APple')


-- Final insert of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3
;

-- Create a nonclustered rowstore index
CREATE INDEX ix_myValue ON #tmp_cohellation_fun (myValue)
;

SET STATISTICS XML ON
;

-- Seek, but incorrect results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue LIKE 'apple%'
;

-- Scan, with correct results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue COLLATE SQL_Latin1_General_CP1_CI_AS LIKE 'apple%'
;

-- Seek, with correct results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue LIKE '[aA][pP][pP][lL][eE]%'
;

SET STATISTICS XML OFF
;

DROP TABLE IF EXISTS #tmp_cohellation_fun

Quiéralo. No puedo entender por qué SQL no puede simplemente retroceder con gracia como este cuando dice clasificar desde mayúsculas y minúsculas a mayúsculas y minúsculas, cuando tiene dos colaciones idénticas. Entiendo por qué no puedes ir para otro lado. De todos modos esto es algo bueno.
John Leidegren

13

Tanto esto como la COLLATErespuesta afectarán el rendimiento, ya que hacen que la consulta no sea SARGable , pero la forma más fácil de hacerlo (como sugirió Edgar en un comentario) es:

WHERE LOWER(Name) LIKE '%hospitalist%' 

o

WHERE UPPER(Name) LIKE '%HOSPITALIST%' 
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.