MySQL nie rozróżnia wielkości liter


242

Czy ktoś może mi powiedzieć, czy SELECTzapytanie MySQL domyślnie rozróżnia małe i wielkie litery? A jeśli nie, jakie zapytanie musiałbym wysłać, aby móc zrobić coś takiego:

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

W rzeczywistości rzeczywistą wartością Valuejest IAreSavage.


44
Ostatecznie zależy to od złożonego sortowania - jeśli jest to „_ci” (bez uwzględniania wielkości liter) lub „_cs” (z uwzględnieniem wielkości liter)
Jovan Perovic

15
To jedno źle sformułowane pytanie;). Połowa odpowiedzi pokazuje, jak przeprowadzić porównanie bez rozróżniania wielkości liter, a połowa zmierza do rozróżniania wielkości liter. I tylko 1 mówi ci, że domyślnie nie uwzględnia wielkości liter. :) Warto zauważyć, że rozróżnianie wielkości liter działa nawet wtedy, gdy wykonujesz porównanie typu'value' in ('val1', 'val2', 'val3')
SaltyNuts,

5
@ Mężczyzna z SaltNuts, czytając to pytanie 7 lat później i zdając sobie sprawę, jak bardzo byłam noobem, jest zawstydzająca! Mógłbym po prostu przeczytać dokumentację, a odpowiedź brzmi jak pierwsze zdanie na temat instrukcji SELECT ...
NoodleOfDeath

Aby dodać do tego, co powiedział @JovanPerovic, utf8_bin również rozróżnia wielkość liter. Nie jestem pewien, czy to wtedy istniało
Chiwda,

Odpowiedzi:


494

wrażliwe na wielkość liter , chyba że zrobić porównanie binarne .


3
W większości zgadzam się z komentarzem Tima, nie sądzę, aby stosowanie „lower ()” dla twoich wartości było najlepszym sposobem na poradzenie sobie z tym, wydaje się to obejściem. Ale przyznaję, że czasami ma to sens i jest łatwiejsze. (Colin wspomniał, że sortowanie jest lepsze) Mieliśmy dane historyczne przeniesione do tabeli mysql, co złamało starą logikę z powodu pewnych wartości kolumn mających niewrażliwy przypadek. Musieliśmy znać różnicę między „GE1234” a „ge1234”, musieli być wyjątkowi i pozostać zalogowani w ten sposób. Zamiast tego ustawiamy naszą kolumnę w instrukcji tworzenia tabeli: varchar (20)
ZNAK ZESTAWU

19
Nie wiem, dlaczego tak wielu ludzi to zagłosowało. Wyraźnie stwierdza tutaj dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html, że „… oznacza to, że w przypadku znaków alfabetycznych rozróżniana jest wielkość liter”. Więc jeśli szukam „DickSavagewood”, NIE wyłapałbym „dicksavagewood”. Robiąc to samo z LOWER () BĘDZIE to podnosić. Tak więc moja odpowiedź na pytanie: w twoim przypadku SELECT rzeczywiście rozróżnia małe i wielkie litery.
Luftwaffle,

10
@ user1961753: Przeczytaj ponownie: „W przypadku ciągów binarnych (varbinary, blob) ... rozróżniana jest wielkość liter”.
Marc B,

1
@MarcB ten link jest teraz uszkodzony. Czy możesz to naprawić? :)
Phiter

5
Jak powiedział Jovan, zależy to od ułożenia, więc ta odpowiedź jest całkiem błędna.
phil294

117

Możesz pomniejszyć wartość i przekazany parametr:

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

Innym (lepszym) sposobem byłoby użycie COLLATEoperatora, jak wspomniano w dokumentacji


21
Jak wówczas wyglądałoby to SELECToświadczenie COLLATE?
Tak Barry

11
Na powyższej stronie dokumentacji napisano, że „niebinarne porównania ciągów domyślnie nie uwzględniają wielkości liter”.
Per Quested Aronsson

9
Przerażające, ile osób głosowało za odpowiedzią. Jak wyjaśnia powyżej @Marc, w porównaniach nie jest rozróżniana wielkość liter. Musisz zrozumieć zestawienia i indeksy oraz odpowiednio je skonfigurować - użycie transformacji ciągów takich jak LOWER()lub dowolna COLLATEklauzula może całkowicie ominąć indeks, a wraz z upływem czasu, wraz ze wzrostem tabeli, może to mieć drastyczny wpływ na wydajność. Czy to są nazwy użytkowników, których szukasz? Użyj sortowania bez rozróżniania wielkości liter i dodaj unikalny indeks do kolumny. Użyj, EXPLAINaby potwierdzić, że indeks jest używany.
mindplay.dk

1
Już miałem powiedzieć to samo, co mindplay.dk ... górne () i dolne () pomijają indeks i bezpośrednio wpływają na wydajność dużych tabel baz danych.
GTodorov

Zgadzam się zarówno z opiniami mindplay.dk, jak i GTodorova. Zachowaj ostrożność, stosując jakąś metodę na kolumnie docelowej w klauzuli where. Indeks kolumny może być bezużyteczny. Użyj WYJAŚNIJ!
traeper

51

WYKORZYSTAJ BINARY

To jest prosty wybór

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

= 1

To jest wybór z binarnym

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

lub

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

= 0


3
Kiedy ma sens użycie BINARY po tylko jednej stronie znaku = (WYBIERZ * z myTable GDZIE BINARY „coś” = „Coś”)?
Jimmy

@ Jimmy Co dokładnie masz na myśli? Kod działa. Kiedy jedna strona porównania jest rzutowana na binarną, porównanie jest wykonywane binarnie.
Jori,

@Jori Och, chyba źle odczytałem - myślałem, że jeden z dwóch przykładów ma BINARY po obu stronach równości.
Jimmy

Właśnie głosowałem, ponieważ to naprawdę jest właściwa odpowiedź. Zgodnie z dokumentacją na stronie MySQL mówią, że lepiej jest użyć polecenia BINARY, niż próbować typecastować słowa / żądania w określonym języku, ponieważ polecenie BINARY mówi, aby pozostawić wszystko tak, jak jest i używać dokładnie tak, jak jest jest prezentowane. Więc kiedy przyszedłem szukać odpowiedzi - dwie odpowiedzi zaprowadziły mnie na stronę MySQL i przejrzałem ich dokumentację. Korzystanie z BINARY jest lepsze. Tłumaczenie może powodować inne problemy.
Mark Manning

43

Porównania nie uwzględniają wielkości liter, gdy kolumna używa sortowania, które kończy się na _ci(na przykład sortowanie domyślne latin1_general_ci ), i rozróżniają małe i wielkie litery, gdy kolumna używa sortowania, które kończy się na _cslub _bin(np. utf8_unicode_csI utf8_binsortowania).

Sprawdź układanie

Możesz sprawdzić serwer , bazę danych i zestawienia połączeń, używając:

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

i możesz sprawdzić sortowanie tabel za pomocą:

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 |

Zmień układanie

Możesz zmienić sortowanie bazy danych, tabeli lub kolumny na wielkość liter, w następujący sposób:

-- 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;

W twoich porównaniach rozróżniana jest teraz wielkość liter.


25

Porównanie ciągów w wyrażeniu GDZIE nie rozróżnia wielkości liter. Możesz spróbować porównać za pomocą

WHERE `colname` = 'keyword'

lub

WHERE `colname` = 'KeyWord'

i otrzymasz ten sam wynik . To jest domyślne zachowanie MySQL.

Jeśli chcesz, aby porównanie uwzględniało wielkość liter , możesz dodać COLLATEtak:

WHERE `colname` COLLATE latin1_general_cs = 'KeyWord'

Ten SQL dałby inny wynik z tym: WHERE colnameCOLLATE latin1_general_cs = 'keyword'

latin1_general_cs jest powszechnym lub domyślnym zestawieniem w większości baz danych.



9

Domyślnie rozróżniana jest wielkość liter, ale następną najważniejszą rzeczą, na którą powinieneś zwrócić uwagę, jest sposób, w jaki tabela została utworzona, ponieważ możesz określić rozróżnianie wielkości liter podczas tworzenia tabeli.

Poniższy skrypt tworzy tabelę. Zauważ na dole, że jest napisane „COLLATE latin1_general_cs”. To cs na końcu oznacza, że ​​wielkość liter ma znaczenie. Jeśli chcesz, aby w tabeli nie rozróżniano wielkości liter, możesz pominąć tę część lub użyć polecenia „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;

Jeśli Twój projekt umożliwia utworzenie własnej tabeli, sensowne jest określenie preferencji rozróżniania wielkości liter podczas tworzenia tabeli.




2

Zauważ również, że w nazwach tabel rozróżniana jest wielkość liter w systemie Linux, chyba że ustawisz lower_case_table_namedyrektywę config na 1 . Wynika to z faktu, że tabele są reprezentowane przez pliki, w których rozróżniana jest wielkość liter w systemie Linux.

Szczególnie uważaj na rozwój systemu Windows, który nie rozróżnia wielkich i małych liter, i wdrażanie go tam, gdzie jest. Na przykład:

"SELECT * from mytable" 

przeciwko tabeli myTable odniesie sukces w systemie Windows, ale w Linuksie ponownie, chyba że zostanie ustawiona wyżej wspomniana dyrektywa.

Odnośnik tutaj: http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html


1
+1 - Scenariusz pisania zapytań bez rozróżniania wielkości liter, a następnie niepowodzenia na Linuxach zdarzał się często w naszym projekcie
Vic,

@ Vic Mam ten sam problem z moim projektem. Czy możesz mi powiedzieć, jak to naprawiłeś?
Kamran Ahmed

@KamranAhmed, musisz używać obudowy nazw tabel dokładnie tak, jak pojawiają się one w skryptach tworzenia
Vic

@Vic to byłby ostateczność, ponieważ musiałbym modyfikować dosłownie mnóstwo zapytań. Zastanawiałem się, czy byłby to łatwy sposób. W każdym razie dzięki!
Kamran Ahmed

@KamranAhmed, spróbuj zmienić lower_case_table_namezgodnie z odpowiedzią, pod którą komentujemy
Vic

1

Aktualnie akceptowane rozwiązanie jest w większości prawidłowe.

Jeśli używasz łańcucha niebinarnego (CHAR, VARCHAR, TEXT), w porównaniach nie jest rozróżniana wielkość liter , według domyślnego sortowania.

Jeśli używasz ciągu binarnego (BINARY, VARBINARY, BLOB), w porównaniach rozróżniana jest wielkość liter, więc musisz użyć LOWERopisanego w innych odpowiedziach.

Jeśli nie używasz domyślnego sortowania, a używasz łańcucha niebinarnego, o tym, czy wybrano sortowanie, decyduje wielkość liter.

Źródło: https://dev.mysql.com/doc/refman/8.0/en/case-sensitivity.html . Przeczytaj uważnie. Niektórzy inni mylnie stwierdzili, że w porównaniach z konieczności rozróżniana jest wielkość liter lub nie jest uwzględniana wielkość liter. Nie o to chodzi.


0

Możesz tego spróbować. mam nadzieję, że się przyda.

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

0

W polach ciągów z ustawioną flagą binarną zawsze będzie rozróżniana wielkość liter. Jeśli potrzebujesz rozróżnić małe i wielkie litery w polu tekstowym niebinarnym, użyj tego: WYBIERZ „test” REGEXP BINARNY „TEST” JAKO WYNIK;

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.