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

Selvamani P
źródło
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;
ospider
źródło
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');
Selvamani P
źródło
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.

samawaat
źródło
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;
}
Sunil Gupta
źródło
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

Deepak Arora
źródło
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) 
Harpreet
źródło
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.

Nicola Pedretti
źródło
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
Ashh
źródło
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;

user3855339
źródło
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)
Tina Bri
źródło
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)

user12359502
źródło
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.

Siddhant
źródło
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;
Myles Baker
źródło