Если у вас MySQL 4.x/5.x и ЛЮБЫЕ ПРОБЛЕМЫ С РУССКИМ - ЧИТАТЬ ЭТО!

Статус
В этой теме нельзя размещать новые ответы.

Nyima

Guest
ЕСЛИ КОМУ ИНТЕРЕСНО ТО ЕСТЬ РЕШЕНИЕ РАЗ И НАВСЕГДА БЕЗ "SET NAMES" ПОД ВИНДУ!!!

Автор оригинала: alldates
А не нашлось ли какого-нибудь решения, чтбы не добавлять в кучу скриптов SET NAMES 'cp1251';?
Меня интересует вариант под Windows.
Может что-то можно сделать на самом сервере?
Есть решение! На абсолютную точность своего понимания не претендую поскольку сел за МySQL пару дней назад чтоб срочно написать диплом :), но результат гарантирую на 100%.
Итак, после того как я обновивил свой PHP с версии 5.02 до версии 5.03 на моем локальном веб-сервере (апач 2.0.53) и MySQL 4.1.9 перестал должным образом работать PHP-NUKE 7.6, а именно - русские символы в названиях разделов форумов и именах юзеров стали отобоажаться вопросами, причем при использовании типа mysql4 в настройке нюка форум вообще не грузился и писал invalid mix collation, апгрейт на MySQL 4.1.10 застивил его грузится, но проблем с вопросами вместо кирилицы не исправил. Я пару раз почередовал PHP 5.02 с PHP 5.03 и понял что проблема именно в нем, причем в PHP 5.03 используется только одна либа - libmysql.dll - и для модуля php_mysql.dll и для модуля php_mysqli.dll - и имеет клиента версии 4.1.7 (теперь понятно почему у тех у кого был PHP 5.0.2 или PHP 5.0.1 были проблемы только с модулем php_mysqli.dll у которого версия клиета 4.1.7 и либа libmysqli, и не было проблем с модулем php_mysql.dll у которого версия клиента 3.23(22).x и либа libmysql, а вот у тех у кого PHP 5.0.3 проблемы и с тем и с тем модулем - а либа то у них ОДНА - и проблема в ней). Попав на этот форум и почитав много всего я применил для своего скрипта SET NAMES cp1251 и он помог - выдрал мне из таблицы nuke_authors имя "Нехристь", однако я понял из ваших постов что это не совсем круто, и так я сам все равно PHP-nuke не исравлю, а писать с такими задрочками диплом вообще никуда не идет. И я пошел по первой ссылке http://dev.mysql.com/doc/mysql/en/Charset-connection.html и вот что я понял:
character_set_server - кодировка всего сервера (любая база по умолчанию будет создаваться с этой кодировкой) - тут все понятно;
character_set_database - кодировка отделно взятой базы данных (например NUKE), любая таблица в этой базе будет по умолчанию создаваться с этой кодировкой, тут тоже все понятно;
character_set_client - кодировка в которой идет запрос от клиента к серверу - тут надо быть аккуратнее и понимать, что если мы запустим mysql.exe -u root -p password то кодировка символов самой командной строки (окна "доса") -сp866, а кодировка клиента(кодировка в которой идет запрос от клиента к серверу) по умолчанию latin1!!! и если мы ее не изменим (set character_set_client = cp866) то запрос вида: select * from nuke_authors where name = 'Нехристь' - возвратит ноль строк вместо одной в которой также будет и слово 'Нехристь'(нормальными символами - если character_set_results выставить в кодировку опять же нашего окна доса - сp866) - это произойдет потому (возврат нуля строк) что наши введенные символы с окна доса в кодировке сp866 будет переданы серверу как символы в другой! кодировке скажем сp1251 или utf8 или ucs2 или koi8u - и как бы сервер на перекодировал их (символы) там на приеме в другую кодировку (а в какую указывает переменная character_set_connection) все равно она не будет после перевода иметь соответствия нашим символам и в таблице такому запросу (а именно слову 'Нехристь' перекОВЕРКАНОМУ в результате неправильного указания кодировки клиенту 'set character_set_client = НЕ cp866' для отправки запроса серверу) не найдется соответствия и в ответе будет ноль строк;
character_set_results - кодировка в которой отправляются ответы от сервера к клиенту, здесь надо выставить кодировку в которой может отображать символы наш клиент (для нашего окна доса это cp866) и если эта переменная будет иметь другой параметр, например utf8 или сp1251 то вместо слова 'Нехристь' будут другие значки, но не вопросы;
character_set_connection - кодировка в которую должен перевести сервер символы из возможно другой (известной ему по переменной character_set_client) кодировки пришедшей от клиента, перед тем как ее (команду или запрос) обработать и отправить результат обратно клиенту. Тут впринципе даже если сервер переведет сначало запрос немного в другую (utf8 или ucs2 или сp866, но не latin1 и тому подобные в которых соответствующих символов нет) кодировку отличную от кодировки (например сp1251) используемой в таблице - запрос пройдет успешно и возвратит искомые записи (Нехристь) - видимо, если набор символов не теряется при первом переводе в кодировку заданую в character_set_connection, то сервер использует кодировки таблиц к которым обращается и умно сам перекодирует в них символы как-бы на лету и возвращает нам в кодировке character_set_results, а параметр задается для удобства чтоб лишний раз сервер не тратил время на перевод запроса в кодировку таблицы или таблиц (если они все имеют одинаковую кодировку то это выгодно и переводить нужно будет как раз только один раз и то если от клиента они идут в другой - как у нас в сp866 - кодировке :)). Во всяком случае мой запрос
select * from nuke_authors where name = 'Нехристь' завершался с возвратом строки при любой из кодировок utf8 ucs2 сp866 ну и конечно же сp1251 назначенных переменной character_set_connection , но при условии что character_set_client = cp866 и естественно слово 'Нехристь' не отображалось в ответе чудо значками только при character_set_results = сp866 (все так и должно быть ведь у нас окно доса). Эти все наблюдения я проверял не только в досе но и в совершенно других условиях - ZEND Studio 4 и в PHPEd и в MySQL Query Browser и в EMS MySQL.
Из всего понятого мной (дочитать ту ссылку полностью так и не успел) пришел к выводу что надо заставить нашего клиента PHP - и конектится в нужной нам кодировке чтобы там на сервере ждали наши русские символы; и указать имя кодировки серверу для нашего соединения - чтоб он знал во что переводить или не переводить наши символы; и на последок заставить нашего клиента отображать результаты в той кодировке в которой они пришли. Почитав на форумах про то как тут собирали под линукс библиотеки с пшп путем указания параметров при компиляции, пришел к выводу что править dll - ку Hiew'ом, от которой столько проблем, для изменения в ней указания на кодировку, как это описано в соседнем форуме вовсе не безнадежно и попробовать можно:
Итак - запустил Hiew602, открыл libmysql.dll; нашел latin1 - заменил на сp1251; нашел latin1_bin - заменил на cp1251_bin; нашел сразу же рядом latin1_german2_ci - заменил на cp1251_general_ci, нашел рядом latin1_swedish_ci - заменил опять же на тот самый cp1251_general_ci (если тут вместо latin1_swedish_ci поставить cp1251_general_cs то скрипт будет выдавать на mysqli_character_set_name(con_id) ответ cp1251_general_cs, лучше поэтому ..._ci). количество символов у обоих кодировок одинаково - latin1_swedish_ci = cp1251_general_ci =17 символов. Сохраняем и смотрим - уже не плохо - запускается апачь с пшп, mysqli_character_set_name(con_id) выдает cp1251_general_ci, но русские символы выглядет вопросами, не закарлючками а именно вопросами!, а это пожоже значит что наш модуль для MySQL в PHP-хе не то что подбирает им какуюто другую не правильную кодировку и выводит в ней, а просто не находит ей вообще никакого соответствия, как будто о ней никогда и не слышал и не знал. Странно ведь libmySQL.dll которая лежит в каталоге MySQL точно такая же как она там знает о кодировках? а там во всяком случае в папке \MySQL\MySQL Server 4.1\share\charsets\ лежат себе какието xml файлы которые и описуют все кодировки! (напоминаю библиотека в папке bin каталога MySQL такаяже как и в папке PHP - не знаю может у меня она случайно както попала в папку bin и там ее быть не должно)Тут много говорили о том как PHP указать путь к некому файлу конфигурации MySQL'я чтоб PHP смог свою либу запустить с такими же параметрами как и МySQL запускает свою и понимает все кодировки, так вот этого делать не надо - надо просто указать либе где лежат кодировки или узнать где она их ищет!!! по умолчанию ( потому что она их просто не видит) и это записано в самой либе libmysql.dll (хотя есть парадокс - либа MySQL ищет их тамже по умолчанию где и либа лежащая в папке PHP, но либа или сервак MySQL все находит а PHP нет). Итак я открыл libmysql.dll лежaщей в папке PHP и нашел там строку:
/ charsets/ C:/mysql/ share Index.xml ucs2 .xml ¬c¤
немного не так отобразилась (на месте пробелов твердые знаки) но так даже понятней - вот тут то я и понял что это то место где либа ищет свои кодировки!!! ведь это основной файл (index.xml) для определения кодировок. Менять я тут ничего не стал, мои кодировки и файл index.xml лежат в папке D:\Program Files\MySQL\MySQL Server 4.1\share\charsets\
в строке котрую я нашел в либе небыло если смотреть слево направо от диска С:/ части пути \charsets\ а было сразу share - может надо както по частям воспринимать этот путь - адресация какая-то как старший байт, короче я решил на всякий случай скопировать содержимое папки D:\Program Files\MySQL\MySQL Server 4.1\share\charsets\ и в папку c:\mysql\share\ (что как оказалось не пригодилось) и в паку
c:\mysql\share\charsets\ (вот куда надо копировать кодировки!!! и PHP оживет навеки). Скопировал, перезапустил апач, закоментировал в своем скрипте set names сp1251 - оно свое отжило :) иииии О ЧУДО - Нехристь буковка в буковку, захожу на страницу php-nuke в форумы и все темы и все фамилии и все что в базе на русском то и тут тоже на родной кирилице сp1251.....как в старые добрые времена (2 дня назад :)).
Итого: останавливаем Апач, открываем HIEW'ом файл libmysql.dll - меняем четыре строчки:
нашел latin1 - заменил на сp1251
нашел latin1_bin - заменил на cp1251_bin
нашел latin1_german2_ci - заменил на cp1251_general_ci
нашел latin1_swedish_ci - заменил на cp1251_general_ci
далее копируем содержимое папки ..\MySQL\MySQL Server 4.1\share\charsets\ в папку c:\mysql\share\charsets\ и запускаем Апач. Вот и все.
А все что было выше этих 9 строчек вступление в доме который построил Джек.
 

alex A. Kh.

Guest
вот, что написано в мануале:

With the mysql client, it is not necessary to execute SET NAMES every time you start up if you want to use a character set different from the default. You can add the --default-character-set option setting to your mysql statement line, or in your option file. For example, the following option file setting changes the three character set variables set to koi8r each time you run mysql:

[mysql]
default-character-set=koi8r
 

NonStop

Guest
Nyima - молодец, однако mysql.com рекомендует(!!!) использование charsets
при правильном использовании все будет работать

у меня тоже были проблемы с кодировкой, т.к. работу скриптов проверял в ДОС-окне, но после выставления
-- скрипт написан в UltraEdit, поэтому входящая кодировка виндовая
set character_set_client='cp1251'
set character_set_conneccion='cp1251'
результат выходит на консоль, поэтому кодировка возврата досовская
set character_set_results='cp866'

все буквы нормально отображаются, проблем с сортировкой и upper/lower тоже не наблюдается

главная проблема в том, что php под винду по-умолчанию коннектится с параметрами
character_set_client='latin1'
character_set_connection='latin1'
character_set_results='latin1'

чтобы поменять это php надо перебрать, жаль, что нельзя в php.ini задать (я, по крайней мере, не нашел как)
очень подробно написал Nyima, на англиском
http://dev.mysql.com/doc/mysql/en/Charset-connection.html
советую читать не спеша, написано подробно
 

slach

Новичок
zorgi ;) причем тут php.ini и дефолтовый чарсет который выдается в HTTP клиента в заголовке Content-Type ?
 

zorgi

Новичок
slach

Ты попробуй, потом сам себя спрашивай,
а я задаюсь тем же вопросом. )))
 

Max_kmv

Новичок
Автор оригинала: zorgi
Пропиши в php.ini

default_charset = "cp1251"
Лично у меня это никакого эффекта не возымело на вышеописанную проблему. Да и как замечано выше теоретически не должно. Поскольку знаки вопросов появляются именно при получении PHP данных из MySQL. (MySQL 4.1.11, PHP 5.0.4, W2000)

Народ, может кто-нибудь объяснить почему вообще такая проблема имеет место быть :) ? Ведь раньше такой ерунды не наблюдалось, и пофиг в какой кодировке мускл слал результат пхп. Так, для лучшего понимания их "общения". :)
 

slach

Новичок
вопросики идут когда из одного charset (того в котором работает сервер) перекодируется в другой charset(клиентский) , но соответсвия символам нет...
такое часто бывает когда русские символы из UTF8 перекодируются в latin1 (под win32 это дефолтовый чарсет у libmysql.dll)
 

DIS

Guest
может дело в пхп?

вобщем всё как-то непонятно.

стоял PHP 4.3.6 + MySQL 4.1.1 на Linux
всё чудненько работало.
но! стоило пересобрать Apache_1.3.33 с PHP 4.3.11,
так всё, "привет". вся кириллица, что вывалывается из базы превратилась в вопросики..

SET NAMES cp1251 конечно помогает, но ведь с PHP 4.3.6 всё нормально было!

Почему?
Кто знает ответ на этот вопрос?
 

slach

Новичок
2DIS
известно почему, клиент mysql'евый не собран с правильным чарсетом

пересобери MYSQL Клиента с default-charset правильным и все должно заработать

2zorgi... и все таки, вопросики которые получаются из MySQL и default_charset из php.ini не имеют ничего общего...
 

DIS

Guest
Автор оригинала: slach
2DIS
известно почему, клиент mysql'евый не собран с правильным чарсетом

пересобери MYSQL Клиента с default-charset правильным и все должно заработать

2zorgi... и все таки, вопросики которые получаются из MySQL и default_charset из php.ini не имеют ничего общего...
уже...
причём всё ещё проще..
собрал с использованием php-шной либы,
т.е. '--with-mysql' и всё заработало.
 

confguru

ExAdmin
Команда форума
slach

Наступил на теже грабли.. Причем mySQL 4.1.11 - везде указал виндовую кодировку.
Помогает только в SET NAMES cp1251
в классе mysql :)

-~{}~ 28.04.05 10:45:

Ктати выдает
$charset = mysql_client_encoding($this->Link_ID);
echo $charset;
latin1_swedish_ci

-~{}~ 28.04.05 10:57:

Все пофиксил..!
# The MySQL server
[mysqld]
init-connect="SET NAMES cp1251"
 

Diver

Guest
написал как сказал Nyima (пропатчил libmysql.dll ...)
теперь phpmyadmin ругается:

Ошибка
Ответ MySQL:
#2019 - Can't initialize character set ��51 (path: C:\mysql\\share\charsets\)
однако скрипты с добавлением в бд работают (но опять таки ??? если не использовать предварительный запрос на SET CHARSET cp1251)
конфа: apache 2.0.53, php 5.0.4, mysql 4.1.11-nt, win2003server eng enterprise, phpMyAdmin 2.6.1-pl3
 

DIS

Guest
Товарищи:)

прописывайте в my.cnf все коллатионы и чарсеты cp1251.
ставьте php 4.3.11, используя пхп-шную либу (--with-mysql)
и никаких проблем не будет.
 

Diver

Guest
вот my.ini
--------
[client]
port=3306
character_set_client=cp1251
character_set_connection=cp1251
collation_connection=cp1251
character_set_client=cp1251
character_set_connection=cp1251
character_set_results=cp1251
collation_database=cp1251
character_set_database=cp1251
collation_server=cp1251
[mysqld]

port=3306
basedir="E:/Program Files/MySQL/MySQL Server 4.1/"
datadir="E:/Program Files/MySQL/MySQL Server 4.1/Data/"

default-character-set=cp1251
init-connect="SET CHARSET cp1251"
init-connect="SET NAME cp1251"
character_set_server=cp1251
----------------
остальное не тронуто. не помогает
 

confguru

ExAdmin
Команда форума
DIS

[mysqld]
init-connect="SET NAMES cp1251"

И не надо ничего патчить... :)
Я надеюсь вы продакшен сервер не на виндах держите :)
 

DIS

Guest
я на виндах ничего не держу :)

а на линюксе всё работает без всяких SET NAMES
 

Diver

Guest
блин. все равно не работает. даже патчинная, даже с init-connect="SET NAMES cp1251" и прочей лобудой. на виндах
 

confguru

ExAdmin
Команда форума
Еще заметил ньюанс при переносе баз со страрых версий
Mysql нужно указывать

mysql --default-character-set=cp1251 -u db_user -p my_db < my_db.sql

А то русский превращается в latin1 ^-)
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху