Jak przechowywać znaki Emoji w bazie danych MySQL


172

W moim projekcie używam znaku Emoji. Te znaki są zapisywane (??) w bazie danych mysql. Użyłem domyślnego sortowania bazy danych w programie utf8mb4_general_ci. To pokazuje

1366 Niepoprawna wartość ciągu: „\ xF0 \ x9F \ x98 \ x83 \ xF0 \ x9F ...” dla kolumny „komentarz” w wierszu 1


1
Jak oszczędzasz swoje dane? Czy możesz nam pokazać ten kod?
Tomas Buteler

1
Dzięki za komentarz. Znalazłem rozwiązanie dla tej domyślnej kolekcji Change Database jako ** utf8mb4 **, a także Zmień kolekcję tabeli jako ** ZESTAW ZNAKÓW utf8mb4 Sortuj utf8mb4_bin **. ALTER TABLE Tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
Selvamani P

1
Kod: insert into tablename (column1,column2,column3,column4,column5,column6,column7) values ('273','3','Hdhdhdh😜😀😊😃hzhzhzzhjzj 我爱你 ❌',49,1,'2016-09-13 08:02:29','2016-09-13 08:02:29'Ustaw utf8mb4 w połączeniu z bazą danych: $database_connection = new mysqli($server, $user,$password,$database_name); $database_connection->set_charset("utf8mb4");
Selvamani P

Odpowiedzi:


29

krok 1, zmień domyślny zestaw znaków w bazie danych:

ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

krok 2, ustaw kodowanie podczas tworzenia tabeli:

CREATE TABLE IF NOT EXISTS table_name (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;

lub zmień tabelę

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE table_name modify name text charset utf8mb4;

Wykonałem te zapytania i zatrzymałem i ponownie uruchomiłem serwer mysql, ale kiedy próbuję wstawić emoji do mojej tabeli, nadal otrzymuję ten sam błąd. Wszystkie polecenia zakończyły się pomyślnie, z wyjątkiem INSERT. INSERT INTO Entries (data, godzina, podpis) VALUES (2018-05-20 ', '12: 38: 00', 'Testing description with emoji: 😊❤️'); Ustawienia kolumny to Sortowanie: utf8mb4_0900_ai_ci Definicja: tekst opisu

1
Twoje połączenie również musi być utf8mb4, a nie utf8, aby działało.
Henrik Hansen

3
@ospider, w kroku 2 używasz utfmb4_general_ci zamiast Unicode - czy jest jakiś powód, dlaczego?
Warren,

263

1) Baza danych: Zmień domyślne sortowanie bazy danych na utf8mb4.

2) Tabela: Zmień sortowanie tabeli na CHARACTER SET utf8mb4 COLLATE utf8mb4_bin.

Pytanie:

ALTER TABLE Tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin

3) Kod:

INSERT INTO tablename (column1, column2, column3, column4, column5, column6, column7)
VALUES ('273', '3', 'Hdhdhdh😜😀😊😃hzhzhzzhjzj 我爱你 ❌', 49, 1, '2016-09-13 08:02:29', '2016-09-13 08:02:29')

4) Ustaw utf8mb4w połączeniu z bazą danych:

  $database_connection = new mysqli($server, $user, $password, $database_name); 
  $database_connection->set_charset('utf8mb4');

4
Czy jest to możliwe bez zmiany domyślnej kolekcji bazy danych?
AliN11

23
To nie działa dla mnie. Staje się "???" zamiast uśmieszków. tylko "☺" ten smily dostał się bezpiecznie do bazy danych.
Ciekawy deweloper

10
Może trzeba zaktualizować nie tylko tabelę do utf8mb4, ale także same kolumny, w przeciwnym razie nadal mogą pojawiać się jako ?? zamiast 💙.
Ael

2
Pracował dla mnie, ale nie zapomnij zrestartować MySQL.
Ravi Misra

8
Muszę biec, SET NAMES utf8mb4;aby zacząć zapisywać emotikony; przed tym rozkazem ratował ich jako??
cubbuk

18

Zarówno bazy danych, jak i tabele powinny mieć zestaw znaków utf8mb4i sortowanie utf8mb4_unicode_ci.

Tworząc nową bazę danych należy użyć:

CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Jeśli masz istniejącą bazę danych i chcesz dodać wsparcie:

ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

Musisz także ustawić prawidłowy zestaw znaków i sortowanie dla swoich tabel:

CREATE TABLE IF NOT EXISTS table_name (
    ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;

lub zmień to, jeśli masz istniejące tabele z dużą ilością danych:

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Pamiętaj, że utf8_general_cinie jest to już zalecana najlepsza praktyka. Zobacz powiązane pytania i odpowiedzi:

Jaka jest różnica między utf8_general_ci i utf8_unicode_ci w Stack Overflow.


Mam bazę danych i tabelę zawierającą dane. i podczas wykonywania drugiej instrukcji alter mówi, że: ERROR 1833 (HY000): Nie można zmienić kolumny 'id': używane w ograniczeniu klucza obcego 'FK12njtf8e0jmyb45lqfpt6ad89' tabeli 'lizbazi.post'
Seyyed Mahdiyar Zerehpoush

@SeyyedMahdiyarZerehpoush - możesz być w stanie ograniczyć aktualizację do określonych kolumn, które tego wymagają, jak opisano tutaj: stackoverflow.com/a/15781925/1247581 np.ALTER TABLE mytable MODIFY my_emoji_friendly_text_column VARCHAR(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
theartofrain

jakieś różnice podczas używania utf8mb4_binvs utf8mb4_unicode_cidla kolumn?
Muhammad Omer Aslam

14

Jeśli korzystasz z Solr + Mysql + Java, możesz użyć:

Można to wykorzystać:

  • case1: Kiedy nie chcesz zmieniać DB.
  • case2: kiedy musisz importować emotikony z Twojego MySQL do rdzenia Solr.

W powyższym przypadku jest to jedno z rozwiązań umożliwiających przechowywanie emotikonów w systemie.

Kroki, aby z niego skorzystać:

Używana biblioteka: import java.net.URLDecoder; import java.net.URLEncoder;

  1. Użyj urlEncoder, aby zakodować swój ciąg znaków z emotikonami.
  2. Przechowuj go w DB bez zmiany MysqlDB.
  3. Możesz przechowywać go w solr core (w postaci zdekodowanej), jeśli chcesz, lub możesz przechowywać zakodowaną formę.
  4. Pobierając te emotikony z rdzenia DB lub Solr, możesz je teraz zdekodować za pomocą urlDecoder.

Przykład kodu:

import java.net.URLDecoder;
import java.net.URLEncoder;

public static void main(String[] args) {
    //SpringApplication.run(ParticipantApplication.class, args);
    System.out.println(encodeStringUrl("🇺🇸🇨🇳🇯🇵🇩🇪🔳🔺🆔🆔🆑3⃣5⃣3⃣‼〽➗➗🎦🔆🎦🔆♋♍♋♍⬅⬆⬅⬅🛂🚹🛂🛄🚳🚬💊🔧💊🗿     "));
    System.out.println(decodeStringUrl("Hello+emoticons%2C%2C%F0%9F%98%80%F0%9F%98%81%F0%9F%98%8A%F0%9F%98%8B%F0%9F%98%8E%F0%9F%98%8A%F0%9F%98%8D%E2%98%BA%F0%9F%98%98%E2%98%BA%F0%9F%98%91%F0%9F%98%87%F0%9F%98%98%F0%9F%98%8B%F0%9F%90%84"));
}

public static String encodeStringUrl(String url) {
    String encodedUrl =null;
    try {
         encodedUrl = URLEncoder.encode(url, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return encodedUrl;
    }
    return encodedUrl;
}

public static String decodeStringUrl(String encodedUrl) {
    String decodedUrl =null;
    try {
         decodedUrl = URLDecoder.decode(encodedUrl, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return decodedUrl;
    }
    return decodedUrl;
}

Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną, natychmiastową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego długoterminową wartość, pokazując, dlaczego jest to dobre rozwiązanie problemu, i uczyniłoby go bardziej użytecznym dla przyszłych czytelników z innymi, podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
Toby Speight

1
działa jak urok, użyłem go w modelu, więc naprawdę nie muszę zmieniać żadnego kodu i bazy danych tylko model danych na
seterze

1
Wywołania funkcji kodowania / dekodowania zwykle powodują problemy. Zamiast tego popraw ustawienia zestawu znaków w różnych miejscach.
Rick James

1
To nie jest rozwiązanie problemu, to jest jego ominięcie. I napotkasz wiele problemów z tą metodą, na przykład spowolnisz swoją aplikację, ponieważ musisz wszystko zdekodować i zakodować. Również jeśli wpiszesz znak %, dekodowanie się zepsuje.
Jonathan Laliberte

14

Zaktualizowałem moją bazę danych i tabelę, aby zaktualizować je z utf8 do utf8mb4 . Ale dla mnie nic nie działa. Potem próbowałem zaktualizować typ danych kolumny na blob , na szczęście zadziałało i dane zostały zapisane. Nawet moja baza danych i tabela to ZESTAW ZNAKÓW utf8 COLLATE utf8_unicode


13

Polecenie do zmodyfikowania kolumny to:

ALTER TABLE TABLE_NAME MODIFY COLUMN_NAME TYPE;

I musimy użyć type = BLOB

Przykład modyfikacji jest następujący: -

ALTER TABLE messages MODIFY content BLOB;

Sprawdziłem, że najnowsze bazy danych MySQL i inne nie muszą ''być używane w poleceniu na nazwa_tabeli, nazwa_kolumny itp.

Pobierz i zapisz dane: bezpośrednio zapisz treść czatu w kolumnie i pobierz dane, pobierz dane jako tablicę bajtów (byte[])z kolumny db, a następnie przekonwertuj je na stringnp. (Kod Java)

new String((byte[]) arr) 

2
Tak. Jeśli potrzebujesz tylko przechowywać unicode, takie jak emoji w określonym polu, zaakceptowana odpowiedź jest zbyt uciążliwa. Po prostu zmień text/ varcharpole na a blobi gotowe. Szaleństwo konwertowania zestawu znaków i sortowania na całym DB tylko w tym celu :)
davidkonrad

9

Moja odpowiedź tylko dodaje do odpowiedzi Selvamani P.

Może być również konieczna zmiana SET NAMES utf8zapytań za pomocą SET NAMES utf8mb4. To załatwiło sprawę dla mnie.

Ponadto, jest to świetny artykuł na swojej stronie portu z utf8 do utf8mb4. W szczególności artykuł przedstawia 2 dobre punkty dotyczące indeksów i naprawy tabel po ich konwersji na utf8mb4:

INDEKSY

Podczas konwersji z utf8 na utf8mb4 maksymalna długość kolumny lub klucza indeksu pozostaje niezmieniona pod względem liczby bajtów. Dlatego jest mniejszy pod względem znaków, ponieważ maksymalna długość znaku wynosi teraz cztery bajty zamiast trzech. [...] Mechanizm magazynowania InnoDB ma indeks o maksymalnej długości 767 bajtów, więc dla kolumn utf8 lub utf8mb4 można indeksować maksymalnie 255 lub 191 znaków. Jeśli obecnie masz kolumny utf8 z indeksami dłuższymi niż 191 znaków, będziesz musiał indeksować mniejszą liczbę znaków, gdy używasz utf8mb4.

STOŁY NAPRAWCZE

Po uaktualnieniu serwera MySQL i wprowadzeniu niezbędnych zmian opisanych powyżej, upewnij się, że naprawiłeś i zoptymalizowałeś wszystkie bazy danych i tabele. Nie zrobiłem tego od razu po aktualizacji (nie sądziłem, że to konieczne, ponieważ na pierwszy rzut oka wszystko wydawało się działać dobrze) i napotkałem kilka dziwnych błędów, w których instrukcje UPDATE nie miały żadnego efektu, mimo że nie zostały wyrzucone błędy.

Przeczytaj więcej o zapytaniach do naprawy tabel w artykule.


REPAIR TABLEi OPTIMIZE TABLEpowinny być niepotrzebne - ALTERpowoduje to ich wykonanie.
Rick James

5

W powyższych odpowiedziach nie wspomniano o głównym punkcie, że

Musimy przekazać ciąg zapytania z opcjami "useUnicode=yes"i parametrami "characterEncoding=UTF-8"połączenia

Coś takiego

mysql://USERNAME:PASSWORD@HOSTNAME:PORT/DATABASE_NAME?useUnicode=yes&characterEncoding=UTF-8

5

Cóż, nie musisz zmieniać całego zestawu znaków DB. Zamiast tego możesz to zrobić, zmieniając kolumnę na typ blob .

ALTER TABLE wiadomości MODIFY content BLOB;


3

Mam dobre rozwiązanie, aby zaoszczędzić Twój czas. Ja też napotykam ten sam problem, ale nie mogłem go rozwiązać pierwszą odpowiedzią.

Twój domyślny charakter to utf-8. Ale emoji potrzebuje utf8mb4 do obsługi. Jeśli masz uprawnienia do zmiany pliku konfiguracyjnego mysql, możesz wykonać ten krok.

Dlatego wykonaj następujący krok, aby zaktualizować zestaw znaków (z utf-8 do utf8mb4).

krok 1. otwórz swój my.cnf dla mysql, dodaj następujące wiersze do swojego my.cnf.

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
init_connect='SET NAMES utf8mb4'

[mysql]
default-character-set = utf8mb4


[client]
default-character-set = utf8mb4

krok 2. zatrzymaj usługę mysql i uruchom usługę mysql

mysql.server stop
mysql.server start

Skończone! Następnie możesz sprawdzić, czy twoja postać została zmieniona na utf8mb4.

mysql> SHOW VARIABLES LIKE 'character_set%';
+--------------------------+----------------------------------------------------------+
| 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                                                     |
| character_sets_dir       | /usr/local/Cellar/mysql@5.7/5.7.29/share/mysql/charsets/ |
+--------------------------+----------------------------------------------------------+
8 rows in set (0.00 sec)

2

Obsługa emoji dla aplikacji posiadającej stos techniczny - mysql, java, springboot, hibernate

Zastosuj poniższe zmiany w mysql do obsługi Unicode.

  1. ALTER DATABASE <database-name> CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
  2. ALTER TABLE <table-name> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Połączenie DB - zmiana adresu URL jdbc:

jdbc:mysql://localhost:3306/<database-name>?useUnicode=yes&characterEncoding=UTF-8

Uwaga - Jeśli powyższy krok nie działa, zaktualizuj wersję mysql-connector do 8.0.15. (mysql 5.7 współpracuje ze złączem w wersji 8.0.15 dla obsługi Unicode)


1

Najprostszym rozwiązaniem, które działa dla mnie, jest przechowywanie danych jako json_encode .

później, kiedy będziesz pobierać, po prostu upewnij się, że masz json_decode .

Tutaj nie musisz zmieniać sortowania ani zestawu znaków bazy danych i tabeli.


0

Dla każdego, kto próbuje rozwiązać ten problem na zarządzanej instancji MySQL (w moim przypadku na AWS RDS), najłatwiejszym sposobem było zmodyfikowanie grupy parametrów i ustawienie zestawu znaków serwera i sortowania odpowiednio na utf8mb4i utf8mb4_bin. Po ponownym uruchomieniu serwera szybkie zapytanie weryfikuje ustawienia baz systemowych i nowo utworzonych:

SELECT * FROM information_schema.SCHEMATA S;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.