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
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
Respostas:
Na configuração padrão de um banco de dados SQL Server, comparações de string são case-insensitive. Se o seu banco de dados substituir essa configuração (por meio do uso de um agrupamento alternativo), você precisará especificar que tipo de agrupamento usar em sua consulta.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
Observe que o agrupamento que forneci é apenas um exemplo (embora seja mais do que provável que funcione bem para você). Um esboço mais completo dos agrupamentos do SQL Server pode ser encontrado aqui .
UPPER
ou LOWER
maiúsculas e minúsculas e usar o LIKE
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 = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
Encontrei outra solução em outro lugar; isto é, usar
upper(@yourString)
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.
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 usando SQL_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 uma COLLATE
cláusula. Uma comparação de string precisa ser feita em ambos os casos, mas o uso UPPER()
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. Adicionar COLLATE
simplesmente direciona o processamento para gerar as chaves de classificação usando um conjunto de regras diferente daquele usado por padrão. Usar COLLATE
é definitivamente mais eficiente (ou "performante", se você gosta dessa palavra :) do que usar UPPER()
, como comprovado neste script de teste (em PasteBin) .
Há também o problema observado por @Ceisc na resposta de @ Danny:
Em alguns idiomas, as conversões de caso não são de ida e volta. ou seja, LOWER (x)! = LOWER (UPPER (x)).
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 exemplo convert(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 forem NVARCHAR
, não importa qual local você usar, pois todos são iguais nesse caso, portanto, Latin1_General_100_BIN2
sempre funciona. Se os dados forem VARCHAR
, você deve usar o mesmo local que os dados estão atualmente em (por exemplo Latin1_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 da COLLATE
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 a COLLATE
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 tornaria Latin1_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
Não, apenas o uso LIKE
não funcionará. LIKE
procura valores que correspondam exatamente ao seu padrão fornecido. Neste caso LIKE
, 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.).
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')
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.
WHERE
enunciado, e afetará todas asWHERE
cláusulas, correto?