УСТАНОВИТЬ ИМЕНА utf8 в MySQL?

110

Я часто вижу что-то подобное в сценариях PHP, использующих MySQL.

query("SET NAMES utf8");   

Мне никогда не приходилось делать это ни для одного проекта, поэтому у меня есть пара основных вопросов по этому поводу.

  1. Это что-то, что делается только с PDO?
  2. Если это не специфическая вещь для PDO, то какова цель этого? Я понимаю, что он устанавливает кодировку для mysql, но я имею в виду, что мне никогда не приходилось ее использовать, так зачем мне ее использовать?
JasonDavis
источник
4
"SET NAMES utf8" следует избегать из-за внедрения SQL. Подробности см. На php.net/manual/en/mysqlinfo.concepts.charset.php.
masakielastic 08
3
@masakielastic Я не вижу, где установка 'set names utf8' представляет угрозу для внедрения sql? Используя правильный MySQL API, где находится поток?
широкополосный
3
Простите за мою недоброжелательность. См. Ответ ircmaxell: stackoverflow.com/a/12118602/531320 Althogh "SET NAMES" не имеет проблем, пока вы используете UTF-8, вероятность того, что вы будете использовать GBK или Big5 (китайский) или Shift_JIS (японский) в будущем, неоспорима. .
masakielastic

Ответы:

75

Это необходимо всякий раз, когда вы хотите отправить на сервер данные, содержащие символы, которые не могут быть представлены в чистом 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
@ Винко Врсалович: Не обязательно ... У меня были все мои файлы в utf8, но у моего предыдущего хостера была установлена ​​кодировка mysql на latin1, и поскольку я не сказал mysql, что я отправляю символы в utf8 (следовательно, установил имена utf8), он их сохранил в латинской кодировке и все мои специальные символы (словенский čšž) выглядели так, как будто они были захвачены машиной - еще одна вещь: когда вы выполняете поиск в phpmyadmin, вы не найдете результатов, потому что č похоже на Å и так далее
Эрик Черпняк
Обратите внимание, что он также определяет набор символов, который сервер должен использовать для отправки результатов обратно клиенту, поэтому он также необходим при получении этих данных, например, с помощью SELECTоператора.
Леопольдо Санчик
@Тим. На самом деле нет такой вещи, как «расширенный ASCII». Существует множество различных кодировок, которые можно назвать расширенным ASCII (любой однобайтовый набор символов, первая половина которого совпадает с ASCII, а их множество).
TRiG
43

Из руководства :

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

Более подробно (и снова взяты из руководства ):

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

karim79
источник
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

user1783273
источник
1

Спасибо всем!

не используйте: query ("SET NAMES utf8"); это настройка, а не запрос. установите его сразу после начала соединения с помощью setCharset () (или аналогичного метода)

какая-то мелочь в parctice:

положение дел:

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

Сохранение и чтение данных не проблема, пока mysql может обрабатывать символы. если вы посмотрите в db, вы уже увидите, что там есть дерьмо (например, с помощью phpmyadmin).

до сих пор это не проблема! (неверно, но часто работает (в европе)) ..

..если другой клиент / программа или измененная библиотека, которая работает правильно, не будет читать / сохранять данные. тогда у вас большие неприятности!

user3162905
источник
0

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

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

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

dmitry_podyachev
источник