Como faço para construir uma consulta SQL (MS SQL Server) em que a cláusula "where" não diferencia maiúsculas de minúsculas?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Eu quero que os resultados voltem ignorando o caso
sql
sql-server
where-clause
case-insensitive
Raul Agrait
fonte
fonte
WHERE
enunciado, e afetará todas asWHERE
cláusulas, correto?UPPER
ouLOWER
maiúsculas e minúsculas e usar oLIKE
para pesquisar?Normalmente, as comparações de strings não diferenciam maiúsculas de minúsculas. Se seu banco de dados estiver configurado para agrupamento que diferencia maiúsculas de minúsculas, você precisa forçar o uso de um que não diferencia maiúsculas de minúsculas:
SELECT balance FROM people WHERE email = '[email protected]' COLLATE SQL_Latin1_General_CP1_CI_AS
fonte
Encontrei outra solução em outro lugar; isto é, usar
mas todo mundo aqui está dizendo que, no SQL Server, não importa porque está ignorando maiúsculas de qualquer maneira? Tenho certeza que nosso banco de dados diferencia maiúsculas de minúsculas.
fonte
As 2 principais respostas (de Adam Robinson e Andrejs Cainikovs ) são meio, meio corretas, no sentido de que funcionam tecnicamente, mas suas explicações estão erradas e, portanto, podem ser enganosas em muitos casos. Por exemplo, embora o
SQL_Latin1_General_CP1_CI_AS
agrupamento funcione em muitos casos, ele não deve ser considerado o agrupamento adequado, sem distinção entre maiúsculas e minúsculas. Na verdade, dado que o OP está trabalhando em um banco de dados com um agrupamento que diferencia maiúsculas de minúsculas (ou possivelmente binário), sabemos que o OP não está usando o agrupamento que é o padrão para muitas instalações (especialmente qualquer instalado em um sistema operacional usando US Inglês como língua):SQL_Latin1_General_CP1_CI_AS
. Claro, o OP pode estar usandoSQL_Latin1_General_CP1_CS_AS
, mas ao trabalhar comVARCHAR
dados, é importante não alterar a página de código, pois isso pode levar à perda de dados e isso é controlado pela localidade / cultura do agrupamento (ou seja, Latin1_General vs francês vs hebraico etc.). Por favor, veja o ponto # 9 abaixo.As outras quatro respostas estão erradas em vários graus.
Esclarecerei todos os mal-entendidos aqui para que os leitores possam fazer as escolhas mais apropriadas / eficientes.
Não use
UPPER()
. Isso é um trabalho extra completamente desnecessário. Use umaCOLLATE
cláusula. Uma comparação de string precisa ser feita em ambos os casos, mas o usoUPPER()
também tem que verificar, caractere por caractere, para ver se há um mapeamento em maiúsculas e, em seguida, alterá-lo. E você precisa fazer isso dos dois lados. AdicionarCOLLATE
simplesmente direciona o processamento para gerar as chaves de classificação usando um conjunto de regras diferente daquele usado por padrão. UsarCOLLATE
é definitivamente mais eficiente (ou "performante", se você gosta dessa palavra :) do que usarUPPER()
, como comprovado neste script de teste (em PasteBin) .Há também o problema observado por @Ceisc na resposta de @ Danny:
A maiúscula turca "İ" é o exemplo comum.
Não, o agrupamento não é uma configuração de todo o banco de dados, pelo menos não neste contexto. Há um agrupamento padrão no nível do banco de dados e é usado como padrão para colunas alteradas e criadas recentemente que não especificam a
COLLATE
cláusula (que é provavelmente de onde vem esse equívoco comum), mas não afeta as consultas diretamente, a menos que você comparando literais e variáveis de string com outros literais e variáveis de string, ou você está fazendo referência a metadados no nível do banco de dados.Não, o agrupamento não é por consulta.
Os agrupamentos são por predicado (ou seja, algo operando algo) ou expressão, não por consulta. E isso é verdade para toda a consulta, não apenas para a
WHERE
cláusula. Isso cobre JOINs, GROUP BY, ORDER BY, PARTITION BY, etc.Não, não converta para
VARBINARY
(por exemploconvert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) pelos seguintes motivos:_BIN2
se estiver usando o SQL Server 2008 ou mais recente; caso contrário, você não terá escolha a não ser usar um que termine com_BIN
. Se os dados foremNVARCHAR
, não importa qual local você usar, pois todos são iguais nesse caso, portanto,Latin1_General_100_BIN2
sempre funciona. Se os dados foremVARCHAR
, você deve usar o mesmo local que os dados estão atualmente em (por exemploLatin1_General
,French
,Japanese_XJIS
, etc), porque o local determina a página de código que é usado, e mudar as páginas de código pode alterar os dados (perda de dados IE).CONVERT()
ele, usará o valor padrão 30. O perigo é que, se a string pode ter mais de 30 bytes, ela ficará silenciosamente truncada e você provavelmente obterá resultados incorretos com esse predicado.Não,
LIKE
nem sempre diferencia maiúsculas de minúsculas. Ele usa o agrupamento da coluna que está sendo referenciada, ou o agrupamento do banco de dados se uma variável for comparada a um literal de string ou o agrupamento especificado por meio daCOLLATE
cláusula opcional .LCASE
não é uma função do SQL Server. Parece ser Oracle ou MySQL. Ou possivelmente Visual Basic?Uma vez que o contexto da questão está comparando uma coluna a um literal de string, nem o agrupamento da instância (muitas vezes referido como "servidor") nem o agrupamento do banco de dados têm qualquer impacto direto aqui. Os agrupamentos são armazenados para cada coluna e cada coluna pode ter um agrupamento diferente, e esses agrupamentos não precisam ser iguais ao agrupamento padrão do banco de dados ou ao agrupamento da instância. Claro, o agrupamento de instância é o padrão para o que um banco de dados recém-criado usará como seu agrupamento padrão se a
COLLATE
cláusula não foi especificada ao criar o banco de dados. E da mesma forma, o agrupamento padrão do banco de dados é o que uma coluna alterada ou recém-criada usará se aCOLLATE
cláusula não for especificada.Você deve usar o agrupamento que não diferencia maiúsculas de minúsculas que, de outra forma, é o mesmo que o agrupamento da coluna. Use a seguinte consulta para encontrar o agrupamento da coluna (altere o nome da tabela e o nome do esquema):
SELECT col.* FROM sys.columns col WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName') AND col.[collation_name] IS NOT NULL;
Em seguida, basta alterar o
_CS
para ser_CI
. Então,Latin1_General_100_CS_AS
se tornariaLatin1_General_100_CI_AS
.Se a coluna estiver usando um agrupamento binário (terminando em
_BIN
ou_BIN2
), encontre um agrupamento semelhante usando a seguinte consulta:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Por exemplo, supondo que a coluna esteja usando
Japanese_XJIS_100_BIN2
, faça o seguinte:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Para mais informações sobre agrupamentos, codificações, etc, visite: Collations Informações
fonte
Não, apenas o uso
LIKE
não funcionará.LIKE
procura valores que correspondam exatamente ao seu padrão fornecido. Neste casoLIKE
, encontraria apenas o texto 'sOmeVal' e não 'someval'.Uma solução prática é usar a
LCASE()
função.LCASE('sOmeVal')
obtém a string minúscula do seu texto: 'someval'. Se você usar esta função para ambos os lados da comparação, ela funcionará:SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
A instrução compara duas strings em minúsculas, de modo que seu 'sOmeVal' corresponderá a todas as outras notações de 'someval' (por exemplo, 'Someval', 'sOMEVAl' etc.).
fonte
LCASE()
no SQL Server (pelo menos não que eu consiga ver). Acho que essa resposta é para um RDBMS totalmente diferente. Por favor, veja minha resposta para esclarecimentos sobre comparações de strings.Você pode forçar a distinção entre maiúsculas e minúsculas, convertendo para um varbinary como este:
SELECT * FROM myTable WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
fonte
Em qual banco de dados você está? Com o MS SQL Server, é uma configuração para todo o banco de dados, ou você pode substituí-la por consulta com a palavra-chave COLLATE.
fonte