Podczas próby wykonania procedury wyboru w procedurze przechowywanej w MySQL pojawia się następujący błąd.
Nielegalna kombinacja zestawień (latin1_general_cs, IMPLICIT) i (latin1_general_ci, IMPLICIT) dla operacji „=”
Masz pojęcie, co może tu pójść nie tak?
Zestawienie tabeli to latin1_general_ci
i kolumny w klauzuli where latin1_general_cs
.
Odpowiedzi:
Jest to na ogół spowodowane porównywaniem dwóch ciągów niezgodnego zestawiania lub próbą wybrania danych z różnych zestawień do połączonej kolumny.
Klauzula
COLLATE
pozwala określić sortowanie użyte w zapytaniu.Na przykład poniższa
WHERE
klauzula zawsze podaje opublikowany błąd:Rozwiązaniem jest określenie wspólnego sortowania dla dwóch kolumn w zapytaniu. Oto przykład, który używa
COLLATE
klauzuli:Inną opcją jest użycie
BINARY
operatora:Twoje rozwiązanie może wyglądać mniej więcej tak:
lub,
źródło
COLLATE latin1_general_ci
który powoduje kolejny błąd:COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1''
- nawet jeśli nie masz kolumny z ZNAKIEM ZESTAWU „latin1”! Rozwiązaniem jest użycie obsady BINARY. Zobacz także to pytanieTL; DR
Zmień ułożenie jednego (lub obu) ciągów, aby pasowały do siebie, albo dodaj
COLLATE
klauzulę do wyrażenia.Co to w ogóle jest to „zestawienie”?
Jak udokumentowano w Ogólnych zestawach znaków i zestawieniach :
Dalsze przykłady podano w części Przykłady efektu zestawienia .
Okej, ale w jaki sposób MySQL decyduje, którego sortowania użyć dla danego wyrażenia?
Jak udokumentowano w Collation of Expressions :
Czym więc jest „nielegalna mieszanka zestawień”?
„Nielegalna mieszanka zestawień” występuje, gdy wyrażenie porównuje dwa ciągi różnych zestawień, ale o jednakowym przymusie, a reguły przymusu nie mogą pomóc w rozwiązaniu konfliktu. Jest to sytuacja opisana pod trzecim punktem w powyższym cytacie.
Konkretny błąd podany w pytaniu
Illegal mix of collations (latin1_general_cs,IMPLICIT) and (latin1_general_ci,IMPLICIT) for operation '='
mówi nam, że istniało porównanie równości między dwoma ciągami znaków innej niż Unicode o jednakowej koercyjności. Co więcej, mówi nam, że zestawienia nie zostały podane wprost w instrukcji, ale raczej sugerowane ze źródeł ciągów (takich jak metadane kolumny).To wszystko bardzo dobrze, ale jak rozwiązać takie błędy?
Jak sugerują cytowane powyżej fragmenty ręczne, problem ten można rozwiązać na wiele sposobów, z których dwa są rozsądne i zalecane:
Zmień zestawienie jednego (lub obu) ciągów, aby pasowały do siebie i nie było już żadnych dwuznaczności.
To, jak można to zrobić, zależy od tego, skąd przyszedł ciąg: Wyrażenia dosłowne przyjmują sortowanie określone w
collation_connection
zmiennej systemowej; wartości z tabel pobierają sortowanie określone w ich metadanych kolumnowych.Wymuś, aby jeden łańcuch nie był przymusowy.
Pominąłem następujący cytat z powyższego:
Zatem zwykłe dodanie
COLLATE
klauzuli do jednego z ciągów użytych w porównaniu wymusi użycie tego zestawienia.Podczas gdy inni byliby strasznie złą praktyką, gdyby zostali rozmieszczeni tylko w celu rozwiązania tego błędu:
Zmuś jeden (lub oba) ciągi, aby miały jakąś inną wartość koercyjności, aby mieć pierwszeństwo.
Zastosowanie
CONCAT()
lubCONCAT_WS()
spowoduje łańcuch znaków o koercyjności 1; oraz (jeśli w przechowywanej procedurze) użycie parametrów / zmiennych lokalnych spowodowałoby łańcuchy o koercyjności 2.Zmień kodowanie jednego (lub obu) ciągów, aby jeden był Unicode, a drugi nie.
Można to zrobić poprzez transkodowanie za pomocą ; lub poprzez zmianę podstawowego zestawu znaków danych (np. modyfikację kolumny, zmianę wartości literalnych lub wysłanie ich od klienta w innym kodowaniu i zmianę / dodanie wprowadzającego zestawu znaków). Pamiętaj, że zmiana kodowania spowoduje inne problemy, jeśli niektórych pożądanych znaków nie będzie można zakodować w nowym zestawie znaków.
CONVERT(expr USING transcoding_name)
character_set_connection
character_set_client
Zmień kodowanie jednego (lub obu) ciągów, tak aby były one takie same i zmień jeden ciąg, aby użyć odpowiedniego
_bin
zestawienia.Metody zmiany kodowania i zestawień zostały wyszczególnione powyżej. Takie podejście byłoby mało przydatne, gdyby rzeczywiście trzeba było zastosować bardziej zaawansowane reguły zestawiania, niż te oferowane przez
_bin
zestawienie.źródło
Dodanie mojego 2c do dyskusji dla przyszłych pracowników Google.
Badałem podobny problem, w którym podczas używania funkcji niestandardowych, które otrzymały parametr varchar, wystąpił następujący błąd :
Za pomocą następującego zapytania:
Byłem w stanie powiedzieć, że DB używa utf8_general_ci , podczas gdy tabele zostały zdefiniowane za pomocą utf8_unicode_ci :
Zauważ, że widoki mają sortowanie NULL . Wygląda na to, że widoki i funkcje mają definicje sortowania, nawet jeśli to zapytanie pokazuje wartość null dla jednego widoku. Stosowane sortowanie to sortowanie DB, które zostało zdefiniowane podczas tworzenia widoku / funkcji.
Smutnym rozwiązaniem było zarówno zmiana sortowania db, jak i odtworzenie widoków / funkcji, aby zmusić je do użycia bieżącego sortowania.
Zmiana sortowania bazy danych:
Zmiana sortowania tabeli:
Mam nadzieję, że to komuś pomoże.
źródło
show full columns from my_table;
alter table <TABLE> modify column <COL> varchar(255) collate utf8_general_ci;
SHOW session variables like '%collation%';
mówi ci, że »collation_connection« to »utf8mb4_general_ci«? Następnie biegnijSET collation_connection = utf8mb4_unicode_ci
wcześniej.Czasami konwertowanie zestawów znaków może być niebezpieczne, szczególnie w bazach danych z dużą ilością danych. Myślę, że najlepszą opcją jest użycie operatora „binarnego”:
źródło
Miałem podobny problem, próbowałem użyć procedury FIND_IN_SET ze zmienną łańcuchową .
i otrzymywał błąd
Krótka odpowiedź:
Nie trzeba zmieniać żadnych zmiennych collation_YYYY, wystarczy dodać poprawne sortowanie obok deklaracji zmiennych , tj
Długa odpowiedź:
Najpierw sprawdziłem zmienne sortowania:
Następnie sprawdziłem zestawienie tabel:
Oznacza to, że moja zmienna została skonfigurowana z domyślnym zestawieniem utf8_general_ci, podczas gdy moja tabela została skonfigurowana jako utf8_unicode_ci .
Dodając polecenie COLLATE obok deklaracji zmiennej, sortowanie zmiennych pasowało do sortowania skonfigurowanego dla tabeli.
źródło
Możesz wypróbować ten skrypt , który konwertuje wszystkie twoje bazy danych i tabele na utf8.
źródło
Rozwiązanie w przypadku literałów.
Korzystam z integracji danych Pentaho i nie mogę określić składni sql. Użycie bardzo prostego wyszukiwania DB dało błąd „Nielegalna mieszanka zestawień (cp850_general_ci, COERCIBLE) i (latin1_swedish_ci, COERCIBLE) dla operacji„ = ”„
Wygenerowany kod to „WYBIERZ DATA_DATA JAKO najnowsza_DATA_DATA OD hr_cc_normalised_data_date_v GDZIE PSEUDO_KEY =?”
Krótko mówiąc, przegląd był do widoku i kiedy wydałem
co wyjaśnia, skąd pochodzi „cp850_general_ci”.
Widok został po prostu utworzony za pomocą „SELECT” X ”, ......” Według literałów takich jak ten powinien dziedziczyć ich zestaw znaków i zestawienie z ustawień serwera, które zostały poprawnie zdefiniowane jako „latin1” i „latin1_general_cs”, ponieważ najwyraźniej tak się nie stało. Wymusiłem to w tworzeniu widoku
teraz pokazuje latin1_general_cs dla obu kolumn i błąd zniknął. :)
źródło
MySQL naprawdę nie lubi miksowania zestawień, chyba że może zmusić je do tego samego (co oczywiście nie jest możliwe w twoim przypadku). Czy nie można po prostu zmusić do użycia tego samego zestawienia za pomocą klauzuli COLLATE ? (lub prostszy
BINARY
skrót, jeśli dotyczy ...).źródło
Jeśli kolumny, z którymi masz problem, to „skróty”, rozważ następujące kwestie ...
Jeśli „skrót” jest łańcuchem binarnym, naprawdę powinieneś użyć
BINARY(...)
typu danych.Jeśli „skrót” jest łańcuchem szesnastkowym, nie potrzebujesz utf8 i powinieneś tego unikać ze względu na sprawdzanie znaków itp. Na przykład, MySQL
MD5(...)
daje 32-bajtowy ciąg znaków o stałej długości.SHA1(...)
daje 40-bajtowy ciąg szesnastkowy. Można to zapisać wCHAR(32) CHARACTER SET ascii
(lub 40 dla sha1).Lub jeszcze lepiej zapisz się
UNHEX(MD5(...))
wBINARY(16)
. To zmniejsza o połowę rozmiar kolumny. (Sprawia to jednak, że raczej nie można go wydrukować.)SELECT HEX(hash) ...
Jeśli chcesz, aby był czytelny.Porównanie dwóch
BINARY
kolumn nie ma problemów z sortowaniem.źródło
Bardzo interesujące ... Przygotuj się. Spojrzałem na wszystkie rozwiązania „dodaj zestawienie” i dla mnie są to poprawki pomocy zespołu. W rzeczywistości projekt bazy danych był „zły”. Tak, dodaje się standardowe zmiany i nowe rzeczy, bla bla, ale to nie zmienia faktu, że projekt bazy danych jest zły. Odmawiam pójścia drogą dodawania „sortowania” do wszystkich instrukcji SQL, aby moje zapytanie działało. Jedynym rozwiązaniem, które działa dla mnie i praktycznie wyeliminuje potrzebę poprawiania mojego kodu w przyszłości, jest przeprojektowanie bazy danych / tabel, tak aby pasowały do zestawu znaków, z którym będę żył i który obejmę na dłuższą metę. W takim przypadku wybieram zestaw znaków „ utf8mb4 ”.
Tak więc rozwiązaniem tutaj, gdy pojawia się ten „nielegalny” komunikat o błędzie, jest przeprojektowanie bazy danych i tabel. To jest o wiele łatwiejsze i szybsze niż się wydaje. Eksportowanie danych i ponowne importowanie ich z pliku CSV może nawet nie być wymagane. Zmień zestaw znaków w bazie danych i upewnij się, że wszystkie zestawy znaków w tabelach są zgodne.
Użyj tych poleceń, aby poprowadzić Cię:
Teraz, jeśli lubisz dodawać „zestawiać” tu i tam i wzbogacać swój kod o siły, które wypełniają „nadpisania”, zgadnij.
źródło
Możliwym rozwiązaniem jest konwersja całej bazy danych na UTF8 (patrz także to pytanie ).
źródło
Kolejnym źródłem problemu z zestawieniami jest
mysql.proc
tabela. Sprawdź zestawienia procedur i funkcji przechowywania:Zwróć także uwagę na kolumny
mysql.proc.collation_connection
imysql.proc.character_set_client
.źródło
Jeśli masz zainstalowany phpMyAdmin, możesz postępować zgodnie z instrukcjami podanymi w następującym linku: https://mediatemple.net/community/products/dv/204403914/default-mysql-character-set-and-collation Musisz dopasować zestawienie bazy danych z bazą wszystkich tabel, a także pól tabel, a następnie ponownie skompiluj wszystkie procedury składowane i funkcje. Dzięki temu wszystko powinno znów działać.
źródło
użyłem
ALTER DATABASE mydb DEFAULT COLLATE utf8_unicode_ci;
, ale nie działałem.W tym zapytaniu:
Ta praca dla mnie:
Tak, tylko
concat
.źródło
Ten kod musi być umieszczony wewnątrz Uruchom zapytanie / zapytania SQL w bazie danych
OKNO SQL QUERY
Zastąp nazwę tabeli i nazwę kolumny odpowiednią nazwą.
źródło