Встановити імена utf8 в MySQL?


110

Я часто бачу щось подібне до цього нижче в скриптах PHP за допомогою MySQL

query("SET NAMES utf8");   

Мені ніколи не доводилося цього робити жодному проекту, тому у мене є кілька основних питань щодо цього.

  1. Це щось, що робиться тільки з PDO?
  2. Якщо це не конкретна річ із ЗНО, то яка мета цього робити? Я розумію, що це встановлення кодування для mysql, але я маю на увазі, мені ніколи не довелося його використовувати, тому чому я б хотів ним користуватися?

4
Слід уникати "SET NAMES utf8" через інжекцію SQL. Докладніше див. У php.net/manual/en/mysqlinfo.concepts.charset.php.
masakielastic

3
@masakielastic Я не бачу, де встановлення "set names utf8" є загрозою для введення sql? Використовуючи належний API MySQL, де нитка?
широкосмуговий

3
Вибачте за мою недоброзичливість. Див ircmaxell у відповідь: stackoverflow.com/a/12118602/531320 Althogh «SET NAMES» не має жодних проблем до тих пір , як використання UTF-8, можливість ви будете використовувати GBK або Big5 (китайський) або SHIFT_JIS (японський) в майбутньому не викликає сумнівів .
masakielastic

Відповіді:


74

Він потрібен щоразу, коли ви хочете відправити дані на сервер із символами, які не можуть бути представлені в чистому ASCII, наприклад, "ñ" або "ö".

Це якщо екземпляр MySQL не налаштований очікувати кодування UTF-8 за замовчуванням від клієнтських з'єднань (їх багато, залежно від вашого місця розташування та платформи.)

Прочитайте http://www.joelonsoftware.com/articles/Unicode.html, якщо ви не знаєте, як працює Unicode.

Прочитайте, чи використовувати "SET NAMES", щоб побачити альтернативи SET NAMES та про що це йдеться.


3
'ö' і 'ñ' розширені ASCII. Вам все-таки знадобиться SET NAMES UTF8для них?
Тім

2
Я виявив, що мені часто доводиться додавати utf8_decode ($ my_text); в PHP, щоб отримати спеціальні символи UTF-8, які правильно відображатимуться на веб-сайтах, коли дані запитувались з MySQL. У MySQL мої таблиці та стовпці встановлені на UTF-8 - значить, чи потрібно це?
NexusRex

1
@ Vinko Vrsalovic: Не обов'язково ... У мене були всі файли у utf8, але в моєму попередньому хостері було встановлено набір даних mysql на latin1, і тому що я не сказав, що я mysql надсилаю символи у utf8 (звідси встановити імена utf8), він зберігав їх в латинській наборі, і всі мої спеціальні символи (словенський čšž) виглядали так, що їх перегнав автомобіль - ще одне: коли ви здійснюєте пошук у phpmyadmin, ви не знайдете результатів, тому що č схожий на Å і так далі
Ерік Черпняк

Зауважте, що він також визначає набір символів, який сервер повинен використовувати для відправки результатів назад клієнту, тому він також необхідний при отриманні цих даних, використовуючи, наприклад, SELECTзаяву.
Леопольдо Санчик

@Tim. Насправді немає такого поняття, як "розширений ASCII". Існує ціла купа різних кодувань, які всі можна назвати розширеними ASCII (будь-який однобайтовий набір символів, коли перша половина збігається з ASCII, і є багато таких).
TRiG

43

З посібника :

SET NAMES вказує, який набір символів клієнт використовуватиме для надсилання SQL-операторів на сервер.

Більш детально, (і ще раз, безкоштовно знятий з посібника ):

SET NAMES вказує, який набір символів клієнт використовуватиме для надсилання SQL-операторів на сервер. Таким чином, SET NAMES 'cp1251' повідомляє серверу: «майбутні вхідні повідомлення цього клієнта мають набір символів cp1251». Він також визначає набір символів, який сервер повинен використовувати для відправки результатів назад клієнту. (Наприклад, він вказує, який набір символів використовувати для значень стовпців, якщо ви використовуєте оператор SELECT.)


6
Я тебе люблю. Щойно зробив мій вечір!
karim79

34

Отримати правильне кодування дійсно складно - занадто багато шарів:

  • Веб-переглядач
  • Сторінка
  • PHP
  • MySQL

Команда SQL "SET CHARSET utf8" від PHP забезпечить, щоб клієнтська сторона (PHP) отримала дані у utf8, незалежно від того, як вони зберігаються в базі даних. Звичайно, спочатку їх потрібно правильно зберігати.

Визначення DDL порівняно з реальними даними

Кодування, визначене для таблиці / стовпця, насправді не означає, що дані перебувають у кодуванні. Якщо у вас трапилася таблиця, визначена як, utf8але зберігається як різницьке кодування, то MySQL буде ставитись до них як utf8до вас, і у вас виникли проблеми. Що означає, що ви повинні це виправити спочатку.

Що перевірити

Вам потрібно перевірити, що кодує потік даних на кожному шарі.

  • Перевірте заголовки та заголовки HTTP.
  • Перевірте, що насправді надіслано в тій частині запиту.
  • Не забувайте, що MySQL має кодування майже скрізь:
    • База даних
    • Столи
    • Стовпці
    • Сервер в цілому
    • Клієнт
      Переконайтесь, що скрізь є правильний.

Перетворення

Якщо ви отримуєте дані, наприклад windows-1250, і хочете їх зберігати utf-8, то використовуйте цей SQL перед зберіганням:

SET NAMES 'cp1250';

Якщо ви маєте дані в БД як windows-1250і хочете відновити їх utf8, використовуйте:

SET CHARSET 'utf8';

Ще кілька приміток:

  • Не покладайтеся на занадто "розумні" інструменти для показу даних. Наприклад, phpMyAdmin робить (робив, коли я його використовував) кодування дуже погано. І він проходить через усі шари, тому це важко з'ясувати.
  • Крім того, Internet Explorer мав справді дурну поведінку "вгадувати" кодування на основі дивних правил.
  • Використовуйте прості редактори, де ви можете переключити кодування. Я рекомендую MySQL Workbench.

19

Цей запит повинен бути написаний перед запитом, який створює або оновлює дані в базі даних, такий запит виглядає так:

mysql_query("set names 'utf8'");

Зауважте, що ви повинні написати кодер, який ви використовуєте у заголовку, наприклад, якщо ви використовуєте utf-8, ви додасте його так у заголовок, або це вирішить проблему з Internet Explorer

тому ваша сторінка виглядає приблизно так

<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, натомість ви повинні використовувати MySQLi або PDO.
Андре Фігерейра

Чудова відповідь, дякую за приклад. Це одна відповідь, яка допомогла мені уявити, що мені потрібно зробити, і це вирішило мою проблему!
GTS Joe

1
Останній тег повинен бути </html> не <html>
GTS Joe


5

Замість цього за допомогою SQL запиту використовуйте функцію 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.

Додаткову інформацію див. У розділі концепцій набору символів MySQL.

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


1

Дякую усім!

не використовувати: query ("НАЗВАЙТЕ ІМИ utf8"); це налаштування, а не запит. покладіть його безпосередньо після початку з'єднання з setCharset () (або подібним методом)

якась дрібниця в parctice:

статус:

  • сервер mysql за замовчуванням розмовляє latin1
  • ваш отвір додаток у utf8
  • з'єднання здійснюється без зайвих (так: latin1) (без SET NAMES utf8 ..., без методу / функції set_charset ())

Зберігання та читання даних не є проблемою, оскільки довгий mysql може обробляти символів. якщо ви заглянете в db, ви вже побачите, що в ньому є лайно (наприклад, використання phpmyadmin).

до цих пір це не проблема! (неправильно, але працює часто (в Європі)) ..

..не якщо інший клієнт / програма або змінена бібліотека, яка працює правильно, буде читати / зберігати дані. то ви у великій неприємності!


0

Не тільки PDO. Якщо відповідь sql типу "????" символів, попередньо встановлених вами шаблону (сподіваюся, UTF-8) дійсно рекомендується:

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

або через стиль процедури mysqli_set_charset($db,"utf8")

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.