accept - MySQL utf8mb4, Errores al guardar Emojis
mysql accept emoji (5)
Intento guardar nombres de usuarios de un servicio en mi base de datos MySQL. Esos nombres pueden contener emojis como 🙈😂😱🍰 (solo por ejemplos)
Después de buscar un poco, encontré este stackoverflow vinculado a este tutorial . Seguí los pasos y parece que todo está configurado correctamente.
Tengo una base de datos (conjunto de caracteres y colación establecida en utf8mb4 (_unicode_ci)), una tabla llamada TestTable, también configurada de esta manera, así como una columna "Texto", configurada de esta manera (VARCHAR (191) utf8mb4_unicode_ci).
Cuando intento guardar emojis me sale un error:
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
El único Emoji que pude guardar correctamente fue el sol ☀️
Aunque no intenté que todos fueran honestos.
¿Hay algo que me falta en la configuración?
Tenga en cuenta: Todas las pruebas de ahorro no involucraron al lado del cliente. Utilizo phpmyadmin para cambiar manualmente los valores y guardar los datos. Entonces, la configuración adecuada del lado del cliente es algo de lo que me ocuparé después de que el servidor guarde correctamente los emojis.
Otro comentario
: Actualmente, al guardar emojis, recibo el error como se
Username 🍰
arriba o no recibo ningún error y los datos del
Username 🍰
de
Username 🍰
se almacenarán como
Username ????
.
El error o ningún error depende de la forma en que guardo.
Al crear / guardar a través de la instrucción SQL, guardo con signos de interrogación, al editar en línea, guardo con signos de interrogación, al editar con el botón de edición me sale el error.
gracias
EDITAR 1: Muy bien, así que creo que descubrí el problema, pero no la solución. Parece que las variables específicas de la base de datos no cambiaron correctamente.
Cuando estoy conectado como root en mi servidor y leo las variables (global):
Consulta utilizada:
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)
Para mi base de datos (en phpmyadmin, la misma consulta) tiene el siguiente aspecto:
+--------------------------+--------------------+
| 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 |
+--------------------------+--------------------+
¿Cómo puedo ajustar esta configuración en la base de datos específica? Además, aunque tengo la primera configuración mostrada como predeterminada, al crear una nueva base de datos, obtengo la segunda como configuración.
Edición 2:
Aquí está mi archivo
my.cnf
:
[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/
ALTER TABLE
table_name
CHANGE column_name column_name VARCHAR (255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL;
consulta de ejemplo:
ALTER TABLE `reactions` CHANGE `emoji` `emoji` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL;
después de eso, exitoso capaz de almacenar emoji en la tabla:
Es probable que su servicio / aplicación se conecte con "utf8" en lugar de "utf8mb4" para el juego de caracteres del cliente. Eso depende de la aplicación del cliente.
Para una aplicación PHP, consulte http://php.net/manual/en/function.mysql-set-charset.php o http://php.net/manual/en/mysqli.set-charset.php
Para una aplicación Python, consulte https://github.com/PyMySQL/PyMySQL#example o http://docs.sqlalchemy.org/en/latest/dialects/mysql.html#mysql-unicode
Además, verifique que sus columnas realmente sean utf8mb4. Una forma directa es así:
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)
No estoy orgulloso de esta respuesta, porque utiliza la fuerza bruta para limpiar la entrada. Es brutal, pero funciona.
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) . "'')";
Para mí, resultó que el problema radicaba en el cliente mysql.
El cliente mysql actualiza la
my.cnf
de
my.cnf
en un servidor y dio como resultado una configuración de caracteres no deseada.
Entonces, lo que necesitaba hacer es agregar
character-set-client-handshake = FALSE
.
Inhabilita la configuración del cliente de perturbar mi configuración de caracteres.
my.cnf
sería así.
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
...
Espero eso ayude.
character_set_client
,
_connection
y
_results
deben ser
utf8mb4
para que ese shortcake sea comestible.
Algo, en algún lugar, está configurando un subconjunto de esos individualmente. Revisa la configuración de my.cnf y phpmyadmin: algo no está configurando los tres.
Si
SET NAMES utf8mb4
se ejecuta, los tres se configuran correctamente.
El sol brillaba porque solo tiene 3 bytes:
E2 98 80
;
utf8 es suficiente para codificaciones utf8 de 3 bytes de caracteres Unicode.