SET NAMA utf8 di MySQL?

110

Saya sering melihat sesuatu yang mirip di bawah ini di skrip PHP menggunakan MySQL

query("SET NAMES utf8");   

Saya belum pernah melakukan ini untuk proyek apa pun, jadi saya punya beberapa pertanyaan dasar tentang itu.

  1. Apakah ini sesuatu yang dilakukan hanya dengan PDO?
  2. Kalau bukan spesifik PDO, lalu apa tujuannya? Saya menyadari itu adalah pengaturan pengkodean untuk mysql tapi maksud saya, saya tidak pernah menggunakannya jadi mengapa saya ingin menggunakannya?
JasonDavis
sumber
4
"SET NAMES utf8" harus dihindari karena injeksi SQL. Lihat php.net/manual/en/mysqlinfo.concepts.charset.php untuk detailnya.
masakielastic
3
@ Masakielastic Saya tidak melihat di mana pengaturan 'set names utf8' merupakan ancaman bagi sql injection? Menggunakan MySQL API yang tepat di mana utasnya?
broadband
3
Maaf atas ketidakbaikan saya. Lihat jawaban ircmaxell: stackoverflow.com/a/12118602/531320 Meskipun "SET NAMES" tidak bermasalah selama menggunakan UTF-8, kemungkinan Anda akan menggunakan GBK atau Big5 (China) atau Shift_JIS (Jepang) di masa mendatang tidak dapat disangkal .
masakielastic

Jawaban:

74

Ini diperlukan kapan pun Anda ingin mengirim data ke server yang memiliki karakter yang tidak dapat direpresentasikan dalam ASCII murni, seperti 'ñ' atau 'ö'.

Bahwa jika instance MySQL tidak dikonfigurasi untuk mengharapkan encoding UTF-8 secara default dari koneksi klien (banyak, tergantung pada lokasi dan platform Anda.)

Baca http://www.joelonsoftware.com/articles/Unicode.html jika Anda tidak mengetahui cara kerja Unicode.

Baca Apakah akan menggunakan "SET NAMA" untuk melihat SET NAMES alternatif dan tentang apa sebenarnya itu.

Vinko Vrsalovic
sumber
3
'ö' dan 'ñ' diperpanjang ASCII. Apakah Anda masih membutuhkannya SET NAMES UTF8?
Tim
2
Saya telah menemukan bahwa saya sering harus menambahkan utf8_decode ($ my_text); di PHP untuk mendapatkan karakter UTF-8 khusus untuk ditampilkan di situs web dengan benar ketika data diminta dari MySQL. Tabel dan kolom saya disetel ke UTF-8 di MySQL — jadi apakah ini perlu?
NexusRex
1
@ Vinko Vrsalovic: Belum tentu ... Saya memiliki semua file saya di utf8 tetapi penghosting saya sebelumnya telah menyetel charset mysql ke latin1 dan karena saya belum memberi tahu mysql bahwa saya mengirim karakter di utf8 (karenanya menetapkan nama utf8) itu menyimpannya dalam bahasa latin charset dan semua karakter khusus saya (bahasa Slovenia čšž) tampak seperti dibanjiri oleh mobil - satu hal lagi: ketika Anda melakukan pencarian di phpmyadmin Anda tidak akan menemukan hasil, karena a č seperti Å dan seterusnya
Erik Čerpnjak
Perhatikan bahwa ini juga menentukan set karakter yang harus digunakan server untuk mengirim hasil kembali ke klien, oleh karena itu juga diperlukan saat menerima data ini, misalnya menggunakan SELECTpernyataan.
Leopoldo Sanczyk
@Tim. Sebenarnya tidak ada yang namanya "ASCII diperpanjang". Ada sejumlah besar pengkodean berbeda yang semuanya dapat disebut ASCII diperpanjang (kumpulan karakter byte tunggal apa pun di mana paruh pertama sama dengan ASCII, dan ada banyak sekali).
TRiG
43

Dari manual :

SET NAMES menunjukkan set karakter apa yang akan digunakan klien untuk mengirim pernyataan SQL ke server.

Lebih rumit lagi, (dan sekali lagi, diambil secara serampangan dari manual ):

SET NAMES menunjukkan set karakter apa yang akan digunakan klien untuk mengirim pernyataan SQL ke server. Jadi, SET NAMES 'cp1251' memberi tahu server, "pesan masuk di masa mendatang dari klien ini berada dalam kumpulan karakter cp1251". Ini juga menentukan set karakter yang harus digunakan server untuk mengirim hasil kembali ke klien. (Misalnya, ini menunjukkan kumpulan karakter apa yang digunakan untuk nilai kolom jika Anda menggunakan pernyataan SELECT.)

karim79.dll
sumber
6
Aku cinta kamu. Baru saja membuat malam saya!
karim79
34

Melakukan encoding dengan benar sangat sulit - ada terlalu banyak lapisan:

  • Browser
  • Halaman
  • PHP
  • MySQL

Perintah SQL "SET CHARSET utf8" dari PHP akan memastikan bahwa sisi klien (PHP) akan mendapatkan data di utf8, tidak peduli bagaimana mereka disimpan dalam database. Tentu saja, mereka perlu disimpan dengan benar terlebih dahulu.

Definisi DDL vs. data nyata

Pengkodean yang ditentukan untuk tabel / kolom tidak berarti bahwa data berada dalam pengkodean itu. Jika Anda kebetulan memiliki tabel yang didefinisikan sebagai utf8tetapi disimpan sebagai pengkodean yang berbeda, maka MySQL akan memperlakukannya sebagai utf8dan Anda dalam masalah. Artinya Anda harus memperbaiki ini dulu.

Apa yang harus diperiksa

Anda perlu memeriksa pengkodean aliran data di setiap lapisan.

  • Periksa header HTTP, header.
  • Periksa apa yang sebenarnya dikirim dalam isi permintaan.
  • Jangan lupa bahwa MySQL memiliki pengkodean hampir di semua tempat:
    • Database
    • Tabel
    • Kolom
    • Server secara keseluruhan
    • Klien
      Pastikan ada orang yang tepat di mana-mana.

Konversi

Jika Anda menerima data misalnya windows-1250, dan ingin menyimpannya utf-8, gunakan SQL ini sebelum menyimpan:

SET NAMES 'cp1250';

Jika Anda memiliki data di DB sebagai windows-1250dan ingin mengambil utf8, gunakan:

SET CHARSET 'utf8';

Beberapa catatan lagi:

  • Jangan mengandalkan alat yang terlalu "pintar" untuk menampilkan data. Misalnya phpMyAdmin tidak (melakukan ketika saya menggunakannya) pengkodean sangat buruk. Dan itu melewati semua lapisan sehingga sulit untuk menemukannya.
  • Selain itu, Internet Explorer memiliki perilaku yang sangat bodoh dalam "menebak" pengkodean berdasarkan aturan yang aneh.
  • Gunakan editor sederhana tempat Anda dapat beralih encoding. Saya merekomendasikan MySQL Workbench.
Ondra Žižka
sumber
19

Query ini harus ditulis sebelum query yang membuat atau memperbarui data dalam database, query ini terlihat seperti:

mysql_query("set names 'utf8'");

Perhatikan bahwa Anda harus menulis penyandian yang Anda gunakan di tajuk misalnya jika Anda menggunakan utf-8 Anda menambahkannya seperti ini di tajuk atau itu akan menimbulkan masalah dengan Internet Explorer

jadi halaman Anda terlihat seperti ini

<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>
usama sulaiman
sumber
8
Anda seharusnya tidak menggunakan pustaka PHP mysql sebagai gantinya Anda harus menggunakan MySQLi atau PDO.
André Figueira
Jawaban bagus, terima kasih untuk contohnya. Ini adalah satu jawaban yang membantu saya memvisualisasikan apa yang perlu saya lakukan dan itu menyelesaikan masalah saya!
GTS Joe
1
Tag terakhir harus </html> bukan <html>
GTS Joe
9

Solusinya adalah

 $conn->set_charset("utf8");
nurp
sumber
5

Alih-alih melakukan ini melalui kueri SQL, gunakan fungsi php: 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.

Lihat bagian konsep kumpulan karakter MySQL untuk informasi lebih lanjut.

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

pengguna1783273
sumber
1

Terima kasih semuanya!

jangan gunakan: query ("SET NAMES utf8"); ini adalah hal-hal penyiapan dan bukan kueri. luruskan setelah koneksi dimulai dengan setCharset () (atau metode serupa)

beberapa hal kecil di parctice:

status:

  • server mysql secara default berbicara latin1
  • aplikasi hole Anda ada di utf8
  • koneksi dibuat tanpa tambahan (jadi: latin1) (tidak ada SET NAMES utf8 ..., tidak ada set_charset () metode / fungsi)

Menyimpan dan membaca data tidak masalah selama mysql dapat menangani karakternya. jika Anda melihat di db Anda akan melihat ada omong kosong di dalamnya (misalnya menggunakan phpmyadmin).

sampai sekarang ini tidak menjadi masalah! (salah tapi sering berhasil (di eropa)) ..

..kecuali klien / program lain atau pustaka yang diubah, yang berfungsi dengan benar, akan membaca / menyimpan data. maka kamu dalam masalah besar!

pengguna3162905
sumber
0

Tidak hanya PDO. Jika sql menjawab seperti '????' simbol, preset charset Anda (harap UTF-8) sangat direkomendasikan:

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

atau melalui gaya prosedur mysqli_set_charset($db,"utf8")

dmitry_podyachev
sumber