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

Foi útil?

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.

  1. Não use UPPER(). Isso é completamente trabalho extra desnecessário. Use uma cláusula COLLATE. A comparação de string precisa ser feito em qualquer caso, mas usando UPPER() 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. Adicionando COLLATE simplesmente direciona o processamento para gerar as chaves de classificação usando um conjunto diferente de regras do que ia por padrão. Usando COLLATE é definitivamente mais eficiente (ou "performance", se você gosta desse palavra :) do que usar UPPER(), 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.

  2. 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.

  3. Não, agrupamento não é por consulta.

  4. 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.

  5. Não, não converter para VARBINARY (e.g.convert(varbinary, myField) = convert(varbinary, 'sOmeVal')), pelas seguintes razões:

    1. que é uma comparação binária, que não é case-insensitive (que é o que esta questão está pedindo)
    2. 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 forem NVARCHAR 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 forem VARCHAR, você deve usar a mesma localidade que o dATA é actualmente em (por exemplo Latin1_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).
    3. 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.
    4. 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).
  6. 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áusula COLLATE opcional.

  7. LCASE não é uma função SQL Server. Parece ser Oracle ou MySQL. Ou, eventualmente, Visual Basic?

  8. 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áusula COLLATE não foi especificado.

  9. 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 tornaria Latin1_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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top