¿Cómo hacer una búsqueda sensible a mayúsculas y minúsculas en la cláusula WHERE (estoy usando SQL Server)?

150

Quiero hacer una búsqueda sensible a mayúsculas y minúsculas en mi consulta SQL. Pero por defecto, SQL Server no considera el caso de las cadenas.

¿Alguna idea sobre cómo hacer una búsqueda sensible a mayúsculas y minúsculas en una consulta SQL?

Veera
fuente

Respuestas:

174

Se puede hacer cambiando la colación . Por defecto no distingue entre mayúsculas y minúsculas.

Extracto del enlace:

SELECT 1
FROM dbo.Customers
WHERE   CustID = @CustID COLLATE SQL_Latin1_General_CP1_CS_AS
    AND CustPassword = @CustPassword COLLATE SQL_Latin1_General_CP1_CS_AS

O cambie las columnas para que distingan entre mayúsculas y minúsculas .

Ashish Jain
fuente
2
Cómo usar cuando tenemos en su lugar =. como WHERE CustID en (@CustID)
rinuthomaz
La recopilación funciona para la mayoría de los casos, pero si tiene otros caracteres de idioma en sus datos, devolverá falsos positivos: /schwarz-weißversus:/schwarz-weiss
Lazlow
162

Al usar colación o conversión a binario, así:

SELECT *
FROM Users
WHERE   
    Username = @Username COLLATE SQL_Latin1_General_CP1_CS_AS
    AND Password = @Password COLLATE SQL_Latin1_General_CP1_CS_AS
    AND Username = @Username 
    AND Password = @Password 

La duplicación de nombre de usuario / contraseña existe para dar al motor la posibilidad de usar índices. La clasificación anterior es una clasificación sensible a mayúsculas y minúsculas, cambie a la que necesita si es necesario.

El segundo, convertir a binario, podría hacerse así:

SELECT *
FROM Users
WHERE   
    CAST(Username as varbinary(100)) = CAST(@Username as varbinary))
    AND CAST(Password as varbinary(100)) = CAST(@Password as varbinary(100))
    AND Username = @Username 
    AND Password = @Password 
Jonas Lincoln
fuente
13
Las personas que lean esta pregunta también pueden encontrar útil leer cómo cambiar la columna en sí para que distinga entre mayúsculas y minúsculas, lo que elimina la necesidad de usar la intercalación en la cláusula WHERE. Ver: stackoverflow.com/a/485394/908677
Elijah Lofgren
2
El método de conversión como varbinary funcionó para mí cuando se usa directamente en la base de datos, pero no funcionó al enviar la misma declaración desde una aplicación .NET; no tengo idea de por qué. Pero el método de clasificación funcionó bien.
Doug
1
Esta respuesta sería perfecta si incluyera una explicación de dónde colocar el término buscado, es decir, dónde like "*word or phrase*"se insertaría una frase similar a una búsqueda SQL normal .
Hombre enlatado
@CannedMan: puede usar la solución de clasificación anterior de la misma manera con la declaración LIKE. Simplemente haga lo siguiente para devolver todas las 'D' mayúsculas. "SELECT * FROM SomeTable WHERE ColumnName como '% D%' COLLATE SQL_Latin1_General_CP1_CS_AS"
Radderz
No funciona con el alfabeto checo. Palabra probada: 'ukázka'. Está en la tabla como una sola palabra en una columna, pero su búsqueda no la encontró.
Jan Macháček
14

Puede realizar la consulta utilizando convertir a varbinary, es muy fácil. Ejemplo:

Select * from your_table where convert(varbinary, your_column) = convert(varbinary, 'aBcD') 
Juan carlos velez
fuente
2
No funciona con el alfabeto checo. Palabra probada: 'ukázka'. Está en la tabla como una sola palabra en una columna, pero su búsqueda no la encontró.
Jan Macháček
7

USE BINARY_CHECKSUM

SELECT 
FROM Users
WHERE   
    BINARY_CHECKSUM(Username) = BINARY_CHECKSUM(@Username)
    AND BINARY_CHECKSUM(Password) = BINARY_CHECKSUM(@Password)
Sandeep
fuente
3
¿No significa esto que ya no es una comparación exacta? ¿Puede haber a veces que sea cierto que en realidad no son lo mismo?
O'Rooney
3
Estoy de acuerdo @ O'Rooney, esto en ocasiones devolverá falsos positivos.
Des Horsley
5

usar HASHBYTES

declare @first_value nvarchar(1) = 'a'
declare @second_value navarchar(1) = 'A'

if HASHBYTES('SHA1',@first_value) = HASHBYTES('SHA1',@second_value) begin
    print 'equal'
end else begin
    print 'not equal'
end

-- output:
-- not equal

... en donde cláusula

declare @example table (ValueA nvarchar(1), ValueB nvarchar(1))

insert into @example (ValueA, ValueB)
values  ('a', 'A'),
        ('a', 'a'),
        ('a', 'b')

select  ValueA + ' = ' + ValueB
from    @example
where   hashbytes('SHA1', ValueA) = hashbytes('SHA1', ValueB)

-- output:
-- a = a

select  ValueA + ' <> ' + ValueB
from    @example
where   hashbytes('SHA1', ValueA) <> hashbytes('SHA1', ValueB)

-- output:
-- a <> A
-- a <> b

o para encontrar un valor

declare @value_b nvarchar(1) = 'A'

select  ValueB + ' = ' + @value_b
from    @example
where   hashbytes('SHA1', ValueB) = hasbytes('SHA1', @value_b)

-- output:
-- A = A
Doblar
fuente
5

use Latin1_General_CS como su cotejo en su sql db

blake
fuente
2

En MySQL, si no desea cambiar la intercalación y desea realizar una búsqueda sensible a mayúsculas y minúsculas, simplemente use una palabra clave binaria como esta:

SELECT * FROM table_name WHERE binary username=@search_parameter and binary password=@search_parameter
Sumit Joshi
fuente
2
Esa no es una consulta válida de SQL Server. Creo que es MySQL
Jon Tirjan
2
Funciona perfectamente en MySQL
WM
1
select * from incidentsnew1 
where BINARY_CHECKSUM(CloseBy) = BINARY_CHECKSUM(Upper(CloseBy))
Hemant yadav
fuente
-4

Tal como lo han dicho otros, puede realizar una búsqueda sensible a mayúsculas y minúsculas. O simplemente cambie el formato de clasificación de una columna especificada como yo. Para las columnas Usuario / Contraseña en mi base de datos, las cambio a intercalación mediante el siguiente comando:

ALTER TABLE `UserAuthentication` CHANGE `Password` `Password` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL;
Gfast2
fuente
¡NO almacene contraseñas como texto sin formato! Deberían haber sido picados y salados, ¡y luego la comparación está en el picadillo y la sal! ¡Esto es simplemente una respuesta terrible!
Nelson