web-dev-qa-db-fra.com

Impossible de stocker emoji dans la base de données

LA SITUATION:

Désolé par avance si cette question a déjà été posée, mais les solutions ne fonctionnent pas pour moi.

Quoi que j'essaye, je ne peux pas stocker emoji dans ma base de données. Ils sont enregistrés en tant que ????
Les seuls émoticônes correctement enregistrés sont ceux qui ne nécessitent que 3 octets, comme le visage timide ou le soleil. 

L'utf8mb4 réel ne fonctionne pas.

 Database screenshot

Il a été testé sur Android et Ios. Avec les mêmes résultats.

VERSIONS:

Mysql: 5.5.49 
CodeIgniter: 3.0.0

LES MARCHES:

  1. J'ai modifié le jeu de caractères de la base de données et les propriétés de classement.

    ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci

  2. J'ai modifié le jeu de caractères de la table et les propriétés de classement.

    ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

  3. J'ai défini chaque champ de la table, si possible, sur Encodage: UTF-8(ut8mb4) et Collation: utf8mb4_unicode_ci.

  4. J'ai modifié la connexion à la base de données dans l'application CodeIgniter.

  5. J'ai exécuté ce qui suit: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci

  6. Enfin, j'ai aussi essayé ceci: REPAIR TABLE table_name; OPTIMIZE TABLE table_name;

Tout aurait dû être configuré correctement mais cela ne fonctionne toujours pas.

PARAMETRES DE LA BASE DE DONNEES:

C'est le résultat en exécutant la commande suivante: 

`SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';`

 Database settings

TABLE SETTINGS:

Un aperçu de la structure de la table:

 Table settings

CONNEXION DE LA BASE DE DONNEES:

Ce sont les paramètres de connexion à la base de données dans database.php (notez que ce n'est pas la seule base de données, il y en a aussi d'autres qui se connectent en utilisant utf8)

$db['my_database'] = array(
        'dsn'           => '',
        'hostname'      => PROJECT_DATABASE_HOSTNAME,
        'username'      => PROJECT_DATABASE_USERNAME,
        'password'      => PROJECT_DATABASE_PASSWORD,
        'database'      => PROJECT_DATABASE_NAME,
        'dbdriver'      => 'mysqli',
        'dbprefix'      => '',
        'pconnect'      => FALSE,
        'db_debug'      => TRUE,
        'cache_on'      => FALSE,
        'cachedir'      => '',
        'char_set'      => 'utf8mb4',
        'dbcollat'      => 'utf8mb4_unicode_ci',
        'swap_pre'      => '',
        'encrypt'       => FALSE,
        'compress'      => FALSE,
        'stricton'      => FALSE,
        'failover'      => array(),
        'save_queries'  => TRUE
    );

MY.CNF SETTINGS:

C'est tout le contenu du fichier my.cnf:

[mysqld]
default-storage-engine=MyISAM
innodb_file_per_table=1
max_allowed_packet=268435456
open_files_limit=10000
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

LA QUESTION:

Savez-vous pourquoi ne fonctionne pas? Est-ce que je manque quelque chose?

HYPHOTESIS 1:

Je ne suis pas sûr, mais la cause du problème peut être la suivante:

Comme vous pouvez le voir dans my.cnf, character-set-server est clairement défini comme utf8mb4:

Mais après avoir exécuté la requête dans la base de données:

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';

Le résultat est que character-set-server = latin1

Savez-vous pourquoi est-ce? Pourquoi ne met-il pas réellement à jour?

HYPHOTESIS 2:

L'application utilise plusieurs bases de données différentes… .. Celle-ci est définie sur utf8mb4 mais toutes les autres sont définies sur utf8. Cela peut être un problème même s'il s'agit de bases de données séparées?

Je vous remercie!

MODIFIER:

Ceci est le résultat de SHOW CREATE TABLE app_messages;

CREATE TABLE `app_messages` (
  `message_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `project_id` bigint(20) NOT NULL,
  `sender_id` bigint(20) NOT NULL,
  `receiver_id` bigint(20) NOT NULL,
  `message` text COLLATE utf8mb4_unicode_ci,
  `timestamp` bigint(20) DEFAULT NULL,
  `is_read` enum('x','') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`message_id`)
) ENGINE=InnoDB AUTO_INCREMENT=496 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

EDIT 2:

J'ai lancé la commande suivante:

INSERT INTO app_messages (message_id, project_id, sender_id, receiver_id, message, timestamp, is_read)
VALUES ('496','322','77','188', '????' ,'1473413606','x');

Et deux autres similaires avec ???? et ????

Ils ont été insérés dans la table sans problèmes:

 enter image description here

Mais dans l'application actuelle, ce que je vois vraiment est: ? (cette fois, il n'y en a qu'un? Et non 4)

18
FrancescoMussi

Ok, j'ai finalement réussi à le faire fonctionner! Merci. Tous ceux qui ont essayé de m'aider, en particulier @ Rick James et @ Gérard Roche.

SUGGESTION:

Si vous avez besoin de travailler avec emoji, commencez par faire des tests simples sur localhost. Créez une nouvelle base de données et créez une nouvelle application à des fins de test. 

Si vous suivez les étapes que j'ai écrites dans la question ou si vous suivez ce tutoriel: https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4 ça doit fonctionner.

En travaillant localement sur une nouvelle application de base, vous aurez plus de contrôle et plus d’espace pour faire tous les tests dont vous avez besoin.

SOLUTION:

Dans mon cas, le problème était dans la configuration de la base de données dans CodeIgniter. Ce n'était pas correctement configurer char_set et le classement pour un oubli négligé: je remplaçais les paramètres de la base de données dans la fonction qui enregistrait les messages pour être sûr qu'il fonctionnait avec la base de données mobile.

AVANT:

function message_save ( $data = FALSE )
{   
    $project_db_config                  = array();
    $project_db_config['hostname']      = 'MY_Host';
    $project_db_config['username']      = 'MY_USERNAME';
    $project_db_config['password']      = 'MY_PASSWORD';
    $project_db_config['database']      = 'MY_DATABASE';

    $mobile_db                          = $this->load->database( $project_db_config, TRUE );

    // other code to save message       
}

APRÈS:

function message_save ( $data = FALSE )
{
    $mobile_db_connection = $this->load->database('admin_mobile_mh', TRUE);

    // other code to save message
}

CONCLUSION:

L'application doit définir la connexion à la base de données correctement. Si la base de données est correctement configurée mais que la connexion avec votre application n'est pas correcte, cela ne fonctionnera pas.

Donc, si vous rencontrez des problèmes similaires, assurez-vous que l’API configure correctement le char_set comme utf8mb4 et le db_collat comme utf8mb4_unicode_ci.

2
FrancescoMussi

Le seul moyen que je connaisse pour obtenir ???? pour un Emoji est de ne pas avoir la colonne déclarée utf8mb4. Je comprends que vous avez apparemment déterminé que la colonne est déclarée de cette façon, mais veuillez exécuter SHOW CREATE TABLE table_name; pour le confirmer davantage.

Les valeurs par défaut du système, de la base de données et de la table ne sont pas pertinentes si la colonne remplace le CHARACTER SET.

Une note pour toutes les autres tentatives de réponses: La COLLATION est sans importance, seul le CHARACTER SET est pertinent pour cette question .

1
Rick James

my.cnf est chargé en premier, puis conf.d/*.cnf

Au lieu de modifier my.cnf * (qui peut être remplacé par des configurations dans conf.d/*.cnf), créez une configuration de remplacement personnalisée, par exemple. conf.d/90-my.cnf.

Prefixing 90 s'assure que les paramètres personnalisés sont chargés en dernier, ce qui signifie qu'ils écrasent tous les paramètres définis précédemment.

Pour vous assurer que la nouvelle configuration est rechargée, voir Recharger sans redémarrer le service MySQL .

Exemple de structure de configuration (Linux)

.
├── conf.d
│   ├── 90-my.cnf
│   ├── conn.cnf
│   ├── my5.6.cnf
│   └── mysqld_safe_syslog.cnf
├── debian.cnf
├── debian-start
└── my.cnf

conf.d/90-my.cnf

# https://mathiasbynens.be/notes/mysql-utf8mb4
# http://stackoverflow.com/q/3513773/934739

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]

character-set-client-handshake = FALSE

# The server character set and collation are used as default values if the
# database character set and collation are not specified in CREATE DATABASE
# statements. They have no other purpose.
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
1
Gerard

salut j'ai utilisé EMOJI dans Android et je l'ai stocké dans la base de données orm à l'aide de EMOJI_INDEX .I enregistré dans la base de données dans un message normal sous forme de chaîne mais Quand j'arrive à ce moment-là, je vérifie s'il y a des emoji, puis je les convertis en processemoji.

textMessage.setText(getItem(pos).file != null ? "":EmojiUtil.getInstance(context).processEmoji(getItem(pos).message, textMessage.getTextSize()));

Jetez un oeil à partir d'ici comment j'ai changé Emoji_Index pour traiter

if (emojiImages == null || emojiImages.isRecycled()) {
        InputStream localInputStream;
        try {
            localInputStream = context.getAssets().open("emoji/emoji_2x.png");
            Options opts = new Options();
            opts.inPurgeable = true;
            opts.inInputShareable = true;
            emojiImages = BitmapFactory.decodeStream(localInputStream, null, opts);
        } catch (IOException e) {
            return Html.fromHtml(paramString);
        }
    }

Pour plus d'informations, jetez un oeil à partir de ici . Merci, cela vous aidera. 

0
Saveen Dhiman

Au lieu de varchar, vous pouvez modifier la valeur de la table Table comme suit en utf8mb4

Assurez-vous que tous les jeux de caractères et les champs de texte par défaut de vos tables sont convertis en utf8mb4, en plus de définir les jeux de caractères client et serveur, par exemple. ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4; et ainsi de suite.

0
Naresh Kumar .P

J'ai eu un problème avec la version du serveur, sur linux. J'ai dû changer le fichier database_interface.lib.php manuellement et autour de cette 

si (! PMA_DRIZZLE) { if (! empty ($ GLOBALS ['collation_connection']))) {

changez-le pour que cela devienne ceci: (notez les références utf8mb4_unicode_ci)

    // Skip charsets for Drizzle
if (!PMA_DRIZZLE) {
    if (! empty($GLOBALS['collation_connection'])) {
        PMA_DBI_query("SET CHARACTER SET 'utf8mb4';", $link, PMA_DBI_QUERY_STORE);
        $set_collation_con_query = "SET collation_connection = '"
            . PMA_Util::sqlAddSlashes($GLOBALS['collation_connection']) . "';";
        PMA_DBI_query(
            $set_collation_con_query,
            $link,
            PMA_DBI_QUERY_STORE
        );
    } else {
        PMA_DBI_query(
            "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';",
            $link,
            PMA_DBI_QUERY_STORE
        );
    }
}
0
Miguel