Mysql
 sql >> Baza danych >  >> RDS >> Mysql

MySQL Nielegalna mieszanka zestawień

Pomocne jest zrozumienie następujących definicji:

  • kodowanie znaków szczegółowo opisuje, w jaki sposób każdy symbol jest reprezentowany w postaci binarnej (a zatem przechowywany w komputerze). Na przykład symbol é (U+00E9, łacińska mała litera E z ostrym) jest zakodowany jako 0xc3a9 w UTF-8 (które MySQL wywołuje utf8 ) i 0xe9 w Windows-1252 (które MySQL wywołuje latin1 ).

  • Zestaw znaków to alfabet symboli, które mogą być reprezentowane przy użyciu danego kodowania znaków. Myląco, termin ten jest również używany w znaczeniu tego samego, co kodowanie znaków.

  • zestawianie jest porządkiem w zestawie znaków, dzięki czemu łańcuchy mogą być porównywane. Na przykład:latin1_swedish_ci sortowanie traktuje najbardziej akcentowane odmiany znaku jako równoważne znakowi bazowemu, podczas gdy jego latin1_general_ci sortowanie uporządkuje je przed następnym znakiem bazowym, ale nie jest równoważne (są też inne, bardziej znaczące różnice:takie jak kolejność znaków, jak å , ä , ö i ß ).

MySQL zdecyduje, które sortowanie należy zastosować do danego wyrażenia, zgodnie z dokumentacją w Zestawienie wyrażeń :w szczególności zestawienie kolumny ma pierwszeństwo przed zestawieniem literału ciągu.

WHERE klauzula zapytania porównuje następujące ciągi:

  1. wartość w fos_user.username , zakodowane w zestawie znaków kolumny (Windows-1252) i wyrażające preferencje dotyczące jej sortowania latin1_swedish_ci (o wartości koercji 2); z

  2. literał ciągu 'Nrv⧧Kasi' , zakodowane w zestawie znaków połączenia (UTF-8, zgodnie z konfiguracją Doctrine) i wyrażające preferencje dotyczące sortowania połączenia utf8_general_ci (o wartości koercyjności 4).

Ponieważ pierwszy z tych ciągów ma niższą wartość koercyjności niż drugi, MySQL próbuje przeprowadzić porównanie przy użyciu sortowania tego ciągu:latin1_swedish_ci . Aby to zrobić, MySQL próbuje przekonwertować drugi ciąg na latin1 —ale ponieważ znak nie istnieje w tym zestawie znaków, porównanie nie powiedzie się.

Ostrzeżenie

Należy zatrzymać się na chwilę, aby zastanowić się, jak kolumna jest obecnie zakodowana:próbujesz odfiltrować rekordy, w których fos_user.username jest równy łańcuchowi, który zawiera znak, którego nie może istnieją w tej kolumnie !

Jeśli uważasz, że kolumna tak zawierają takie znaki, to prawdopodobnie napisałeś do kolumny, podczas gdy kodowanie znaków połączenia zostało ustawione na coś (np. latin1 ), które spowodowały, że MySQL zinterpretował odebraną sekwencję bajtów jako znaki, które znajdują się w zestawie znaków Windows-1252.

W takim przypadku, zanim przejdziesz dalej, popraw swoje dane!

  1. przekonwertuj takie kolumny na kodowanie znaków, które było używane podczas wstawiania danych, jeśli jest inne niż dotychczasowe kodowanie:

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo;
    
  2. usuń informacje o kodowaniu związane z takimi kolumnami, konwertując je na binary zestaw znaków:

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary;
    
  3. powiązać z takimi kolumnami kodowanie, w którym dane zostały faktycznie przesłane, konwertując je na odpowiedni zestaw znaków.

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET bar;
    

Zwróć uwagę, że w przypadku konwersji z kodowania wielobajtowego może być konieczne zwiększenie rozmiaru kolumny (lub nawet zmiana jej typu), aby pomieścić maksymalną możliwą długość konwertowanego ciągu.

Gdy już mamy pewność, że kolumny są poprawnie zakodowane, można wymusić przeprowadzenie porównania przy użyciu sortowania Unicode przez...

  • jawna konwersja wartości fos_user.username do zestawu znaków Unicode:

    WHERE CONVERT(fos_user.username USING utf8) = ?
    
  • wymuszenie na literale ciągu znaków mniejszej wartości koercyjności niż kolumna (spowoduje niejawną konwersję wartości kolumny na UTF-8):

    WHERE fos_user.username = ? COLLATE utf8_general_ci
    

Można też, jak mówisz, na stałe przekonwertować kolumny na kodowanie Unicode i odpowiednio ustawić ich sortowanie.

Należy wziąć pod uwagę, że kodowanie Unicode zajmuje więcej miejsca niż jednobajtowe zestawy znaków, więc:

  • może być wymagane więcej miejsca;

  • porównania mogą być wolniejsze; i

  • może zaistnieć potrzeba dostosowania długości prefiksu indeksu (zwróć uwagę, że maksymalna liczba jest w bajtach, więc może reprezentować mniej znaków niż poprzednio).

Należy również pamiętać, że zgodnie z dokumentacją w sekcji ALTER TABLE Składnia :



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tworzenie tabeli mysql z jawnym domyślnym zestawem znaków, co jeśli tego nie zrobię?

  2. Jak wyłączyć sprawdzanie klucza obcego w MySQL?

  3. Znajdź wolny pokój (system rezerwacji)

  4. LOAD DATA INFILE łatwo przekonwertować RRRRMMDD na RRRR-MM-DD?

  5. Jak formatować liczby za pomocą przecinków w MySQL