Beim Versuch, eine Auswahl über eine in MySQL gespeicherte Prozedur durchzuführen, wird der folgende Fehler angezeigt.
Unzulässige Mischung von Kollatierungen (latin1_general_cs, IMPLICIT) und (latin1_general_ci, IMPLICIT) für die Operation '='
Irgendeine Idee, was hier falsch laufen könnte?
Die Sortierung der Tabelle ist latin1_general_ci
und die der Spalte in der where-Klausel latin1_general_cs
.
Antworten:
Dies wird im Allgemeinen durch den Vergleich zweier Zeichenfolgen inkompatibler Kollatierung oder durch den Versuch verursacht, Daten unterschiedlicher Kollatierung in einer kombinierten Spalte auszuwählen.
Mit dieser Klausel
COLLATE
können Sie die in der Abfrage verwendete Sortierung angeben.Beispielsweise gibt die folgende
WHERE
Klausel immer den Fehler aus, den Sie gepostet haben:Ihre Lösung besteht darin, eine gemeinsame Sortierung für die beiden Spalten in der Abfrage anzugeben. Hier ist ein Beispiel, das die
COLLATE
Klausel verwendet:Eine andere Option ist die Verwendung des
BINARY
Operators:Ihre Lösung könnte ungefähr so aussehen:
oder,
quelle
COLLATE latin1_general_ci
einen Fehler gibt, der einen weiteren Fehler verursacht:COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1''
- Auch wenn Sie keine Spalte mit CHARACTER SET 'latin1' haben! Die Lösung besteht darin, die BINARY-Besetzung zu verwenden. Siehe auch diese FrageTL; DR
Ändern Sie entweder die Sortierung einer (oder beider) Zeichenfolgen so, dass sie übereinstimmen, oder fügen Sie
COLLATE
Ihrem Ausdruck eine Klausel hinzu.Was ist das für eine "Zusammenstellung"?
Wie unter Zeichensätze und Kollatierungen im Allgemeinen dokumentiert :
Weitere Beispiele finden Sie unter Beispiele für den Effekt der Kollatierung .
Okay, aber wie entscheidet MySQL, welche Sortierung für einen bestimmten Ausdruck verwendet werden soll?
Wie unter Zusammenstellung von Ausdrücken dokumentiert :
Was ist also eine "illegale Mischung von Kollatierungen"?
Eine "illegale Mischung von Kollatierungen" tritt auf, wenn ein Ausdruck zwei Zeichenfolgen unterschiedlicher Kollatierungen, aber gleicher Zwangsfähigkeit vergleicht und die Zwangsregeln nicht zur Lösung des Konflikts beitragen können. Dies ist die Situation, die unter dem dritten Punkt im obigen Zitat beschrieben ist.
Der in der Frage angegebene besondere Fehler zeigt
Illegal mix of collations (latin1_general_cs,IMPLICIT) and (latin1_general_ci,IMPLICIT) for operation '='
, dass es einen Gleichheitsvergleich zwischen zwei Nicht-Unicode-Zeichenfolgen mit gleicher Zwangsfähigkeit gab. Außerdem erfahren wir, dass die Kollatierungen nicht explizit in der Anweisung angegeben wurden, sondern aus den Quellen der Zeichenfolgen (z. B. Spaltenmetadaten) stammen.Das ist alles sehr gut, aber wie löst man solche Fehler?
Wie aus den oben zitierten manuellen Auszügen hervorgeht, kann dieses Problem auf verschiedene Weise gelöst werden, von denen zwei sinnvoll und zu empfehlen sind:
Ändern Sie die Sortierung einer (oder beider) Zeichenfolgen so, dass sie übereinstimmen und keine Mehrdeutigkeit mehr besteht.
Wie dies getan werden kann, hängt davon ab, woher die Zeichenfolge stammt: Literale Ausdrücke verwenden die in der
collation_connection
Systemvariablen angegebene Kollatierung. Werte aus Tabellen verwenden die in ihren Spaltenmetadaten angegebene Sortierung.Erzwinge, dass eine Saite nicht erzwungen werden kann.
Ich habe das folgende Zitat oben weggelassen:
Durch einfaches Hinzufügen einer
COLLATE
Klausel zu einer der im Vergleich verwendeten Zeichenfolgen wird die Verwendung dieser Kollatierung erzwungen.Während die anderen eine schrecklich schlechte Praxis wären, wenn sie nur zur Behebung dieses Fehlers eingesetzt würden:
Erzwingen Sie, dass eine (oder beide) der Zeichenfolgen einen anderen Koerzitivfeldwert haben, damit einer Vorrang hat.
Die Verwendung von
CONCAT()
oderCONCAT_WS()
würde zu einer Zeichenfolge mit einer Zwangsfähigkeit von 1 führen; und (wenn in einer gespeicherten Routine) die Verwendung von Parametern / lokalen Variablen würde zu Zeichenfolgen mit einer Zwangsfähigkeit von 2 führen.Ändern Sie die Codierungen einer (oder beider) Zeichenfolgen so, dass eine Unicode ist und die andere nicht.
Dies könnte durch Transcodieren mit erfolgen ; oder durch Ändern des zugrunde liegenden Zeichensatzes der Daten (z. B. Ändern der Spalte, Ändern von Literalwerten oder Senden dieser vom Client in einer anderen Codierung und Ändern / Hinzufügen eines Zeichensatz-Einführers). Beachten Sie, dass das Ändern der Codierung zu anderen Problemen führt, wenn einige gewünschte Zeichen im neuen Zeichensatz nicht codiert werden können.
CONVERT(expr USING transcoding_name)
character_set_connection
character_set_client
Ändern Sie die Codierungen einer (oder beider) Zeichenfolgen so, dass beide gleich sind, und ändern Sie eine Zeichenfolge, um die entsprechende
_bin
Sortierung zu verwenden.Verfahren zum Ändern von Codierungen und Kollatierungen wurden oben detailliert beschrieben. Dieser Ansatz wäre wenig nützlich, wenn tatsächlich fortgeschrittenere Kollatierungsregeln angewendet werden müssten, als die
_bin
Kollatierung bietet .quelle
Hinzufügen meiner 2c zur Diskussion für zukünftige Googler.
Ich habe ein ähnliches Problem untersucht, bei dem bei Verwendung benutzerdefinierter Funktionen , die einen varchar-Parameter erhalten haben, der folgende Fehler aufgetreten ist:
Verwenden Sie die folgende Abfrage:
Ich konnte feststellen, dass die Datenbank utf8_general_ci verwendet , während die Tabellen mit utf8_unicode_ci definiert wurden :
Beachten Sie, dass die Ansichten eine NULL- Sortierung haben. Es scheint, dass Ansichten und Funktionen Kollatierungsdefinitionen haben, obwohl diese Abfrage für eine Ansicht null anzeigt. Die verwendete Kollatierung ist die DB-Kollatierung, die beim Erstellen der Ansicht / Funktion definiert wurde.
Die traurige Lösung bestand darin, sowohl die Datenbankkollatierung zu ändern als auch die Ansichten / Funktionen neu zu erstellen, um sie zu zwingen, die aktuelle Kollatierung zu verwenden.
Ändern der Kollatierung der Datenbank:
Ändern der Tabellensortierung:
Ich hoffe das wird jemandem helfen.
quelle
show full columns from my_table;
alter table <TABLE> modify column <COL> varchar(255) collate utf8_general_ci;
SHOW session variables like '%collation%';
sagt aber , dass »collation_connection« »utf8mb4_general_ci« ist? DannSET collation_connection = utf8mb4_unicode_ci
vorher laufen .Manchmal kann es gefährlich sein, Zeichensätze zu konvertieren, insbesondere in Datenbanken mit großen Datenmengen. Ich denke, die beste Option ist die Verwendung des "binären" Operators:
quelle
Ich hatte ein ähnliches Problem, wurde versucht , die FIND_IN_SET Prozedur mit einer Zeichenfolge zu verwenden Variable .
und erhielt den Fehler
Kurze Antwort:
Sie müssen keine Variablen collation_YYYY ändern. Fügen Sie einfach die richtige Kollatierung neben Ihrer Variablendeklaration hinzu , d. H.
Lange Antwort:
Ich habe zuerst die Kollatierungsvariablen überprüft:
Dann habe ich die Tabellensortierung überprüft:
Dies bedeutet, dass meine Variable mit der Standardkollatierung von utf8_general_ci konfiguriert wurde, während meine Tabelle als utf8_unicode_ci konfiguriert wurde .
Durch Hinzufügen des Befehls COLLATE neben der Variablendeklaration stimmte die Variablenkollatierung mit der für die Tabelle konfigurierten Kollatierung überein.
quelle
Sie können dieses Skript ausprobieren , das alle Ihre Datenbanken und Tabellen in utf8 konvertiert.
quelle
Lösung, wenn Literale beteiligt sind.
Ich verwende Pentaho Data Integration und kann die SQL-Syntax nicht angeben. Die Verwendung einer sehr einfachen DB-Suche ergab den Fehler "Unzulässige Mischung von Kollatierungen (cp850_general_ci, COERCIBLE) und (latin1_swedish_ci, COERCIBLE) für die Operation '='".
Der generierte Code war "SELECT DATA_DATE AS latest_DATA_DATE FROM hr_cc_normalised_data_date_v WHERE PSEUDO_KEY =?"
Um die Geschichte kurz zu fassen, war die Suche nach einer Ansicht und als ich herausgab
das erklärt, woher das 'cp850_general_ci' kommt.
Die Ansicht wurde einfach mit 'SELECT' X 'erstellt, ......' Laut den manuellen Literalen sollten solche ihren Zeichensatz und ihre Sortierung von Servereinstellungen erben, die korrekt als 'latin1' und 'latin1_general_cs' definiert wurden Offensichtlich ist es nicht passiert. Ich habe es bei der Erstellung der Ansicht erzwungen
Jetzt wird latin1_general_cs für beide Spalten angezeigt und der Fehler ist behoben. :) :)
quelle
MySQL mag es wirklich nicht, Kollatierungen zu mischen, es sei denn, es kann sie zu derselben zwingen (was in Ihrem Fall eindeutig nicht möglich ist). Können Sie nicht einfach die Verwendung derselben Kollatierung über eine COLLATE-Klausel erzwingen ? (oder die einfachere
BINARY
Verknüpfung, falls zutreffend ...).quelle
Wenn die Spalten, mit denen Sie Probleme haben, "Hashes" sind, beachten Sie Folgendes ...
Wenn der "Hash" eine binäre Zeichenfolge ist, sollten Sie wirklich den
BINARY(...)
Datentyp verwenden.Wenn der "Hash" eine Hex-Zeichenfolge ist, benötigen Sie utf8 nicht und sollten dies aufgrund von Zeichenprüfungen usw. vermeiden. Beispielsweise
MD5(...)
liefert MySQL eine Hex-Zeichenfolge mit fester Länge von 32 Byte.SHA1(...)
gibt eine 40-Byte-Hex-Zeichenfolge. Dies könnte inCHAR(32) CHARACTER SET ascii
(oder 40 für sha1) gespeichert werden .Oder, noch besser, speichert
UNHEX(MD5(...))
inBINARY(16)
. Dies halbiert die Größe der Säule. (Es macht es jedoch ziemlich unbedruckbar.)SELECT HEX(hash) ...
Wenn Sie möchten, dass es lesbar ist.Beim Vergleichen von zwei
BINARY
Spalten treten keine Sortierprobleme auf.quelle
Sehr interessant ... Jetzt sei bereit. Ich habe mir alle "Add Collate" -Lösungen angesehen und für mich sind dies Pflasterkorrekturen. Die Realität ist, dass das Datenbankdesign "schlecht" war. Ja, Standardänderungen und neue Dinge werden hinzugefügt, bla bla, aber es ändert nichts an der Tatsache, dass das Datenbankdesign schlecht ist. Ich lehne es ab, alle SQL-Anweisungen mit "sortieren" zu versehen, damit meine Abfrage funktioniert. Die einzige Lösung, die für mich funktioniert und die Notwendigkeit, meinen Code in Zukunft zu optimieren, praktisch überflüssig macht, besteht darin, die Datenbank / Tabellen so zu gestalten, dass sie dem Zeichensatz entsprechen, mit dem ich leben und den ich langfristig annehmen werde. In diesem Fall entscheide ich mich für den Zeichensatz " utf8mb4 ".
Die Lösung hier, wenn Sie auf diese "illegale" Fehlermeldung stoßen, besteht darin, Ihre Datenbank und Tabellen neu zu gestalten. Es ist viel einfacher und schneller als es sich anhört. Das Exportieren und erneute Importieren Ihrer Daten aus einer CSV ist möglicherweise nicht einmal erforderlich. Ändern Sie den Zeichensatz der Datenbank und stellen Sie sicher, dass alle Zeichensätze Ihrer Tabellen übereinstimmen.
Verwenden Sie diese Befehle, um Sie zu führen:
Wenn Sie es genießen, hier und da "zusammenstellen" hinzuzufügen und Ihren Code mit erzwungenen "Überschreibungen" zu verstärken, sollten Sie raten.
quelle
Eine mögliche Lösung besteht darin , die gesamte Datenbank in UTF8 zu konvertieren (siehe auch diese Frage ).
quelle
Eine weitere Ursache für das Problem mit Kollatierungen ist die
mysql.proc
Tabelle. Überprüfen Sie die Zusammenstellungen Ihrer Speicherverfahren und -funktionen:Achten Sie auch auf
mysql.proc.collation_connection
undmysql.proc.character_set_client
Spalten.quelle
Wenn Sie phpMyAdmin installiert haben, können Sie den Anweisungen unter folgendem Link folgen: https://mediatemple.net/community/products/dv/204403914/default-mysql-character-set-and-collation Sie müssen mit der Sortierung übereinstimmen der Datenbank mit der aller Tabellen sowie der Felder der Tabellen und kompilieren dann alle gespeicherten Prozeduren und Funktionen neu. Damit sollte alles wieder funktionieren.
quelle
ich benutzte
ALTER DATABASE mydb DEFAULT COLLATE utf8_unicode_ci;
, aber nicht funktioniert.In dieser Abfrage:
Diese Arbeit für mich:
Ja, nur a
concat
.quelle
Dieser Code muss in Run SQL Query / Queries on Database eingefügt werden
SQL QUERY WINDOW
Bitte ersetzen Sie Tabellenname und Spaltenname durch den entsprechenden Namen.
quelle