Cara membuat MySQL menangani UTF-8 dengan benar


102

Salah satu tanggapan atas pertanyaan yang saya ajukan kemarin menyarankan agar saya memastikan database saya dapat menangani karakter UTF-8 dengan benar. Bagaimana saya bisa melakukan ini dengan MySQL?


4
Saya sangat berharap kami mendapatkan jawaban yang komprehensif, mencakup berbagai versi MySQL, inkompatibilitas, dll.
Edward Z. Yang


1
@ EdwardZ.Yang - MySQL 4.1 diperkenalkan CHARACTER SETs; 5.1.24 mengacaukan susunan kata-kata tajam Jerman (ß), yang dikoreksi dengan menambahkan pemeriksaan lain di 5.1.62 (bisa dibilang memperburuk keadaan); 5.5.3 mengisi utf8 dengan charset utf8mb4 yang baru.
Rick James

1
Pertanyaan ini sangat mirip dengan pertanyaan ini .. Silakan lihat stackoverflow.com/questions/3513773/…
Nyein Aung

Perlu diketahui bahwa sebagian besar jawaban ini salah. Jangan gunakan utf8. Ini hanya mendukung hingga karakter 3-byte. Kumpulan karakter yang benar yang harus Anda gunakan di MySQL adalah utf8mb4.
Brendan Byrd

Jawaban:


89

Memperbarui:

Jawaban singkat - Anda seharusnya hampir selalu menggunakan utf8mb4charset dan utf8mb4_unicode_cicollation.

Untuk mengubah database:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Lihat:

Jawaban Asli:

MySQL 4.1 dan di atasnya memiliki rangkaian karakter default UTF-8. Anda dapat memverifikasi ini dalam my.cnfberkas, ingatlah untuk mengatur kedua klien dan server ( default-character-setdan character-set-server).

Jika Anda memiliki data yang ingin diubah menjadi UTF-8, buang database Anda, dan impor kembali sebagai UTF-8, pastikan:

  • gunakan SET NAMES utf8sebelum Anda membuat kueri / memasukkan ke dalam database
  • gunakan DEFAULT CHARSET=utf8saat membuat tabel baru
  • pada titik ini klien dan server MySQL Anda harus dalam UTF-8 (lihat my.cnf). ingat bahasa apa pun yang Anda gunakan (seperti PHP) harus UTF-8 juga. Beberapa versi PHP akan menggunakan pustaka klien MySQL mereka sendiri, yang mungkin tidak mendukung UTF-8.

Jika Anda ingin memigrasi data yang ada, ingatlah untuk membuat cadangan terlebih dahulu! Banyak choping data yang aneh dapat terjadi ketika sesuatu tidak berjalan sesuai rencana!

Beberapa sumber:


29
Pemahaman saya adalah bahwa utf8dalam MySQL hanya mengacu pada sebagian kecil dari Unicode penuh. Anda harus menggunakan utf8mb4sebagai gantinya untuk memaksa dukungan penuh. Lihat mathiasbynens.be/notes/mysql-utf8mb4 "Untuk waktu yang lama, saya menggunakan charset utf8 MySQL untuk database, tabel, dan kolom, dengan asumsi itu dipetakan ke encoding UTF-8 yang dijelaskan di atas."
Aaron McDaid

7
MySQL tidak pernah memiliki rangkaian karakter default UTF-8. 4.1 dan 5.x hingga 5.7 terbaru semua digunakan latin1dan latin1_swedish_ciuntuk charset dan pemeriksaan default. Lihat halaman "Kumpulan Karakter dan Penyusunan
Animisme

2
@TimTisdall Anda tidak perlu khawatir utf8mb4mengambil penyimpanan ekstra saat sebagian besar teks adalah ASCII. Meskipun charstring sudah dialokasikan sebelumnya, varcharstring tidak - lihat beberapa baris terakhir di halaman dokumentasi ini . Misalnya, char(10)akan secara pesimistis mencadangkan 40 byte di bawah utf8mb4, tetapi varchar(10)akan mengalokasikan byte sesuai dengan pengkodean panjang variabel.
Kevin A. Naudé

1
@Kevin Saya pikir Anda salah. Saya pikir panjang baris maksimum adalah 64k. Anda hanya dapat membuat bidang utf8mb4 1/4 dari itu karena harus mencadangkan sejumlah ruang itu. Jadi, meskipun itu ASCII Anda hanya dapat memasukkan 16k karakter.
Tim Tisdall

1
@TimTisdall Oh, Anda sedang berbicara tentang batas atas. Ya, itu lebih rendah. Untungnya, versi mysql saat ini akan secara otomatis memutakhirkan dari varchar(n)ke texttipe data jika Anda mencoba mengubah varchar(n)bidang menjadi lebih besar dari ukuran byte yang layak (sambil mengeluarkan peringatan). Indeks juga akan memiliki batas atas kasus terburuk yang lebih rendah, dan itu dapat menimbulkan masalah lain.
Kevin A. Naudé

44

Untuk membuat ini 'permanen', di my.cnf:

[client]
default-character-set=utf8
[mysqld]
character-set-server = utf8

Untuk memeriksanya, buka klien dan tunjukkan beberapa variabel:

SHOW VARIABLES LIKE 'character_set%';

Verifikasi bahwa semuanya utf8, kecuali ..._filesystem, yang seharusnya binarydan ..._dir, yang mengarah ke suatu tempat di instalasi MySQL.


Itu tidak berfungsi dalam kasus saya tetapi saya membuat file my.cf di / etc dengan konten yang diberikan. Saya menggunakancreate table my_name(field_name varchar(25) character set utf8);
Marek Bar

The "TAMPILKAN VARIABEL SEPERTI 'character_set%';" perintah mengungkapkan saya masalah dengan koneksi saya. Terima kasih!
javsmo

1
Ini tidak benar. Apa yang disebut MySQL utf8bukanlah UTF-8 "penuh".
TWR Cole

32

MySQL 4.1 dan yang lebih baru memiliki rangkaian karakter default yang dipanggil utf8tetapi sebenarnya hanya merupakan bagian dari UTF-8 (hanya memungkinkan karakter tiga byte dan lebih kecil).

Gunakan utf8mb4sebagai rangkaian karakter Anda jika Anda ingin UTF-8 "penuh".


5
Sangat setuju, ini satu-satunya jawaban yang benar. utf8tidak menyertakan karakter seperti emotikon. utf8mb4tidak. Periksa ini untuk info lebih lanjut tentang cara memperbarui: mathiasbynens.be/notes/mysql-utf8mb4
jibai31

@Basti - Sebagian besar benar (latin1 adalah default hingga baru-baru ini), dan tidak lengkap (tidak membahas cara memasukkan / memilih data yang dikodekan utf8 dengan benar, atau menampilkannya dalam html).
Rick James

Dengan hormat, @RickJames, Basti mengatakan "sejauh ini" - Saya tidak ingat melihat jawaban Anda ketika saya memposting ini.
TWR Cole

Sayangnya, ada sekitar 5 gejala masalah utf8 yang sangat berbeda, dan sekitar 4 kesalahan yang dilakukan programmer hingga menyebabkan masalah. Sebagian besar jawaban hanya menunjukkan satu hal yang mungkin perlu diperbaiki. Pertanyaan aslinya luas, jadi jawabannya butuh semua 4. Mungkin Basti akrab dengan satu gejala yang satu aspek Anda adalah solusinya.
Rick James

8
Selain itu, saya ingin berhenti sejenak dan memberi tim MySQL tatapan yang sangat baik dan tajam. o_o WTF yang kalian pikirkan? Apakah Anda menyadari betapa banyak kebingungan yang Anda taburkan dengan membuat codepage dalam program Anda yang disebut "utf8" yang sebenarnya bukan UTF-8? Brengsek. </rant>
TWR Cole

20

Jawaban singkatnya: Gunakan utf8mb4di 4 tempat:

  • Byte di klien Anda adalah utf8, bukan latin1 / cp1251 / etc.
  • SET NAMES utf8mb4 atau sesuatu yang setara saat membuat koneksi klien ke MySQL
  • CHARACTER SET utf8mb4 pada semua tabel / kolom - kecuali kolom yang benar-benar ascii / hex / country_code / zip_code / etc.
  • <meta charset charset=UTF-8>jika Anda menampilkan ke HTML. (Ya, ejaannya berbeda di sini.)

Info lebih lanjut ;
UTF8 sepenuhnya

Tautan di atas memberikan "jawaban kanonis terperinci yang diperlukan untuk mengatasi semua masalah". - Ada batasan ruang di forum ini.

Edit

Selain CHARACTER SET utf8mb4berisi "semua" karakter dunia, COLLATION utf8mb4_unicode_520_cibisa dibilang susunan 'terbaik serba bisa' untuk digunakan. (Ada juga kumpulan bahasa Turki, Spanyol, dll untuk mereka yang menginginkan nuansa dalam bahasa tersebut.)


Tautan baru saya tentang cara men-debug masalah utf8 dari output yang Anda dapatkan.
Rick James

Mengapa unicode_520_ci bukan yang terbaik di sekitar: stackoverflow.com/a/49982378/62202
Louis

@ Louis - Dan seperti yang saya tersirat, pengguna Spanyol dan Turki (serta Polandia) mungkin tidak senang. "Terbaik serba bisa" cenderung menyakiti semua orang. MySQL 8.0 memiliki susunan "terbaik" yang lebih baru: utf8mb4_0900_ai_ci . Sayangnya, lagi-lagi L = Ł.
Rick James

4

Charset adalah properti database (default) dan tabel. Anda dapat melihat (perintah MySQL):

show create database foo; 
> CREATE DATABASE  `foo`.`foo` /*!40100 DEFAULT CHARACTER SET latin1 */

show create table foo.bar;
> lots of stuff ending with
> ) ENGINE=InnoDB AUTO_INCREMENT=252 DEFAULT CHARSET=latin1

Dengan kata lain; cukup mudah untuk memeriksa charset database Anda atau mengubahnya:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;

1
Ini tidak benar. Apa yang disebut MySQL utf8bukanlah UTF-8 "penuh".
TWR Cole


2

Saya mengikuti solusi Javier, tetapi saya menambahkan beberapa baris berbeda di my.cnf:

[myslqd]
skip-character-set-client-handshake
collation_server=utf8_unicode_ci
character_set_server=utf8 

Saya menemukan ide ini di sini: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html di komentar pengguna pertama / satu-satunya di bagian bawah halaman. Dia menyebutkan bahwa skip-character-set-client-handshake memiliki arti penting.


Jawaban tanpa suara dan tidak dicintai ini adalah satu-satunya hal yang membantu saya! Jadi itu mendapat suara saya, itu pasti. skip-character-set-client-handshakeadalah kuncinya.
Marcus


0

Atur Anda database collationuntuk UTF-8 kemudian menerapkan table collationke default database.


-1

Jawaban Anda adalah Anda dapat mengkonfigurasi dengan Pengaturan MySql. In My Answer mungkin ada sesuatu yang keluar dari konteksnya tetapi ini juga tahu itu membantu Anda.
cara mengkonfigurasi Character SetdanCollation .

Untuk aplikasi yang menyimpan data menggunakan set karakter MySQL default dan collation ( latin1, latin1_swedish_ci), tidak diperlukan konfigurasi khusus. Jika aplikasi memerlukan penyimpanan data menggunakan kumpulan karakter atau susunan yang berbeda, Anda dapat mengonfigurasi informasi kumpulan karakter dengan beberapa cara:

  • Tentukan pengaturan karakter per database. Misalnya, aplikasi yang menggunakan satu database mungkin memerlukan utf8, sedangkan aplikasi yang menggunakan database lain mungkin memerlukan sjis.
  • Tentukan pengaturan karakter saat startup server. Ini menyebabkan server menggunakan pengaturan yang diberikan untuk semua aplikasi yang tidak membuat pengaturan lain.
  • Tentukan pengaturan karakter pada waktu konfigurasi , jika Anda membangun MySQL dari sumber. Hal ini menyebabkan server menggunakan pengaturan yang diberikan untuk semua aplikasi, tanpa harus menentukannya saat startup server.

Contoh yang ditampilkan di sini untuk pertanyaan Anda untuk menyetel himpunan karakter utf8, di sini juga menyetel pemeriksaan agar lebih berguna ( utf8_general_cipemeriksaan`).

Tentukan pengaturan karakter per database

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Tentukan pengaturan karakter saat startup server

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

Tentukan pengaturan karakter pada waktu konfigurasi MySQL

shell> cmake . -DDEFAULT_CHARSET=utf8 \
           -DDEFAULT_COLLATION=utf8_general_ci

Untuk melihat nilai dari kumpulan karakter dan variabel sistem pemeriksaan yang berlaku untuk koneksi Anda, gunakan pernyataan berikut:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

Ini mungkin jawaban yang panjang tetapi ada banyak cara, Anda dapat menggunakan. Semoga jawaban saya bermanfaat untuk Anda. untuk informasi lebih lanjut http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html


-2

SET NAMES UTF8

Ini adalah triknya


2
Saat menggunakan SET NAMES UTF8(atau UTF8mb4) benar, Anda tidak menjelaskan apa fungsinya (kumpulan karakter yang digunakan untuk koneksi ini). "Ini melakukan trik" terdengar seperti itu akan menyelesaikan masalah (membuat MySQL menangani UTF-8 dengan benar), tetapi banyak database MySQL diatur ke latin1 secara default, sehingga itu tidak akan menjadikannya solusi yang tepat. Saya akan mengubah charset default dan charset tabel menjadi utf8mb4. Sungguh, jawaban ini agak kurang lengkap, jadi saya tidak suka.
basic6

-2

KONEKSI DATABASE KE UTF-8

$connect = mysql_connect('$localhost','$username','$password') or die(mysql_error());
mysql_set_charset('utf8',$connect);
mysql_select_db('$database_name','$connect') or die(mysql_error());

-3

Setel koneksi database Anda ke UTF8:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS)){          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  }

Jika menjalankan PHP, jangan gunakan mysql_*antarmuka yang tidak digunakan lagi . Beralih ke mysqli_*atau PDO.
Rick James

-3

Mampu menemukan solusi. Jalankan perintah berikut seperti yang ditentukan di http://technoguider.com/2015/05/utf8-set-up-in-mysql/

SET NAMES UTF8;
set collation_server = utf8_general_ci;
set default-character-set = utf8;
set init_connect = SET NAMES utf8′;
set character_set_server = utf8;
set character_set_client = utf8;

Dua baris terakhir adalah redundan, karena yang pertama sudah termasuk: dev.mysql.com/doc/refman/5.0/en/charset-connection.html
DanielM

Juga bukan solusi lengkap. Kolom perlu CHARACTER SET utf8. roottidak akan menjalankan yang paling penting init_connect.
Rick James
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.