Seleção insensível a maiúsculas e minúsculas do MySQL


242

Alguém pode me dizer se uma SELECTconsulta MySQL é sensível a maiúsculas ou minúsculas por padrão? E se não, qual consulta eu teria que enviar para que eu possa fazer algo como:

SELECT * FROM `table` WHERE `Value` = "iaresavage"

Onde na realidade, o valor real de Valueé IAreSavage.


44
Em última análise, depende de agrupamento apresentou - se é '_ci' (case-insensitive) ou '_cs' (case-sensitive)
Jovan Perovic

15
Esta é uma pergunta mal formulada;). Metade das respostas está mostrando como fazer uma comparação sem distinção entre maiúsculas e minúsculas, e outra metade com distinção entre maiúsculas e minúsculas. E apenas 1 informa que o padrão é de fato insensitivo a maiúsculas e minúsculas. :) É importante notar que a insensibilidade caso funciona mesmo quando você faz uma comparação como'value' in ('val1', 'val2', 'val3')
SaltyNuts

5
@SaltyNuts cara, ler esta pergunta sete anos depois e perceber o quanto eu era noob é embaraçoso! Eu poderia ter apenas ler a documentação ea resposta está em como a primeira frase sobre instruções SELECT ...
NoodleOfDeath

Para adicionar o que o @JovanPerovic disse, o utf8_bin também faz distinção entre maiúsculas e minúsculas. Não tenho certeza se que existia naquela época
Chiwda

Respostas:


494

Eles não diferenciam maiúsculas de minúsculas , a menos que você faça uma comparação binária .


3
Eu concordo principalmente com o comentário de Tim, não acho que fazer um "menor ()" em seus valores em todos os lugares seja a melhor maneira de lidar com isso, parece uma solução alternativa. Mas admito que às vezes faz sentido e é mais fácil. (Colin mencionou que agrupar era melhor) Tivemos que os dados históricos foram movidos para a tabela mysql, o que quebrou a lógica herdada devido a certos valores de coluna terem maiúsculas e minúsculas. Precisávamos saber a diferença entre "GE1234" e "ge1234", eles precisavam ser exclusivos e permanecer registrados dessa maneira. Montamos nossa coluna na instrução create tabela desta forma em vez disso: varchar (20) CHARACTER SET utf8 COLLATE utf8_bin
gregthegeek

19
Não sei por que tantas pessoas votaram nisso. Ele afirma claramente aqui dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html que "... isso significa que, para caracteres alfabéticos, as comparações diferenciam maiúsculas de minúsculas". Então, se eu procurar por 'DickSavagewood', ele NÃO pegaria 'dicksavagewood'. Fazer o mesmo com LOWER () VAI buscá-lo. Então, minha resposta para a pergunta: no seu caso particular, o SELECT é realmente sensível a maiúsculas.
Luftwaffle

10
@ user1961753: Leia novamente: "Para strings binárias (varbinary, blob) ... diferenciam maiúsculas de minúsculas".
Marc B

1
@ MarcB este link agora está quebrado. Você poderia consertar isso? :)
Phiter

5
Como Jovan disse, isso depende do agrupamento, então essa resposta está praticamente errada.
phil294

117

Você pode minúscula o valor e o parâmetro passado:

SELECT * FROM `table` WHERE LOWER(`Value`) = LOWER("IAreSavage")

Outra (melhor) maneira seria usar o COLLATEoperador conforme mencionado na documentação


21
Como seria essa SELECTdeclaração usando COLLATEentão?
Barry

11
Ele diz, na página de documentação acima mencionada, que "comparações de cadeias não binárias diferenciam maiúsculas de minúsculas por padrão".
Por Quested Aronsson

9
É aterrorizante quantas pessoas votaram positivamente nessa resposta. Como o @Marc explica acima, as comparações não diferenciam maiúsculas de minúsculas. Você precisa entender agrupamentos e índices e configurá-los adequadamente - o uso de transformações de string como LOWER()ou uma COLLATEcláusula arbitrária pode ignorar completamente um índice e, com o tempo, à medida que a tabela cresce, isso pode ter implicações drásticas no desempenho. Provavelmente, esses são nomes de usuário que você está procurando? Use um agrupamento sem distinção entre maiúsculas e minúsculas e adicione um índice exclusivo à coluna. Use EXPLAINpara confirmar que o índice está sendo usado.
mindplay.dk

1
Eu estava prestes a dizer o mesmo que mindplay.dk ... upper () e lower () ignoram o índice e afetam diretamente o desempenho em grandes tabelas de banco de dados.
GTodorov 15/02/19

Concordo com o mindplay.dk e as opiniões de GTodorov. Cuidado ao usar algum método em uma coluna de destino na cláusula where. O índice da coluna pode ser inútil. Use EXPLAIN!
traeper

51

USE BINÁRIO

Esta é uma seleção simples

SELECT * FROM myTable WHERE 'something' = 'Something'

= 1

Este é um select com binário

SELECT * FROM myTable WHERE BINARY 'something' = 'Something'

ou

SELECT * FROM myTable WHERE 'something' = BINARY 'Something'

= 0


3
Quando faz sentido usar BINARY em apenas um lado do = (SELECT * FROM myTable WHERE BINARY 'something' = 'Something')?
21713 Jimmy Jimmy

@ Jimmy O que você quer dizer exatamente? O código funciona. Quando um lado da comparação é convertido em binário, a comparação é feita binária.
Jori

@ Jori Oh, eu acho que eu interpretei errado - eu pensei que um dos dois exemplos tinha BINÁRIO em ambos os lados do mesmo.
11134 Jimmy Jimmy

Eu acabei de votar nisso, porque esta é realmente a resposta certa. De acordo com a documentação no site MySQL, eles dizem que é melhor usar o comando BINARY do que tentar digitar suas palavras / solicitações em uma linguagem específica, porque o comando BINARY diz para deixar tudo como está e usá-lo exatamente como é apresentado. Então, quando cheguei à procura de uma resposta - as duas respostas aqui me levaram ao site MySQL e a olhar para a documentação deles. Usar BINARY é melhor. A tradução pode causar outros problemas.
Mark Manning

43

As comparações diferenciam maiúsculas de minúsculas quando a coluna usa um agrupamento que termina com _ci(como o agrupamento padrão latin1_general_ci ) e diferenciam maiúsculas de minúsculas quando a coluna usa um agrupamento que termina com _csou _bin(como os agrupamentos utf8_unicode_cse utf8_bin).

Verificar agrupamento

Você pode verificar seu servidor , banco de dados e agrupamentos de conexão usando:

mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

e você pode verificar o agrupamento da tabela usando:

mysql> SELECT table_schema, table_name, table_collation 
       FROM information_schema.tables WHERE table_name = `mytable`;
+----------------------+------------+-------------------+
| table_schema         | table_name | table_collation   |
+----------------------+------------+-------------------+
| myschema             | mytable    | latin1_swedish_ci |

Alterar agrupamento

Você pode alterar o agrupamento do banco de dados, tabela ou coluna para algo que diferencia maiúsculas de minúsculas da seguinte maneira:

-- Change database collation
ALTER DATABASE `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;

-- or change table collation
ALTER TABLE `table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- or change column collation
ALTER TABLE `table` CHANGE `Value` 
    `Value` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;

Suas comparações agora devem fazer distinção entre maiúsculas e minúsculas.


25

A comparação de cadeias na frase WHERE não diferencia maiúsculas de minúsculas. Você pode tentar comparar usando

WHERE `colname` = 'keyword'

ou

WHERE `colname` = 'KeyWord'

e você obterá o mesmo resultado . Esse é o comportamento padrão do MySQL.

Se você deseja que a comparação seja sensível a maiúsculas e minúsculas , adicione- COLLATEa assim:

WHERE `colname` COLLATE latin1_general_cs = 'KeyWord'

Esse SQL daria resultados diferentes com este: WHERE colnameCOLLATE latin1_general_cs = 'keyword'

latin1_general_cs é agrupamento comum ou padrão na maioria dos bancos de dados.


16

O agrupamento escolhido define se você diferencia maiúsculas ou minúsculas.


9

O padrão não diferencia maiúsculas de minúsculas, mas a próxima coisa mais importante que você deve examinar é como a tabela foi criada em primeiro lugar, porque você pode especificar a distinção entre maiúsculas e minúsculas ao criar a tabela.

O script abaixo cria uma tabela. Observe na parte inferior que diz "COLLATE latin1_general_cs". Que cs no final significa maiúsculas de minúsculas. Se você quisesse que sua tabela fizesse distinção entre maiúsculas e minúsculas, você deixaria essa parte de fora ou usaria "COLLATE latin1_general_ci".

   CREATE Table PEOPLE (

       USER_ID  INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

       FIRST_NAME  VARCHAR(50) NOT NULL,
       LAST_NAME  VARCHAR(50) NOT NULL,

       PRIMARY KEY (USER_ID)

   )

   ENGINE=MyISAM DEFAULT CHARACTER SET latin1
    COLLATE latin1_general_cs AUTO_INCREMENT=0;

Se seu projeto é tal que você pode criar sua própria tabela, faz sentido especificar sua preferência de distinção entre maiúsculas e minúsculas ao criar a tabela.




2

Observe também que os nomes de tabela diferenciam maiúsculas de minúsculas no Linux, a menos que você defina a lower_case_table_namediretiva de configuração como 1 . Isso ocorre porque as tabelas são representadas por arquivos que diferenciam maiúsculas de minúsculas no Linux.

Cuidado especialmente com o desenvolvimento no Windows que não diferencia maiúsculas de minúsculas e a implantação na produção onde está. Por exemplo:

"SELECT * from mytable" 

contra a tabela myTable terá êxito no Windows, mas falhará no Linux novamente, a menos que a diretiva mencionada acima esteja definida.

Consulte aqui: http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html


1
+1 - O cenário de escrever consultas sem distinção entre maiúsculas e minúsculas e depois falhar no Linux aconteceu muito em nosso projeto
Vic

@ Vic Estou tendo o mesmo problema com o meu projeto. Você poderia, por favor, me dizer como corrigiu isso?
Kamran Ahmed

@KamranAhmed, você precisa usar o invólucro de nomes de tabela exatamente como eles aparecem em scripts de criação
Vic

@ Victor seria o último recurso, pois eu teria que modificar literalmente toneladas de consultas. Eu estava pensando, se haveria alguma maneira fácil de fazer isso. Obrigado embora!
Kamran Ahmed

@KamranAhmed, tente alterar o lower_case_table_nameespecificado na resposta em que estamos comentando #
Vic

1

A solução atualmente aceita é principalmente correta.

Se você estiver usando uma sequência não binária (CHAR, VARCHAR, TEXT), as comparações não diferenciam maiúsculas de minúsculas , pelo agrupamento padrão.

Se você estiver usando uma string binária (BINARY, VARBINARY, BLOB), as comparações diferenciam maiúsculas de minúsculas, portanto, você precisará usar LOWER conforme descrito em outras respostas.

Se você não estiver usando o agrupamento padrão e uma cadeia não-binária, a distinção entre maiúsculas e minúsculas será decidida pelo agrupamento escolhido.

Fonte: https://dev.mysql.com/doc/refman/8.0/en/case-sensitivity.html . Leia atentamente. Alguns outros erraram ao dizer que as comparações são necessariamente sensíveis a maiúsculas ou minúsculas. Este não é o caso.


0

Você pode experimentá-lo. espero que seja util.

SELECT * FROM `table` WHERE `Value` COLLATE latin1_general_cs = "IAreSavage"

0

Os campos de sequência com o conjunto de sinalizadores binários sempre diferenciam maiúsculas de minúsculas. Se você precisar de uma pesquisa que diferencia maiúsculas de minúsculas de um campo de texto não binário, use: SELECT 'test' REGEXP BINARY 'TEST' COMO RESULTADO;

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.