MySQL'de utf8 isimleri belirleyin?


110

MySQL kullanan PHP betiklerinde genellikle buna benzer bir şey görüyorum

query("SET NAMES utf8");   

Bunu henüz herhangi bir proje için yapmak zorunda kalmadım, bu yüzden onunla ilgili birkaç temel sorum var.

  1. Bu sadece PDO ile yapılan bir şey mi?
  2. PDO'ya özgü bir şey değilse, bunu yapmanın amacı nedir? Bunun mysql için kodlamayı ayarladığını anlıyorum ama demek istediğim, hiç kullanmak zorunda kalmadım, bu yüzden neden kullanmak isteyeyim?

4
SQL enjeksiyonu nedeniyle "SET NAMES utf8" kullanılmamalıdır. Ayrıntılar için php.net/manual/en/mysqlinfo.concepts.charset.php adresine bakın.
masakielastik

3
@masakielastic 'set names utf8' ayarının sql enjeksiyonu için nerede bir tehdit olduğunu görmüyorum? Uygun MySQL API kullanarak iş parçacığı nerede?
geniş bant

3
Kabalığım için özür dilerim. İrcmaxell'in cevabına bakın: stackoverflow.com/a/12118602/531320 Althogh "SET İSİMLERİ" UTF-8 kullandığınız sürece sorun yaşamaz, gelecekte GBK veya Big5 (Çince) veya Shift_JIS (Japonca) kullanma olasılığınız inkar edilemez. .
masakielastic

Yanıtlar:


74

'Ñ' veya 'ö' gibi saf ASCII ile temsil edilemeyen karakterlere sahip sunucuya veri göndermek istediğinizde gereklidir.

MySQL örneği, istemci bağlantılarından varsayılan olarak UTF-8 kodlaması bekleyecek şekilde yapılandırılmadıysa (çoğu, konumunuza ve platforma bağlıdır.)

Unicode'un nasıl çalıştığını bilmiyorsanız http://www.joelonsoftware.com/articles/Unicode.html'yi okuyun .

Okuma İster "SET NAMES" kullanmaya SET İSİMLERİ alternatifleri ve ne tam olarak yaklaşık öyle görmek.


3
'ö' ve 'ñ' genişletilmiş ASCII'dir. Hala SET NAMES UTF8onlar için ihtiyacınız olur mu?
Tim

2
Sık sık utf8_decode ($ my_text) eklemem gerektiğini fark ettim; PHP'de veriler MySQL'den sorgulandığında web sitelerinde düzgün bir şekilde gösterilecek özel UTF-8 karakterleri almak için. MySQL'de tablolarım ve sütunlarım UTF-8 olarak ayarlandı - bu yüzden bu gerekli mi?
NexusRex

1
@ Vinko Vrsalovic: Gerekli değil ... Tüm dosyalarım utf8'de vardı ama önceki barındırıcım mysql karakter setini latin1 olarak ayarladı ve mysql'e utf8'de karakter gönderdiğimi söylemedim (dolayısıyla utf8 isimleri ayarlayın) onları depoladı latin karakter setinde ve tüm özel karakterlerim (Slovence čšž) bir araba tarafından istila edilmiş gibi görünüyordu - bir şey daha: phpmyadmin'de bir arama yaptığınızda sonuç bulamayacaksınız, çünkü
č Å'ye

Ayrıca, sunucunun sonuçları istemciye geri göndermek için kullanması gereken karakter kümesini de belirttiğini ve bu nedenle, örneğin bir SELECTifade kullanarak bu verileri alırken de gerekli olduğunu unutmayın .
Leopoldo Sanczyk

@Tim. "Genişletilmiş ASCII" diye bir şey gerçekten yok. Hepsi genişletilmiş ASCII olarak adlandırılabilecek bir sürü farklı kodlama vardır (ilk yarının ASCII ile aynı olduğu ve bunlardan çok sayıda olduğu herhangi bir tek baytlık karakter kümesi).
TRiG

43

Gönderen manuel :

SET İSİMLERİ, istemcinin sunucuya SQL ifadeleri göndermek için hangi karakter setini kullanacağını belirtir.

Daha ayrıntılı olarak (ve bir kez daha kılavuzdan nedensizce kaldırıldı ):

SET İSİMLERİ, istemcinin sunucuya SQL ifadeleri göndermek için hangi karakter setini kullanacağını belirtir. Bu nedenle, SET NAMES 'cp1251' sunucuya "bu istemciden gelecek mesajlar cp1251 karakter setinde olacak" der. Ayrıca, sunucunun sonuçları istemciye geri göndermek için kullanması gereken karakter setini de belirtir. (Örneğin, bir SELECT ifadesi kullanırsanız sütun değerleri için hangi karakter kümesinin kullanılacağını belirtir.)


6
Seni seviyorum. Sadece akşamımı yaptım!
karim79

34

Kodlamayı doğru yapmak gerçekten zor - çok fazla katman var:

  • Tarayıcı
  • Sayfa
  • PHP
  • MySQL

PHP'den "SET CHARSET utf8" SQL komutu, veritabanında nasıl saklanırsa saklansın, istemci tarafının (PHP) verileri utf8'de almasını sağlayacaktır. Tabii ki, önce doğru şekilde saklanmaları gerekir.

DDL tanımı ve gerçek veriler

Bir tablo / sütun için tanımlanan kodlama, verilerin o kodlamada olduğu anlamına gelmez. Olarak tanımlanmış utf8ancak farklı kodlama olarak saklanmış bir tablonuz varsa , MySQL bunları kabul edecek ve başınız utf8belada olacaktır. Bu, önce bunu düzeltmeniz gerektiği anlamına gelir.

Kontrol edilecekler

Her katmanda veri akışını hangi kodlamayı kontrol etmeniz gerekir.

  • HTTP başlıklarını, başlıklarını kontrol edin.
  • İsteğin gövdesinde gerçekten neyin gönderildiğini kontrol edin.
  • MySQL'in hemen hemen her yerde kodlama içerdiğini unutmayın:
    • Veri tabanı
    • Tablolar
    • Sütunlar
    • Bir bütün olarak sunucu
    • Müşteri
      Her yerde doğru olanın olduğundan emin olun.

Dönüştürmek

Örneğin veri alırsanız windows-1250ve depolamak istiyorsanız, depolamadan utf-8önce bu SQL'i kullanın:

SET NAMES 'cp1250';

Veritabanında verileriniz varsa windows-1250ve geri almak istiyorsanız utf8, şunu kullanın:

SET CHARSET 'utf8';

Birkaç not daha:

  • Verileri göstermek için çok "akıllı" araçlara güvenmeyin. Örneğin phpMyAdmin gerçekten kötü kodlama yapıyor (kullandığım sırada yapıyordu). Ve tüm katmanlardan geçtiği için bulması zor.
  • Ayrıca, Internet Explorer, garip kurallara dayalı olarak kodlamayı "tahmin etme" gibi gerçekten aptalca bir davranışa sahipti.
  • Kodlamayı değiştirebileceğiniz basit düzenleyiciler kullanın. MySQL Workbench'i tavsiye ederim.

19

Bu sorgu, veri tabanında veri oluşturan veya güncelleyen sorgudan önce yazılmalıdır, bu sorgu şöyle görünür:

mysql_query("set names 'utf8'");

Başlıkta kullandığınız kodlamayı yazmanız gerektiğini unutmayın, örneğin utf-8 kullanıyorsanız bunu başlık kısmına bu şekilde eklerseniz veya Internet Explorer'da bir soruna neden olur.

yani sayfanız buna benziyor

<html>
    <head>
        <title>page title</title>
        <meta charset="UTF-8" />   
    </head>
    <body>
    <?php
            mysql_query("set names 'utf8'");   
            $sql = "INSERT * FROM ..... ";  
            mysql_query($sql);
    ?>    

    </body>
</html>

8
PHP mysql kitaplığını kullanmamalısınız, bunun yerine MySQLi veya PDO kullanmalısınız.
André Figueira

Harika cevap, örnek için teşekkürler. Yapmam gereken şeyi görselleştirmeme yardımcı olan tek cevap bu ve sorunumu çözdü!
GTS Joe

1
Son etiket <html> olmamalı </html>
GTS Joe

9

Çözüm şudur

 $conn->set_charset("utf8");

5

Bunu bir SQL sorgusu aracılığıyla yapmak yerine php işlevini kullanın: mysqli :: set_charset mysqli_set_charset

Note:

This is the preferred way to change the charset. Using mysqli_query() to set it (such as SET NAMES utf8) is not recommended.

Daha fazla bilgi için MySQL karakter seti kavramları bölümüne bakın.

dan http://www.php.net/manual/en/mysqli.set-charset.php


1

Hepinize teşekkürler!

kullanmayın: query ("SET NAMES utf8"); bu bir kurulum işi ve bir sorgu değil. setCharset () (veya benzer bir yöntem) ile bir bağlantı başladıktan sonra düzeltin

parctice küçük bir şey:

durum:

  • varsayılan olarak mysql sunucusu latin1 konuşur
  • delik uygulamanız utf8'de
  • bağlantı ekstra olmadan yapılır (yani: latin1) (SET NAMES yok utf8 ..., set_charset () yöntemi / işlevi yok)

Mysql karakterleri işleyebildiği sürece veri depolamak ve okumak sorun değildir. db'ye bakarsanız, içinde bir saçmalık olduğunu göreceksiniz (örneğin phpmyadmin kullanarak).

şimdiye kadar bu bir sorun değil! (yanlış ama sıklıkla işe yarar (Avrupa'da)) ..

.. başka bir istemci / program veya doğru çalışan değiştirilmiş bir kitaplık, verileri okuyamaz / kaydedemez. o zaman başın büyük belada!


0

Sadece PDO değil. Sql yanıtı '????' şeklinde ise semboller, karakter setinizin önceden ayarlanmış olması (umarız UTF-8) gerçekten tavsiye eder:

if (!$mysqli->set_charset("utf8")) 
 { printf("Can't set utf8: %s\n", $mysqli->error); }

veya prosedür stili aracılığıyla mysqli_set_charset($db,"utf8")

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.