Ich versuche, Namen von Benutzern eines Dienstes in meiner MySQL-Datenbank zu speichern. Diese Namen können Emojis wie 🙈😂😱🍰 enthalten (nur für Beispiele)
Nachdem ich ein wenig gesucht hatte, fand ich diesen Stapelüberlauf , der mit diesem Tutorial verknüpft war . Ich habe die Schritte befolgt und es sieht so aus, als ob alles richtig konfiguriert ist.
Ich habe eine Datenbank (Zeichensatz und Sortierung auf utf8mb4 (_unicode_ci) eingestellt), eine ebenfalls so konfigurierte Tabelle namens TestTable sowie eine auf diese Weise konfigurierte Spalte "Text" (VARCHAR (191) utf8mb4_unicode_ci).
Wenn ich versuche, Emojis zu speichern, wird folgende Fehlermeldung angezeigt:
Example of error for shortcake (🍰):
Warning: #1300 Invalid utf8 character string: 'F09F8D'
Warning: #1366 Incorrect string value: '\xF0\x9F\x8D\xB0' for column 'Text' at row 1
Das einzige Emoji, das ich richtig retten konnte, war die Sonne ☀️
Obwohl ich nicht alle ausprobiert habe, um ehrlich zu sein.
Fehlt mir etwas in der Konfiguration?
Bitte beachten Sie: An allen Speichertests war keine Client-Seite beteiligt. Ich benutze phpmyadmin, um die Werte manuell zu ändern und die Daten zu speichern. Die richtige Konfiguration der Client-Seite ist etwas, um das ich mich kümmern werde, nachdem der Server Emojis richtig gespeichert hat.
Noch eine Nebenbemerkung : Derzeit erhalte ich beim Speichern von Emojis entweder den oben beschriebenen Fehler oder erhalte keinen Fehler und die Daten von Username 🍰
werden als gespeichert Username ????
. Fehler oder kein Fehler hängen davon ab, wie ich speichere. Beim Erstellen / Speichern über eine SQL-Anweisung speichere ich mit Fragezeichen, beim Bearbeiten inline speichere ich mit Fragezeichen, beim Bearbeiten mit der Schaltfläche Bearbeiten erhalte ich den Fehler.
Vielen Dank
EDIT 1: Okay, ich denke, ich habe das Problem herausgefunden, aber nicht die Lösung. Es sieht so aus, als hätten sich die datenbankspezifischen Variablen nicht richtig geändert.
Wenn ich auf meinem Server als root angemeldet bin und die Variablen auslese (global):
Verwendete Abfrage:SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)
Für meine Datenbank (in phpmyadmin dieselbe Abfrage) sieht es folgendermaßen aus:
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
Wie kann ich diese Einstellungen für die jeweilige Datenbank anpassen? Auch wenn ich die ersten angezeigten Einstellungen als Standard habe, erhalte ich beim Erstellen einer neuen Datenbank die zweite als Einstellungen.
Bearbeiten 2:
Hier ist meine my.cnf
Datei:
[client]
port=3306
socket=/var/run/mysqld/mysqld.sock
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld_safe]
socket=/var/run/mysqld/mysqld.sock
[mysqld]
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
port=3306
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
lc-messages-dir=/usr/share/mysql
log_error=/var/log/mysql/error.log
max_connections=200
max_user_connections=30
wait_timeout=30
interactive_timeout=50
long_query_time=5
innodb_file_per_table
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
!includedir /etc/mysql/conf.d/
$cfg["DefaultCharset"]
in Ihrer PMA-Konfiguration?$cfg["DefaultCharset"]
. Ich habe es nachgeschlagenetc/phpmyadmin/config.inc.php
. Nicht da drin.Antworten:
character_set_client
,_connection
Und_results
sein müssen alleutf8mb4
für das shortcake essbar zu sein.Irgendwo setzt etwas eine Teilmenge davon einzeln. Stöbern Sie in den Einstellungen von my.cnf und phpmyadmin - etwas setzt nicht alle drei.
Wenn
SET NAMES utf8mb4
ausgeführt, werden alle drei korrekt eingestellt.Die Sonne schien, weil es nur 3 Bytes sind -
E2 98 80
; utf8 reicht für 3-Byte-utf8-Codierungen von Unicode-Zeichen aus.quelle
utf8mb4
. Wenn Sie nicht finden, wo Sie das tun sollen, führen Sie es ausSET NAMES utf8mb4
.mysql_query("SET NAMES 'utf8mb4'");
das ist richtig;)Es ist wahrscheinlich, dass Ihr Dienst / Ihre Anwendung für den Client-Zeichensatz eine Verbindung mit "utf8" anstelle von "utf8mb4" herstellt. Das liegt an der Client-Anwendung.
Eine PHP-Anwendung finden Sie unter http://php.net/manual/en/function.mysql-set-charset.php oder http://php.net/manual/en/mysqli.set-charset.php
Eine Python-Anwendung finden Sie unter https://github.com/PyMySQL/PyMySQL#example oder http://docs.sqlalchemy.org/en/latest/dialects/mysql.html#mysql-unicode
Überprüfen Sie auch, ob Ihre Spalten wirklich utf8mb4 sind. Ein direkter Weg ist wie folgt:
mysql> SELECT character_set_name FROM information_schema.`COLUMNS` WHERE table_name = "user" AND column_name = "displayname"; +--------------------+ | character_set_name | +--------------------+ | utf8mb4 | +--------------------+ 1 row in set (0.00 sec)
quelle
Für mich stellte sich heraus, dass das Problem im MySQL-Client lag.
Die Zeicheneinstellung des MySQL-Clients aktualisiert sich
my.cnf
auf einem Server und führt zu einer unbeabsichtigten Zeicheneinstellung.Also musste ich nur hinzufügen
character-set-client-handshake = FALSE
. Dadurch wird verhindert, dass die Client-Einstellung meine Zeicheneinstellung stört.my.cnf
wäre so.[mysqld] character-set-client-handshake = FALSE character-set-server = utf8mb4 ...
Ich hoffe es hilft.
quelle
Beispielabfrage:
ALTER TABLE `reactions` CHANGE `emoji` `emoji` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL;
danach erfolgreich in der Lage, Emoji in Tabelle zu speichern:
quelle
Erwägen Sie das Hinzufügen
init_connect = 'SET NAMES utf8mb4'
an alle my.cnf-s Ihrer Datenbankserver.
(dennoch können (werden) Kunden es außer Kraft setzen)
quelle
Ich bin nicht stolz auf diese Antwort, weil sie Brute-Force verwendet, um die Eingabe zu bereinigen. Es ist brutal, aber es funktioniert
function cleanWord($string, $debug = false) { $new_string = ""; for ($i=0;$i<strlen($string);$i++) { $letter = substr($string, $i, 1); if ($debug) { echo "Letter: " . $letter . "<BR>"; echo "Code: " . ord($letter) . "<BR><BR>"; } $blnSkip = false; if (ord($letter)=="146") { $letter = "´"; $blnSkip = true; } if (ord($letter)=="233") { $letter = "é"; $blnSkip = true; } if (ord($letter)=="147" || ord($letter)=="148") { $letter = """; $blnSkip = true; } if (ord($letter)=="151") { $letter = "–"; $blnSkip = true; } if ($blnSkip) { $new_string .= $letter; break; } if (ord($letter) > 127) { $letter = "�" . ord($letter) . ";"; } $new_string .= $letter; } if ($new_string!="") { $string = $new_string; } //optional $string = str_replace("\r\n", "<BR>", $string); return $string; } //clean up the input $message = cleanWord($message); //now you can insert it as part of SQL statement $sql = "INSERT INTO tbl_message (`message`) VALUES ('" . addslashes($message) . "')";
quelle