servidor SQL ignorar caso em um onde a expressão
-
11-07-2019 - |
Pergunta
Como faço para construir uma consulta SQL (MS SQL Server), onde o "onde" cláusula é case-insensitive?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Eu quero os resultados para voltar ignorando o caso
Solução
Na configuração padrão de um banco de dados SQL Server, Comparação de strings são case-insensitive. Se seu banco de dados substitui essa configuração (através do uso de um agrupamento alternativo), então você precisa especificar que tipo de agrupamento para uso em sua consulta.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
Note que o agrupamento I fornecido é apenas um exemplo (embora provavelmente mais do que função muito bem para você). Um esboço mais completa de agrupamentos do SQL Server podem ser encontrados aqui .
Outras dicas
Normalmente, comparações de string são insensíveis ao caso. Se seu banco de dados está configurado para agrupamento sensível caso, você precisa forçar a utilização de um caso de um insensível:
SELECT balance FROM people WHERE email = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
Eu encontrei outra solução em outro lugar; isto é, para uso
upper(@yourString)
mas todo mundo aqui está dizendo que, no SQL Server, isso não importa porque está ignorando a caixa de qualquer maneira? Tenho certeza de que nosso banco de dados diferencia maiúsculas de minúsculas.
Não, usando apenas LIKE
não vai funcionar. Buscas LIKE
valores correspondentes exatamente o determinado padrão. Neste caso LIKE
iria encontrar apenas o texto 'sOmeVal' e não 'someval'.
Uma solução pracitcable está usando a função LCASE()
. LCASE('sOmeVal')
recebe a string em minúsculas do seu texto: 'someval'. Se você usar essa função para ambos os lados de sua comparação, ele funciona:
SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
A declaração compara duas cordas minúsculas, de modo que o seu 'sOmeVal' irá corresponder a todos os outros notação de 'someval' (por exemplo, 'Someval', 'sOMEVAl' etc.).
Os top 2 respostas (de Adam Robinson e Andrejs Cainikovs ) são meio, sorta correta, na medida em que eles fazem tecnicamente trabalho, mas suas explicações são errado e isso pode ser enganosa em muitos casos. Por exemplo, enquanto o agrupamento SQL_Latin1_General_CP1_CI_AS
irá funcionar em muitos casos, não deve ser assumido como sendo o agrupamento de maiúsculas e minúsculas adequado. Na verdade, dado que o OP está trabalhando em um banco de dados com um agrupamento entre maiúsculas e 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 poderia estar usando SQL_Latin1_General_CP1_CS_AS
, mas quando se trabalha com dados VARCHAR
, é importante não alterar a página de código, uma vez que pode levar a perda de dados, e que é controlada pelo locale / cultura de o agrupamento (ou seja Latin1_General vs vs Francês Hebrew etc). Por favor, veja ponto # 9 abaixo.
Os outros quatro respostas estão erradas em diferentes graus.
vou esclarecer todos os mal-entendidos para que os leitores podem espero fazer o mais adequado / escolhas eficientes.
-
Não use
UPPER()
. Isso é completamente trabalho extra desnecessário. Use uma cláusulaCOLLATE
. A comparação de string precisa ser feito em qualquer caso, mas usandoUPPER()
também tem de verificar, caractere por caractere, para ver se existe um mapeamento maiúsculas, e então alterá-lo. E você precisa fazer isso em ambos os lados. AdicionandoCOLLATE
simplesmente direciona o processamento para gerar as chaves de classificação usando um conjunto diferente de regras do que ia por padrão. UsandoCOLLATE
é definitivamente mais eficiente (ou "performance", se você gosta desse palavra :) do que usarUPPER()
, como ficou provado neste teste roteiro (no pastebin) .Há também a questão observado por @Ceisc em @ A resposta de Danny:
Em algumas conversões de caso idiomas não round-trip. ou seja INFERIOR (x)! = LOWER (UPPER (x)).
O maiúscula turco "I" é o exemplo comum.
-
Não, agrupamento não é uma configuração de todo o banco de dados, pelo menos não neste contexto. Há um agrupamento padrão de nível de banco de dados, e é usado como padrão para colunas alteradas e recém-criados que não especifique a cláusula
COLLATE
(que é provável que esse equívoco comum vem), mas não consultas de impacto diretamente a menos que você está comparando strings literais e variáveis ??para outras strings literais e variáveis, ou você está fazendo referência meta-dados em nível de banco de dados. -
Não, agrupamento não é por consulta.
-
agrupamentos são per predicado (ou seja, algo operando alguma coisa) ou expressão, não por consulta. E isso é verdade para toda a consulta, não apenas a cláusula
WHERE
. Isto cobre JOINs, GROUP BY, ORDER BY, através de divisórias, etc. -
Não, não converter para
VARBINARY
(e.g.convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
), pelas seguintes razões:- que é uma comparação binária, que não é case-insensitive (que é o que esta questão está pedindo)
- Se você quer uma comparação binária, usar um agrupamento binário. Use um que termina com
_BIN2
se você estiver usando SQL Server 2008 ou mais recente, então você não tem escolha a não ser usar um que termina com_BIN
. Se os dados foremNVARCHAR
então não importa qual local que você usar como eles são todos iguais, nesse caso, daíLatin1_General_100_BIN2
sempre funciona. Se os dados foremVARCHAR
, você deve usar a mesma localidade que o dATA é actualmente em (por exemploLatin1_General
,French
,Japanese_XJIS
, etc.) porque a região determina a página de código que é utilizado, e alterando as páginas de código pode alterar os dados (isto é, a perda de dados). - usando um tipo de dados de comprimento variável, sem especificar o tamanho dependerá do tamanho padrão, e existem dois padrões diferentes, dependendo do contexto em que o tipo de dados está a ser utilizado. Ele é 1 ou 30 para tipos string. Quando usado com
CONVERT()
ele usará o valor 30 default. O perigo é, se a cadeia pode ser mais de 30 bytes, ele vai ficar silenciosamente truncado e você provavelmente irá obter resultados incorretos de esse predicado. - Mesmo se você quiser uma comparação entre maiúsculas e minúsculas, agrupamentos binários são não maiúsculas de minúsculas (outro equívoco muito comum).
-
Não,
LIKE
nem sempre é sensível a maiúsculas. Ele utiliza o agrupamento da coluna a ser referenciado, ou o agrupamento do banco de dados, se uma variável é comparado com um literal de cadeia, ou o agrupamento especificado por meio da cláusulaCOLLATE
opcional. -
LCASE
não é uma função SQL Server. Parece ser Oracle ou MySQL. Ou, eventualmente, Visual Basic? -
Uma vez que o contexto da pergunta é comparar uma coluna para um literal de cadeia, nem o agrupamento da instância (muitas vezes referida como "servidor"), nem o agrupamento do banco de dados tem qualquer dirigir impacto aqui. Agrupamentos são armazenadas por cada coluna, e cada coluna pode ter um agrupamento diferente, e esses agrupamentos não precisa ser o mesmo que agrupamento padrão do banco de dados ou agrupamento da instância. Claro, o agrupamento exemplo é o padrão para o que um banco de dados recém-criado vai usar como seu agrupamento padrão se a cláusula
COLLATE
não foi especificado durante a criação do banco de dados. E da mesma forma, agrupamento padrão do banco de dados é o que uma coluna alterada ou recém-criada usará se a cláusulaCOLLATE
não foi especificado. -
Você deve usar o agrupamento de maiúsculas e minúsculas que é de outra maneira o mesmo que o agrupamento da coluna. Use a seguinte consulta para encontrar agrupamento da coluna (mudar nome e esquema nome da tabela):
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 mudar o
_CS
ser_CI
. Então,Latin1_General_100_CS_AS
se tornariaLatin1_General_100_CI_AS
.Se a coluna está usando um agrupamento binário (que termina em
_BIN
ou_BIN2
), em seguida, encontrar um agrupamento semelhante usando a seguinte consulta:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Por exemplo, assumindo-se a coluna utilizando
Japanese_XJIS_100_BIN2
, fazer esta: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: agrupamentos Informações
Você pode forçar a maiúsculas e minúsculas, lançando a um varbinary assim:
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
O banco de dados você está? Com o MS SQL Server, é uma configuração de todo o banco de dados, ou você pode sobrepor-lo por consulta com a palavra-chave COLLATE.