web-dev-qa-db-de.com

Speichern von Emoji in der Datenbank nicht möglich

DIE SITUATION:

Sorry im Voraus, wenn diese Frage bereits gestellt wurde, aber die Lösungen für mich nicht funktionieren.

Egal was ich versuche, ich kann Emoji nicht in meiner Datenbank speichern. Sie werden als ???? gespeichert. 
Die einzigen Emojis, die richtig gespeichert werden, sind diejenigen, die nur 3 Byte benötigen, wie das schüchterne Gesicht oder die Sonne. 

Das eigentliche utf8mb4 funktioniert nicht.

 Database screenshot

Es wurde auf Android und Ios getestet. Mit den gleichen Ergebnissen.

VERSIONEN:

Mysql: 5,5,49 
CodeIgniter: 3.0.0

DIE SCHRITTE:

  1. Ich habe die Eigenschaften des Datenbankzeichensatzes und der Sortierfolge geändert.

    ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci

  2. Ich habe die Eigenschaften des Tabellenzeichensatzes und der Sortierfolge geändert.

    ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

  3. Ich habe jedes Feld der Tabelle, soweit möglich, als Encoding: UTF-8(ut8mb4) und Collation: utf8mb4_unicode_ci festgelegt.

  4. Ich habe die Datenbankverbindung in der CodeIgniter-App geändert.

  5. Ich habe folgendes ausgeführt: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci

  6. Zum Schluss habe ich auch folgendes ausprobiert: REPAIR TABLE table_name; OPTIMIZE TABLE table_name;

Alles sollte richtig eingerichtet sein, aber es funktioniert nicht.

DATENBANK-EINSTELLUNGEN:

Dies ist das Ergebnis, das den folgenden Befehl ausführt: 

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

 Database settings

TISCH EINSTELLUNGEN:

Ein Screenshot der Tabellenstruktur:

 Table settings

DATENBANKVERBINDUNG:

Dies sind die Datenbankverbindungseinstellungen in database.php (beachten Sie, dass dies nicht die einzige Datenbank ist, es gibt auch andere, die eine Verbindung mit utf8 herstellen.)

$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-EINSTELLUNGEN:

Dies ist der gesamte Inhalt der Datei 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

DIE FRAGE:

Weißt du, warum es nicht funktioniert? Fehlt mir etwas?

HYPHOTESE 1:

Ich bin nicht sicher, aber die Ursache des Problems kann folgende sein:

Wie Sie in my.cnf sehen können, ist character-set-server eindeutig als utf8mb4 eingestellt:

Nach dem Ausführen der Abfrage in der Datenbank:

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

Das Ergebnis ist, dass character-set-server = latin1

Weißt du warum das so ist? Warum wird nicht wirklich aktualisiert?

HYPHOTESE 2:

Die Anwendung verwendet mehrere verschiedene Datenbanken. Diese ist auf utf8mb4 gesetzt, alle anderen auf utf8. Es kann ein Problem sein, auch wenn es sich um getrennte Datenbanken handelt.

Vielen Dank!

EDIT:

Dies ist das Ergebnis von 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:

Ich habe den folgenden Befehl ausgeführt:

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

Und zwei anderen ähnlich mit ???? und ????

Sie wurden ohne Probleme in die Tabelle eingefügt:

 enter image description here

Aber in der eigentlichen App sehe ich wirklich: ? (diesmal nur eine? Und nicht 4)

18
FrancescoMussi

Okay, ich habe es endlich geschafft, dass es funktioniert! Vielen Dank an alle, die versucht haben, mir zu helfen, insbesondere @ Rick James und @Gerard Roche.

VORSCHLAG:

Wenn Sie mit Emoji arbeiten müssen, führen Sie zunächst einfache Tests für localhost durch. Erstellen Sie eine neue Datenbank und erstellen Sie eine neue App zum Testen. 

Wenn Sie den Schritten folgen, die ich in der Frage geschrieben habe, oder wenn Sie diesem Tutorial folgen: https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4 es muss funktionieren.

Wenn Sie vor Ort an einer neuen Basis-App arbeiten, haben Sie mehr Kontrolle und mehr Platz, um alle erforderlichen Tests durchzuführen.

LÖSUNG:

In meinem Fall lag das Problem in der Konfiguration der Datenbank in CodeIgniter. Das char_set und die Kollatierung für ein dummes Übersehen wurde nicht richtig eingerichtet: Ich überschrieb die Datenbankeinstellungen in der Funktion, mit der Nachrichten gespeichert werden, um sicherzustellen, dass sie mit der mobilen Datenbank funktioniert.

VOR:

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       
}

NACH DEM:

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

    // other code to save message
}

FAZIT:

Die App muss die Verbindung zur Datenbank ordnungsgemäß herstellen. Wenn Sie die Datenbank ordnungsgemäß eingerichtet haben, aber keine ordnungsgemäße Verbindung mit Ihrer App herstellen, funktioniert sie nicht.

Wenn Sie also auf ähnliche Probleme stoßen, stellen Sie sicher, dass die API den char_set als utf8mb4 und db_collat als utf8mb4_unicode_ci richtig einrichtet.

2
FrancescoMussi

Die einzige Möglichkeit, ???? für ein Emoji zu erhalten, ist, die columnutf8mb4-Anweisung nicht zu haben. Ich verstehe, dass Sie anscheinend festgestellt haben, dass die Spalte auf diese Weise deklariert ist. Führen Sie jedoch SHOW CREATE TABLE table_name; aus, um sie weiter zu bestätigen.

Der Systemstandard, der Datenbankstandard und der Tabellenstandard sind irrelevant, wenn die Spalte den CHARACTER SET überschreibt.

Eine Anmerkung zu allen anderen versuchten Antworten: Die COLLATION ist irrelevant, nur der CHARACTER SET ist relevant für diese Frage .

1
Rick James

my.cnf wird zuerst geladen, dann conf.d/*.cnf

Anstatt my.cnf * (das durch Konfigurationen in conf.d/*.cnf überschrieben werden kann) zu ändern, erstellen Sie eine benutzerdefinierte Überschreibungskonfiguration, z. conf.d/90-my.cnf.

Prefixing 90 sorgt dafür, dass die benutzerdefinierten Einstellungen zuletzt geladen werden. Dies bedeutet, dass alle zuvor festgelegten Einstellungen überschrieben werden.

Um sicherzustellen, dass die neue Konfiguration neu geladen wird, siehe Neu laden ohne Neustart des MySQL-Dienstes .

Beispielkonfigurationsstruktur (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

hallo, ich habe EMOJI in Android verwendet und ich habe es in orm-Datenbank mit EMOJI_INDEX gespeichert Wenn ich diese Zeit bekomme, überprüfe ich, ob es Emoji gibt, und wandle es in dort Processemoji um.

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

Sehen Sie hier, wie ich Emoji_Index in Prozess umgestellt habe

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);
        }
    }

Weitere Informationen finden Sie unter hier . Vielen Dank, dass Ihnen dies helfen wird. 

0
Saveen Dhiman

Anstelle von varchar können Sie den Wert der Tabelle in utf8mb4 ändern.

Stellen Sie sicher, dass alle Standardzeichensätze und Textfelder Ihrer Tabellen in utf8mb4 konvertiert werden. Zusätzlich zum Festlegen der Client- und Server-Zeichensätze, z. ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4; und so weiter.

0
Naresh Kumar .P

Ich hatte ein Problem mit der Serverversion unter Linux. Ich musste die Datei database_interface.lib.php manuell und um diese herum ändern 

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

Ändern Sie es so, dass Folgendes wird: (Beachten Sie die Referenzen 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