Was ist die beste Zusammenstellung für MySQL mit PHP? [geschlossen]

731

Ich frage mich, ob es in MySQL eine "beste" Auswahl für die Sortierung für eine allgemeine Website gibt, bei der Sie nicht 100% sicher sind, was eingegeben wird. Ich verstehe, dass alle Codierungen gleich sein sollten, wie MySQL, Apache, HTML und alles in PHP.

In der Vergangenheit habe ich PHP so eingestellt, dass es in "UTF-8" ausgegeben wird. Aber welche Sortierung stimmt mit dieser in MySQL überein? Ich denke , es ist eine der UTF-8 ist, aber ich verwendet habe utf8_unicode_ci, utf8_general_ciund utf8_binvor.

Darryl Hein
quelle
35
Randnotiz: MySQLs "utf8" ist nicht richtig UTF-8 (keine Unterstützung für 4+ Byte Unicode-Zeichen wie 𝌆), "utf8mb4" jedoch. Mit utf8 wird beim Einfügen ein Feld abgeschnitten, beginnend mit dem ersten nicht unterstützten Unicode-Zeichen. mathiasbynens.be/notes/mysql-utf8mb4
basic6
6
Ich frage mich, ob wir jemals 5 Bytes für all diese Emojis brauchen werden ... seufz
Álvaro González
1
Verwandte Frage: stackoverflow.com/questions/38228335/… "Welche MySQL- Kollatierung passt genau zum PHP-String-Vergleich?"
William Entriken
Für einen Überblick über die vernünftigen Optionen: monolune.com/mysql-utf8-charsets-and-collations-explained
Flux

Antworten:

618

Der Hauptunterschied besteht in der Sortiergenauigkeit (beim Vergleichen von Zeichen in der Sprache) und der Leistung. Die einzige Besonderheit ist utf8_bin, mit der Zeichen im Binärformat verglichen werden können.

utf8_general_ciist etwas schneller als utf8_unicode_ci, aber weniger genau (zum Sortieren). Die spezifische utf8-Sprachcodierung (z. B. utf8_swedish_ci) enthält zusätzliche Sprachregeln, mit denen sie für diese Sprachen am genauesten sortiert werden können. Die meiste Zeit benutze ich utf8_unicode_ci(ich bevorzuge Genauigkeit gegenüber kleinen Leistungsverbesserungen), es sei denn, ich habe einen guten Grund, eine bestimmte Sprache zu bevorzugen.

Weitere Informationen zu bestimmten Unicode-Zeichensätzen finden Sie im MySQL-Handbuch - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Eran Galperin
quelle
4
kleine Leistungsverbesserungen? Bist du dir da sicher? publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=/… Die von Ihnen ausgewählte Sortierung kann die Leistung von Abfragen in der Datenbank erheblich beeinflussen.
Adam Ramadhan
62
Dies ist für DB2 nicht MySQL. Außerdem gibt es keine konkreten Zahlen oder Benchmarks, sodass Sie sich nur auf die Meinung des Autors stützen.
Eran Galperin
3
Beachten Sie, dass es in MySQL (den meisten derzeit verteilten Versionen) einen Fehler gibt, wenn Sie Funktionen verwenden möchten, bei dem Funktionen die Zeichenfolge immer mit utf8_general_ci zurückgeben. Dies führt zu Problemen, wenn Sie eine andere Sortierung für Ihre Zeichenfolgen verwenden - siehe bugs.mysql.com/ bug.php? id = 24690
El Yobo
1
Aus meiner Erfahrung mit verschiedenen Gebietsschemas würde ich immer verwendenutf8_unicode_*
Shiplu Mokaddim
11
Update: Für neuere Versionen empfehlen utf8mb4und utf8mb4_unicode_520_ci. Diese geben Ihnen den Rest des Chinesischen sowie eine verbesserte Sortierung.
Rick James
129

Eigentlich möchten Sie wahrscheinlich utf8_unicode_cioder verwenden utf8_general_ci.

  • utf8_general_ci sortiert, indem alle Akzente entfernt und sortiert werden, als wäre es ASCII
  • utf8_unicode_ci Verwendet die Unicode-Sortierreihenfolge, sodass die Sortierung in mehreren Sprachen korrekt ist

Wenn Sie dies jedoch nur zum Speichern von englischem Text verwenden, sollten sich diese nicht unterscheiden.

Vegard Larsen
quelle
1
Ich mag deine Erklärung! Gut. Aber ich muss besser verstehen, warum die Unicode-Sortierreihenfolge besser zu sortieren ist, als Akzente zu entfernen.
Weia Design
14
@Adam Es hängt wirklich von Ihrer Zielgruppe ab. Das Sortieren ist ein schwieriges Problem bei der korrekten Lokalisierung. ZB auf Norwegisch sind die Buchstaben Æ Ø Å die letzten 3 des Alphabets. Mit utf8_general_ci werden Ø und Å in O und A konvertiert, wodurch sie beim Sortieren in die völlig falsche Position gebracht werden (ich bin nicht sicher, wie Æ behandelt wird, da es sich um eine Ligatur handelt, nicht um ein Zeichen mit Akzent). Diese Sortierreihenfolge ist in fast jeder Sprache unterschiedlich, z. B. haben Norwegisch und Schwedisch unterschiedliche Ordnungen (und leicht unterschiedliche Buchstaben, die als gleich angesehen werden): Æ Ø Å ist sortiert Å Æ Ø (tatsächliche Buchstaben sind Å Ä Ö). Unicode behebt dies.
Vegard Larsen
Grundsätzlich sage ich also, dass Sie wahrscheinlich eine sprachspezifische Sortierung verwenden sollten, wenn Sie können, aber in den meisten Fällen ist dies nicht möglich. Wählen Sie also die allgemeine Unicode-Sortierung. In manchen Sprachen wird es immer noch seltsam sein, aber korrekter als ASCII.
Vegard Larsen
3
@Manatax - Bei jeder der utf8_-Kollatierungen werden die Daten als utf8 gespeichert. Bei der Zusammenstellung geht es nur darum, welche Zeichen als gleich angesehen werden und wie sie geordnet sind.
Frymaster
2
@frymaster - nicht wahr, gemäß: mathiasbynens.be/notes/mysql-utf8mb4 "Mit mySQLs utf8 können Sie nur 5,88% aller möglichen Unicode-Codepunkte speichern"
Daten
120

Seien Sie sich dieses Problems sehr, sehr bewusst, das bei der Verwendung auftreten kann utf8_general_ci.

MySQL unterscheidet einige Zeichen in ausgewählten Anweisungen nicht, wenn die utf8_general_ciSortierung verwendet wird. Dies kann zu sehr bösen Fehlern führen - insbesondere bei Benutzernamen. Abhängig von der Implementierung, die die Datenbanktabellen verwendet, kann dieses Problem böswilligen Benutzern ermöglichen, einen Benutzernamen zu erstellen, der mit einem Administratorkonto übereinstimmt.

Dieses Problem tritt zumindest in frühen 5.x-Versionen auf - ich bin mir nicht sicher, ob sich dieses Verhalten später geändert hat.

Ich bin kein DBA, aber um dieses Problem zu vermeiden, gehe ich immer mit utf8-bineinem, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird.

Das folgende Skript beschreibt das Problem anhand eines Beispiels.

-- first, create a sandbox to play in
CREATE DATABASE `sandbox`;
use `sandbox`;

-- next, make sure that your client connection is of the same 
-- character/collate type as the one we're going to test next:
charset utf8 collate utf8_general_ci

-- now, create the table and fill it with values
CREATE TABLE `test` (`key` VARCHAR(16), `value` VARCHAR(16) )
    CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO `test` VALUES ('Key ONE', 'value'), ('Key TWO', 'valúe');

-- (verify)
SELECT * FROM `test`;

-- now, expose the problem/bug:
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get BOTH keys here! MySQLs UTF8 collates that are 
-- case insensitive (ending with _ci) do not distinguish between 
-- both values!
--
-- collate 'utf8_bin' doesn't have this problem, as I'll show next:
--

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get just one key now, as you'd expect.
--
-- This problem appears to be specific to utf8. Next, I'll try to 
-- do the same with the 'latin1' charset:
--

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_general_ci

-- next, convert the values that we've previously inserted
-- in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_general_ci;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected). This shows 
-- that the problem with utf8/utf8_generic_ci isn't present 
-- in latin1/latin1_general_ci
--
-- To complete the example, I'll check with the binary collate
-- of latin1 as well:

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected).
--
-- Finally, I'll re-introduce the problem in the exact same 
-- way (for any sceptics out there):

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_generic_ci

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

-- now, re-check for the problem/bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Two keys.
--

DROP DATABASE sandbox;
Guus
quelle
36
-1: Dies wird sicherlich behoben, indem ein eindeutiger Schlüssel auf die entsprechende Spalte angewendet wird. Sie würden das gleiche Verhalten sehen, wenn die beiden Werte 'value'und wären 'valUe'. Der springende Punkt einer Kollatierung ist, dass sie (unter anderem) Regeln bereitstellt, wenn zwei Zeichenfolgen als gleich angesehen werden.
Hammerite
13
Das ist genau das Problem, das ich zu veranschaulichen versuche - die Kollatierung macht zwei Dinge gleich, obwohl sie eigentlich gar nicht gleich sein sollen (und daher ist eine eindeutige Einschränkung genau das Gegenteil von dem, was Sie erreichen möchten).
Guus
18
Sie beschreiben es jedoch als "Problem" und führen zu "Fehlern", wenn das Verhalten genau dem entspricht, was mit einer Kollatierung erreicht werden soll. Ihre Beschreibung ist korrekt, jedoch nur insoweit, als es ein Fehler des DBA ist, eine unangemessene Sortierung auszuwählen.
Hammerite
32
Die Sache ist, dass, wenn Sie zwei Benutzernamen eingeben, die von der Sortierung als gleich angesehen werden, es nicht zulässig ist, wenn Sie den Benutzernamen in der Spalte eindeutig festlegen, was Sie natürlich tun sollten!
Student von Hogwarts
12
Ich habe sowohl diese Antwort als auch den Kommentar von @ Hammerite positiv bewertet, da beide zusammen mir geholfen haben, ein Verständnis der Kollatierung zu erreichen.
Nacht - Wiedereinsetzung Monica
86

Verwenden Sie am besten einen Zeichensatz für utf8mb4die Sortierung utf8mb4_unicode_ci.

Der Zeichensatz utf8unterstützt nur eine kleine Anzahl von UTF-8-Codepunkten, etwa 6% der möglichen Zeichen. utf8unterstützt nur das Basic Multilingual Plane (BMP). Es gibt 16 andere Flugzeuge. Jede Ebene enthält 65.536 Zeichen. utf8mb4unterstützt alle 17 Flugzeuge.

MySQL schneidet 4-Byte-UTF-8-Zeichen ab, was zu beschädigten Daten führt.

Der utf8mb4Zeichensatz wurde am 24.03.2010 in MySQL 5.5.3 eingeführt.

Einige der erforderlichen Änderungen zur Verwendung des neuen Zeichensatzes sind nicht trivial:

  • Möglicherweise müssen Änderungen an Ihrem Anwendungsdatenbankadapter vorgenommen werden.
  • An my.cnf müssen Änderungen vorgenommen werden, einschließlich des Festlegens des Zeichensatzes, der Sortierung und des Umschaltens von innodb_file_format auf Barracuda
  • SQL CREATE-Anweisungen müssen möglicherweise Folgendes enthalten: ROW_FORMAT=DYNAMIC
    • DYNAMISCH ist für Indizes für VARCHAR (192) und höher erforderlich.

HINWEIS: Beim Umschalten auf Barracudavon Antelopemuss der MySQL-Dienst möglicherweise mehrmals neu gestartet werden. innodb_file_format_maxändert sich erst, nachdem der MySQL-Dienst neu gestartet wurde auf : innodb_file_format = barracuda.

MySQL verwendet das alte AntelopeInnoDB-Dateiformat. Barracudaunterstützt dynamische Zeilenformate, die Sie benötigen, wenn Sie die SQL-Fehler zum Erstellen von Indizes und Schlüsseln nach dem Wechsel zum Zeichensatz nicht feststellen möchten:utf8mb4

  • # 1709 - Indexspaltengröße zu groß. Die maximale Spaltengröße beträgt 767 Byte.
  • # 1071 - Der angegebene Schlüssel war zu lang. Die maximale Schlüssellänge beträgt 767 Byte

Das folgende Szenario wurde unter MySQL 5.6.17 getestet: Standardmäßig ist MySQL folgendermaßen konfiguriert:

SHOW VARIABLES;

innodb_large_prefix = OFF
innodb_file_format = Antelope

Beenden Sie Ihren MySQL-Dienst und fügen Sie die Optionen zu Ihrer vorhandenen my.cnf hinzu:

[client]
default-character-set= utf8mb4

[mysqld]
explicit_defaults_for_timestamp = true
innodb_large_prefix = true
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_per_table = true

# Character collation
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci

Beispiel einer SQL CREATE-Anweisung:

CREATE TABLE Contacts (
 id INT AUTO_INCREMENT NOT NULL,
 ownerId INT DEFAULT NULL,
 created timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 contact VARCHAR(640) NOT NULL,
 prefix VARCHAR(128) NOT NULL,
 first VARCHAR(128) NOT NULL,
 middle VARCHAR(128) NOT NULL,
 last VARCHAR(128) NOT NULL,
 suffix VARCHAR(128) NOT NULL,
 notes MEDIUMTEXT NOT NULL,
 INDEX IDX_CA367725E05EFD25 (ownerId),
 INDEX created (created),
 INDEX modified_idx (modified),
 INDEX contact_idx (contact),
 PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT=DYNAMIC;
  • Sie können den Fehler # 1709 sehen, der generiert wurde, INDEX contact_idx (contact)wenn ROW_FORMAT=DYNAMICer aus der CREATE-Anweisung entfernt wurde.

HINWEIS: Durch Ändern des Index auf maximal 128 Zeichen contactentfällt die Verwendung von Barracuda mitROW_FORMAT=DYNAMIC

INDEX contact_idx (contact(128)),

Beachten Sie auch: Wenn die Größe des Felds angegeben ist VARCHAR(128), sind dies nicht 128 Byte. Sie können 128, 4-Byte-Zeichen oder 128, 1-Byte-Zeichen verwenden.

Diese INSERTAnweisung sollte das 4-Byte-Zeichen 'poo' in der 2-Zeile enthalten:

INSERT INTO `Contacts` (`id`, `ownerId`, `created`, `modified`, `contact`, `prefix`, `first`, `middle`, `last`, `suffix`, `notes`) VALUES
(1, NULL, '0000-00-00 00:00:00', '2014-08-25 03:00:36', '1234567890', '12345678901234567890', '1234567890123456789012345678901234567890', '1234567890123456789012345678901234567890', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678', '', ''),
(2, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', ''),
(3, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '123💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', '');

Sie können den von der lastSpalte verwendeten Speicherplatz anzeigen:

mysql> SELECT BIT_LENGTH(`last`), CHAR_LENGTH(`last`) FROM `Contacts`;
+--------------------+---------------------+
| BIT_LENGTH(`last`) | CHAR_LENGTH(`last`) |
+--------------------+---------------------+
|               1024 |                 128 | -- All characters are ASCII
|               4096 |                 128 | -- All characters are 4 bytes
|               4024 |                 128 | -- 3 characters are ASCII, 125 are 4 bytes
+--------------------+---------------------+

In Ihrem Datenbankadapter möchten Sie möglicherweise den Zeichensatz und die Sortierung für Ihre Verbindung festlegen:

SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'

In PHP wäre dies eingestellt für: \PDO::MYSQL_ATTR_INIT_COMMAND

Verweise:

Jeremy Postlethwaite
quelle
Weitere Informationen über Wikipedia: Unicode-Flugzeuge
Jeremy Postlethwaite
6
utf8mb4_unicode_ci sollte unbedingt die empfohlene Zusammenstellung für neue Projekte im Jahr 2015 sein.
Trevor Gehman
7
Update ... utf8mb4_unicode_520_ciist besser. In Zukunft wird es utf8mb4_unicode_800_ci(oder so etwas) geben, wenn MySQL die Unicode-Standards einholt.
Rick James
46

Kollatierungen beeinflussen, wie Daten sortiert werden und wie Zeichenfolgen miteinander verglichen werden. Das heißt, Sie sollten die Sortierung verwenden, die die meisten Ihrer Benutzer erwarten.

Beispiel aus der Dokumentation zum Zeichensatz-Unicode :

utf8_general_ciist auch für Deutsch und Französisch zufriedenstellend, außer dass 'ß' gleich 's' und nicht 'ss' ist. Wenn dies für Ihre Anwendung akzeptabel ist, sollten Sie es verwenden, utf8_general_cida es schneller ist. Andernfalls verwenden utf8_unicode_ciSie , weil es genauer ist.

Also - es hängt von Ihrer erwarteten Benutzerbasis ab und davon, wie viel Sie korrekt sortieren müssen. Für eine englische Benutzerbasis utf8_general_cisollte ausreichen, für andere Sprachen wie Schwedisch wurden spezielle Kollatierungen erstellt.

Tomalak
quelle
1
Ich habe utf8_general_ci verwendet und es hat ein paar Sekunden gedauert, während das Sortieren und armcii_general_ci es extrem schnell gemacht hat. Warum ist das passiert? Noch eine Frage: Was denkst du, welche Sortierung von Social-Networking-Sites verwendet wird
22

Im Wesentlichen hängt es davon ab, wie Sie über eine Zeichenfolge denken.

Ich benutze immer utf8_bin wegen des von Guus hervorgehobenen Problems. Meiner Meinung nach ist eine Zeichenfolge in Bezug auf die Datenbank immer noch nur eine Zeichenfolge. Eine Zeichenfolge besteht aus mehreren UTF-8-Zeichen. Ein Zeichen hat eine binäre Darstellung. Warum muss es die Sprache kennen, die Sie verwenden? Normalerweise erstellen Benutzer Datenbanken für Systeme mit dem Umfang für mehrsprachige Websites. Dies ist der springende Punkt bei der Verwendung von UTF-8 als Zeichensatz. Ich bin ein bisschen puristisch, aber ich denke, das Fehlerrisiko überwiegt stark den leichten Vorteil, den Sie bei der Indizierung erhalten können. Alle sprachbezogenen Regeln sollten auf einer viel höheren Ebene als das DBMS durchgeführt werden.

In meinen Büchern sollte "Wert" in einer Million Jahren niemals gleich "Wert" sein.

Wenn ich ein Textfeld speichern und eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung durchführen möchte, verwende ich MYSQL-Zeichenfolgenfunktionen mit PHP-Funktionen wie LOWER () und der PHP-Funktion strtolower ().

Phil
quelle
9
Wenn der binäre Vergleich von Zeichenfolgen Ihr gewünschter Vergleich ist, sollten Sie natürlich die binäre Sortierung verwenden. Wenn Sie jedoch alternative Kollatierungen als "Fehlerrisiko" abtun oder nur zur Vereinfachung der Indizierung dienen, bedeutet dies, dass Sie den Punkt einer Kollatierung nicht vollständig verstehen.
Hammerite
13

Für UTF-8-Textinformationen sollten Sie verwenden, utf8_general_ciweil ...

  • utf8_bin: Vergleichen Sie Zeichenfolgen mit dem Binärwert jedes Zeichens in der Zeichenfolge

  • utf8_general_ci: Vergleichen Sie Zeichenfolgen mit allgemeinen Sprachregeln und mit Vergleichen ohne Berücksichtigung der Groß- und Kleinschreibung

aka es wird das Suchen und Indizieren der Daten schneller / effizienter / nützlicher machen.

Mepcotterell
quelle
12

Die akzeptierte Antwort schlägt ziemlich definitiv vor, utf8_unicode_ci zu verwenden, und während das für neue Projekte großartig ist, wollte ich meine jüngsten gegenteiligen Erfahrungen nur für den Fall erzählen, dass es jemandem Zeit spart.

Da utf8_general_ci die Standardkollatierung für Unicode in MySQL ist, müssen Sie utf8_unicode_ci an vielen Stellen angeben, wenn Sie utf8_unicode_ci verwenden möchten .

Beispielsweise haben alle Clientverbindungen nicht nur einen Standardzeichensatz (für mich sinnvoll), sondern auch eine Standardkollatierung (dh die Kollatierung wird für Unicode immer standardmäßig utf8_general_ci verwendet).

Wenn Sie utf8_unicode_ci für Ihre Felder verwenden, müssen Ihre Skripts, die eine Verbindung zur Datenbank herstellen, wahrscheinlich aktualisiert werden, um die gewünschte Sortierung explizit zu erwähnen. Andernfalls können Abfragen mit Textzeichenfolgen fehlschlagen, wenn Ihre Verbindung die Standardkollatierung verwendet.

Das Ergebnis ist, dass Sie beim Konvertieren eines vorhandenen Systems beliebiger Größe in Unicode / utf8 möglicherweise gezwungen sind, utf8_general_ci zu verwenden, da MySQL die Standardeinstellungen behandelt.

George Lund
quelle
8

Für den von Guus hervorgehobenen Fall würde ich dringend empfehlen, entweder utf8_unicode_cs (Groß- und Kleinschreibung beachten, strikte Übereinstimmung, größtenteils korrekte Reihenfolge) anstelle von utf8_bin (strikte Übereinstimmung, falsche Reihenfolge) zu verwenden.

Wenn das Feld durchsucht werden soll, anstatt für einen Benutzer abgeglichen zu werden, verwenden Sie utf8_general_ci oder utf8_unicode_ci. Bei beiden wird die Groß- und Kleinschreibung nicht berücksichtigt, man wird verlieren ('ß' ist gleich 's' und nicht 'ss'). Es gibt auch sprachspezifische Versionen wie utf8_german_ci, bei denen der Lose Matching besser für die angegebene Sprache geeignet ist.

[Bearbeiten - fast 6 Jahre später]

Ich empfehle den Zeichensatz "utf8" unter MySQL nicht mehr und empfehle stattdessen den Zeichensatz "utf8mb4". Sie stimmen fast vollständig überein, erlauben jedoch ein wenig (viel) mehr Unicode-Zeichen.

Realistisch gesehen hätte MySQL den Zeichensatz "utf8" und die entsprechenden Kollatierungen so aktualisieren müssen, dass sie mit der Spezifikation "utf8" übereinstimmen. Stattdessen sollte ein separater Zeichensatz und entsprechende Kollatierungen die Speicherbezeichnung für diejenigen nicht beeinflussen, die bereits ihren unvollständigen Zeichensatz "utf8" verwenden .

SEoF
quelle
5
Zu Ihrer Information: utf8_unicode_csexistiert nicht. Die einzige Groß- und Kleinschreibung ist utf8 utf8_bin. Das Problem ist, dass die utf8_binSortierung falsch ist. Siehe: stackoverflow.com/questions/15218077/…
Costa
1
Danke für das Update!
Prometheus
2

Fügen Sie in Ihrer Datenbank-Upload-Datei vor jeder Zeile die folgende Zeile ein:

SET NAMES utf8;

Und dein Problem sollte gelöst sein.

Tapos Ghosh
quelle
2
Lesen Sie eine Frage: In der Vergangenheit habe ich PHP so eingestellt, dass es in "UTF-8" ausgegeben wird. Aber welche Sortierung stimmt mit dieser in MySQL überein? Ich denke, es ist eines der UTF-8-Modelle, aber ich habe zuvor utf8_unicode_ci, utf8_general_ci und utf8_bin verwendet.
Jitesh Sojitra
5
Diese Antwort hat nichts mit der Frage zu tun. Darüber hinaus SET NAMESinformiert das direkte Ausgeben einer Abfrage den Client nicht über die Codierung und kann bestimmte Funktionen wie vorbereitete Anweisungen auf sehr subtile Weise beschädigen.
Álvaro González