MySQL'in UTF-8'i düzgün bir şekilde işlemesini sağlama


102

Dün sorduğum bir soruya verilen yanıtlardan biri, veritabanımın UTF-8 karakterlerini doğru şekilde işleyebildiğinden emin olmam gerektiğini önerdi. Bunu MySQL ile nasıl yapabilirim?


4
Umarım çeşitli MySQL sürümlerini, uyumsuzlukları vb. Kapsayan kapsamlı bir yanıt alırız.
Edward Z. Yang


1
@ EdwardZ.Yang - MySQL 4.1 tanıtıldı CHARACTER SETs; 5.1.24, 5.1.62'de başka bir harmanlama eklenerek düzeltilen (muhtemelen işleri daha da kötüleştiren) Alman keskin-s (ß) harmanlamasını karıştırdı; 5.5.3 utf8'i yeni karakter seti utf8mb4 ile doldurdu.
Rick James

1
Bu soru da bununla tamamen aynı .. Lütfen şu stackoverflow.com/questions/3513773/… 'e bakın
Nyein Aung

Bu cevapların çoğunun tamamen yanlış olduğuna işaret etmeye değer. Kullanmayın utf8. Yalnızca 3 baytlık karakterleri destekler. MySQL'de kullanmanız gereken doğru karakter seti utf8mb4.
Brendan Byrd

Yanıtlar:


89

Güncelleme:

Kısa cevap - Neredeyse her zaman utf8mb4karakter kümesini ve utf8mb4_unicode_ciharmanlamayı kullanmalısınız.

Veritabanını değiştirmek için:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Görmek:

Orijinal Cevap:

MySQL 4.1 ve üzeri, varsayılan bir UTF-8 karakter kümesine sahiptir. Bunu my.cnfdosyanızda doğrulayabilirsiniz , hem istemciyi hem de sunucuyu ( default-character-setve character-set-server) ayarlamayı unutmayın .

UTF-8'e dönüştürmek istediğiniz mevcut verileriniz varsa, veritabanınızı boşaltın ve aşağıdakilerden emin olarak UTF-8 olarak geri alın:

  • SET NAMES utf8veritabanına sorgulamadan / eklemeden önce kullanın
  • DEFAULT CHARSET=utf8yeni tablolar oluştururken kullan
  • bu noktada MySQL istemciniz ve sunucunuz UTF-8 olmalıdır (bakınız my.cnf). Kullandığınız tüm dillerin (PHP gibi) da UTF-8 olması gerektiğini unutmayın. PHP'nin bazı sürümleri kendi MySQL istemci kitaplıklarını kullanır ve bu, UTF-8 farkında olmayabilir.

Mevcut verileri taşımak istiyorsanız, önce yedeklemeyi unutmayın! İşler planlandığı gibi gitmediğinde birçok tuhaf veri parçalanması meydana gelebilir!

Bazı kaynaklar:


29
Anladığım kadarıyla utf8MySQL içinde yalnızca tam Unicode'un küçük bir alt kümesine atıfta bulunuluyor. Bunun utf8mb4yerine tam desteği zorlamak için kullanmalısınız . Mathiasbynens.be/notes/mysql-utf8mb4'e bakın "Uzun bir süredir MySQL'in utf8 karakter kümesini veritabanları, tablolar ve sütunlar için kullanıyordum, bunun yukarıda açıklanan UTF-8 kodlamasına eşlendiğini varsayarak ."
Aaron McDaid

7
MySQL hiçbir zaman UTF-8 varsayılan karakter setine sahip olmamıştır. 4.1 ve 5.x'den en son 5.7'ye kadar tüm kullanım latin1ve latin1_swedish_civarsayılan karakter seti ve harmanlama için. Onay için MySQL kılavuzundaki "Sunucu Karakter Seti ve Harmanlama" sayfaya bakın: dev.mysql.com/doc/refman/5.1/en/charset-server.html
Animizm

2
@TimTisdall utf8mb4Metnin çoğu ASCII olduğunda ekstra depolama alanı almaktan endişelenmenize gerek yok . charDizeler önceden tahsis edilmiş olsa da , varchardizeler değildir - bu belge sayfasındaki son birkaç satıra bakın . Örneğin, char(10)utf8mb4 altında karamsar olarak 40 bayt ayıracak, ancak varchar(10)değişken uzunluk kodlamasına uygun olarak bayt ayıracaktır.
Kevin A. Naudé

1
@Kevin Bunu yanlış anladığını düşünüyorum. Maksimum satır uzunluğunun 64k olduğunu düşünüyorum. Bunun sadece 1 / 4'ünü bir utf8mb4 alanı yapabilirsiniz çünkü bu kadar alan ayırması gerekiyordu. Yani, ASCII olsa bile yalnızca 16k karakter girebilirsiniz.
Tim Tisdall

1
@TimTisdall Oh, üst sınırlardan bahsediyorsun. Evet, bunlar daha düşük. Neyse ki, mysql'in yeni sürümleri otomatik yükseltme edecek varchar(n)kadar textbir değiştirmeye çalışırsanız veri türü varchar(n)(Uyarı yayınlanmadan iken) uygulanabilir bayt boyutundan daha büyük alanını. Bir endeks aynı zamanda daha düşük bir en kötü durum üst sınırına sahip olacaktır ve bu başka sorunlar ortaya çıkarabilir.
Kevin A. Naudé

44

Bunu 'kalıcı' yapmak için my.cnf:

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

Kontrol etmek için müşteriye gidin ve bazı değişkenleri gösterin:

SHOW VARIABLES LIKE 'character_set%';

MySQL kurulumunda bir yere işaret eden ve olması gerekenler utf8dışında hepsinin olduğunu doğrulayın ...._filesystembinary..._dir


Benim durumumda işe yaramadı ama yine de verilen içerikle my.cf dosyasını / etc içinde oluşturdum. Kullandımcreate table my_name(field_name varchar(25) character set utf8);
Marek Bar

"DEĞİŞKENLERİ GİBİ GÖSTER 'character_set%';" komutu bana bağlantımla ilgili sorunu ortaya çıkardı. Teşekkürler!
javsmo

1
Bu doğru değil. MySQL çağrıları utf8"tam" UTF-8 değildir.
TWR Cole

32

MySQL 4.1 ve üzeri, çağırdığı, utf8ancak aslında UTF-8'in yalnızca bir alt kümesidir (yalnızca üç baytlık karakterlere izin verir ve daha küçük) varsayılan bir karakter kümesine sahiptir .

utf8mb4"Tam" UTF-8 istiyorsanız karakter kümeniz olarak kullanın .


5
Kesinlikle katılıyorum, bu tek doğru cevap. utf8ifadeler gibi karakterler içermez. utf8mb4yapar. Nasıl güncelleneceği hakkında daha fazla bilgi için bunu kontrol edin: mathiasbynens.be/notes/mysql-utf8mb4
jibai31

@Basti - Çoğunlukla doğru (yakın zamana kadar latin1 varsayılandı) ve tamamlanmadı (utf8 ile kodlanmış verilerin doğru şekilde eklenmesi / seçilmesi veya html'de görüntülenmesi tartışılmaz).
Rick James

Saygılarımla, @RickJames, Basti "şimdiye kadar" dedi - Bunu gönderdiğimde cevabını gördüğümü hatırlamıyorum.
TWR Cole

Ne yazık ki, utf8 problemlerinin 5 belirgin farklı belirtisi ve programcıların sorun yaratmak için yanlış yaptığı 4 şey var. Cevapların çoğu , düzeltilmesi gereken tek bir şeye işaret ediyor. Asıl soru geniş bir soruydu, bu yüzden yanıtın her şeye ihtiyacı vardı 4. Belki de Basti, sizin tek yönünüzün çözüm olduğu bir semptomu biliyordu .
Rick James

8
Bir kenara, bir an durup MySQL ekibine gerçekten iyi, sert bir bakış atmak istiyorum. o_o WTF mi düşünüyordunuz? Programınızda aslında UTF-8 olmayan "utf8" adlı bir kod sayfası oluşturarak ne kadar kafa karıştırdığınızın farkında mısınız? Lanet herifler. </rant>
TWR Cole

20

Kısa cevap: utf8mb44 yerde kullanın :

  • İstemcinizdeki baytlar utf8'dir, latin1 / cp1251 / etc değil.
  • SET NAMES utf8mb4 veya müşterinin MySQL ile bağlantısını kurarken eşdeğer bir şey
  • CHARACTER SET utf8mb4 tüm tablolarda / sütunlarda - kesinlikle ascii / hex / country_code / zip_code / vb. olan sütunlar hariç.
  • <meta charset charset=UTF-8>HTML'ye çıktı gönderiyorsanız. (Evet burada yazım farklıdır.)

Daha fazla bilgi ;
UTF8 tüm yol

Yukarıdaki bağlantılar, "tüm endişeleri ele almak için ayrıntılı kanonik yanıt gereklidir" sağlar. - Bu forumda bir alan sınırı vardır.

Düzenle

CHARACTER SET utf8mb4"Tüm" dünya karakterlerini COLLATION utf8mb4_unicode_520_ciiçermenin yanı sıra , tartışmasız en iyi her yönden harmanlama kullanmaktır. (Bu dillerdeki nüansları isteyenler için Türkçe, İspanyolca vb. Harmanlamalar da vardır.)


Benim yeni bağlantı almak çıkışından utf8 ilgli sorunlarla nasıl.
Rick James

Neden unicode_520_ci her yerde en iyisi değil: stackoverflow.com/a/49982378/62202
Louis

@Louis - Ve ima ettiğim gibi İspanyolca ve Türkçe (Polonyalıların yanı sıra) kullanıcılar mutlu olmayabilir. "Her yönden en iyisi" herkese biraz zarar verme eğilimindedir. MySQL 8.0, daha da yeni bir "en iyi" harmanlamaya sahiptir: utf8mb4_0900_ai_ci . Ne yazık ki, yine L = Ł.
Rick James

4

Karakter kümesi, veritabanının (varsayılan) ve tablonun bir özelliğidir. Bir göz atabilirsiniz (MySQL komutları):

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

Diğer bir deyişle; veritabanı karakter kümenizi kontrol etmek veya değiştirmek oldukça kolaydır:

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

1
Bu doğru değil. MySQL çağrıları utf8"tam" UTF-8 değildir.
TWR Cole


2

Javier'in çözümünü takip ettim, ancak my.cnf dosyasında bazı farklı satırlar ekledim:

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

Bu fikri burada buldum: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html sayfanın altındaki ilk / tek kullanıcı yorumunda. Atla-karakter-kümesi-müşteri-el sıkışmasının bir önemi olduğundan bahseder .


Bu sevilmeyen, sıfır oy cevabı bana yardımcı olan tek şeydi! Yani benim oyumu alıyor, bu kesinlikle kesin. skip-character-set-client-handshakeanahtar oldu.
Marcus


0

Kümenizle database collationiçin UTF-8 daha sonra uygulamak table collationveritabanı varsayılan.


-1

Cevabınız MySql Ayarları ile yapılandırabilirsiniz. Cevabım'da bağlam dışı bir şey olabilir, ancak bu aynı zamanda sizin için yardım olduğunu da bilir.
nasıl yapılandırılır Character SetveCollation .

Varsayılan MySQL karakter kümesini ve harmanlamayı ( latin1, latin1_swedish_ci) kullanarak veri depolayan uygulamalar için özel bir yapılandırmaya gerek yoktur. Uygulamalar farklı bir karakter seti veya harmanlama kullanarak veri depolamaya ihtiyaç duyuyorsa, karakter seti bilgilerini birkaç şekilde yapılandırabilirsiniz:

  • Veritabanı başına karakter ayarlarını belirtin. Örneğin, bir veritabanı kullanan uygulamalar gerektirebilirken utf8, başka bir veritabanını kullanan uygulamalar sjis gerektirebilir.
  • Sunucu başlangıcında karakter ayarlarını belirtin. Bu, sunucunun başka düzenlemeler yapmayan tüm uygulamalar için verilen ayarları kullanmasına neden olur.
  • Yapılandırma sırasında karakter ayarlarını belirtinMySQL'i kaynaktan oluşturuyorsanız, . Bu, sunucunun, sunucu başlangıcında bunları belirtmek zorunda kalmadan tüm uygulamalar için verilen ayarları kullanmasına neden olur.

Burada sorunuz için utf8 karakter kümesini ayarlamak için gösterilen örnekler, burada daha yararlı olması için harmanlamayı da ayarlayın ( utf8_general_ciharmanlama`).

Veritabanı başına karakter ayarlarını belirtin

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Sunucu başlangıcında karakter ayarlarını belirtin

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

MySQL yapılandırma zamanında karakter ayarlarını belirtin

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

Bağlantınız için geçerli olan karakter kümesi ve harmanlama sistemi değişkenlerinin değerlerini görmek için şu ifadeleri kullanın:

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

Bu uzun bir cevap olabilir, ancak kullanabileceğiniz her yol var. Umarım cevabım size yardımcı olur. daha fazla bilgi için http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html


-2

SET NAMES UTF8

Bu hile yapıyor


2
SET NAMES UTF8(Veya UTF8mb4) doğru olsa da , ne yaptığını açıklamazsınız (bu bağlantı için kullanılan karakter kümesi). "Bu hile yapıyor", sorunu çözecekmiş gibi geliyor (MySQL'in UTF-8'i düzgün bir şekilde işlemesini sağlar), ancak birçok MySQL veritabanı varsayılan olarak latin1'e ayarlanmıştır, bu yüzden bu onu uygun bir çözüm yapmaz. Ben ediyorum varsayılan karakter kümesi değiştirmek ve utf8mb4 için tablo karakter kümelerini. Gerçekten, bu cevap oldukça eksik, bu yüzden geri oy verdim.
basic6

-2

UTF-8'E VERİTABANI BAĞLANTISI

$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

Veritabanı bağlantınızı UTF8 olarak ayarlayın:

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

PHP çalıştırıyorsanız, kullanımdan kaldırılmış mysql_*arayüzü kullanmayın . mysqli_*Veya seçeneğine geçin PDO.
Rick James

-3

Bir çözüm bulabildim. Aşağıdakileri http://technoguider.com/2015/05/utf8-set-up-in-mysql/ adresinde belirtildiği gibi çalıştırdı

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;

İlk satır zaten bunları içerdiği için son iki satır gereksizdir: dev.mysql.com/doc/refman/5.0/en/charset-connection.html
DanielM

Ayrıca tam bir çözüm değil. Sütunların ihtiyacı var CHARACTER SET utf8. roottüm önemli olanı yürütmeyecek init_connect.
Rick James
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.