PHP + SQL Server - Как установить кодировку для подключения?

Я пытаюсь сохранить некоторые данные в базе данных SQL Server через php.

Проблема в том, что специальные символы не конвертируются должным образом. Кодировка моего приложения — iso-8859-1, а кодировка, используемая сервером, — windows-1252.

Преобразование данных вручную перед вставкой не помогает, похоже, происходит какое-то преобразование.

Запуск SQL-запроса «set char_convert off» также не помогает.

Кто-нибудь знает, как я могу заставить это работать?

EDIT: я пробовал ini_set('mssql.charset', 'windows-1252'); тоже, но и с этим результата нет.


person Maurice    schedule 24.08.2009    source источник
comment
mssql.charset доступен только с FreeTDS. Отображается ли этот параметр конфигурации в phpinfo() на вашем сервере?   -  person VolkerK    schedule 24.08.2009
comment
Да, это проявляется. Phpinfo также заявляет, что версия библиотеки MSSQL — FreeTDS. локальное значение: главное значение windows-1252: нет значения   -  person Maurice    schedule 24.08.2009


Ответы (13)


Кодировка клиента необходима, но недостаточна:

ini_set('mssql.charset', 'UTF-8');

Я два дня искал, как вставить данные UTF-8 (из веб-форм) в MSSQL 2008 через PHP. Я везде читал, что вы не можете, вам нужно сначала преобразовать в UCS2 (как рекомендует решение cypher). В Windows SQLSRV считается хорошим решением, которое я не смог попробовать, так как я разрабатываю для Mac OSX.

Однако в руководстве по FreeTDS (то, что использует PHP mssql в OSX) сказано добавить букву «N» перед открывающей цитатой:

mssql_query("INSERT INTO table (nvarcharField) VALUES (N'űáúőűá球最大的采购批发平台')", +xon);

Согласно этому обсуждению, символ N указывает серверу преобразовать в Unicode. https://softwareengineering.stackexchange.com/questions/155859/why-do-we-need-to-put-n-before-strings-in-microsoft-sql-server

person Mano Kovacs    schedule 24.08.2012

У меня была такая же проблема, и ini_set('mssql.charset', 'utf-8') у меня не работало. Однако это работало в верхнем регистре:

ini_set('mssql.charset', 'UTF-8');
person Jaime Neto    schedule 06.03.2012

Предлагаю обратить внимание на следующие моменты:

  1. Убедитесь, что столбцы, в которых вы храните информацию, являются nchar или nvarchar, так как char и nvarchar не поддерживают UCS-2 (SQLServer не сохраняет в формате UTF-8 кстати)
  2. Если вы подключаетесь с помощью библиотеки/расширения mssql для PHP, запустите: ini_set('mssql.charset', 'utf-8'); так как нет функции с аргументом charset (connect, query и т. д.)
  3. Убедитесь, что кодировка вашего браузера также установлена ​​на UTF-8.
person Matthew Setter    schedule 13.02.2012
comment
Также, если вы используете Zend_Db, то не забудьте про параметр charset при инициализации соединения:...params.charset = utf8 - person Matthew Setter; 13.02.2012

Если ini_set('mssql.charset', 'UTF-8'); не помогает И у вас нет root-доступа для изменения общесистемного файла freetds.conf, вот что вы можете сделать:

1. Настройте /your/local/freetds.conf файл:

[sqlservername]
    host=192.168.0.56
    port=1433
    tds version=7.0
    client charset=UTF-8

2. Убедитесь, что DSN для подключения использует имя сервера, а не IP-адрес:

'dsn' => 'dblib:host=sqlservername;dbname=yourdb

3. Заставьте FreeTDS использовать ваш локальный файл freetds.conf в качестве непривилегированного пользователя из скрипта php через переменные env:

putenv('FREETDSCONF=/your/local/freetds.conf');
person Attila Fulop    schedule 05.02.2015
comment
Потратил на это 3 часа. Спасибо! - person Yarimadam; 06.09.2018
comment
Спасибо, я потратил 3 ДНЯ на этот вопрос! о/ - person delphirules; 09.10.2018
comment
это должно быть помечено как принятый ответ - person Marek Lisiecki; 08.07.2021

Если вы используете протокол TDS версии 7 или выше, ВСЕ коммуникации по проводу преобразуются в UCS2. Сервер преобразует UCS2 во все, что установлено для сортировки таблицы или столбца, если только столбец не является nvarchar или ntext. Вы можете хранить UTF-8 в обычном формате varchar или тексте, вам просто нужно использовать версию протокола TDS ниже 7, например 6.0 или 4.2. Единственным недостатком этого метода является то, что вы не можете запрашивать какие-либо таблицы nvarchar, ntext или sys.* (я думаю, вы также не можете выполнять CAST()) - поскольку сервер отказывается отправлять что-либо, что может быть преобразовано в UTF-8 для любого клиента, использующего версию протокола ниже 7.

Невозможно избежать преобразования наборов символов при использовании протокола TDS версии 7 или выше (примерно эквивалентно MSSQL 2005 или новее).

person chugadie    schedule 20.08.2013
comment
В системе Linux вы можете установить эту версию протокола TDS в freetds.conf, указав следующие параметры в группе параметров [global] -- tds version = 8.0 client charset = UTF-8 См.: gist.github.com/johnkary/6643856 - person John Kary; 21.09.2013

Мне повезло в аналогичной ситуации (используя соединение PDO ODBD), используя следующий код для преобразования кодировки перед печатью вывода:

$data = mb_convert_encoding($data, 'ISO-8859-1', 'windows-1252');

Мне пришлось вручную установить исходную кодировку, потому что mb_detect_encoding() ошибочно сообщал об этом как «ISO-8859-1».

Мои данные также хранились в базе данных другим приложением, поэтому я мог оказаться в уникальной ситуации, хотя я надеюсь, что это поможет!

person Jacob Hume    schedule 15.03.2011

Мне помогло редактирование этого файла:
/etc/freetds/freetds.conf
...и изменение/установка параметра «tds version» на «7.0». Отредактируйте файл freetds.conf и попробуйте изменить этот параметр для конфигурации вашего сервера (или глобальной).

Это будет работать даже без перезапуска apache.

person bohdanbobrowski    schedule 03.11.2014

В моем случае это сработало после того, как я добавил параметры «CharacterSet» в параметр подключения sqlsrv_connect().

$connectionInfo = array( 
        "Database"=>$DBNAME,
        "ConnectionPooling"=>0,
        "CharacterSet"=>"UTF-8"
);
$LAST_CONNECTION = sqlsrv_connect($DBSERVER, $connectionInfo);

См. документацию здесь: https://docs.microsoft.com/en-us/sql/connect/php/connection-options?view=sql-server-2017

person Donovan P    schedule 17.12.2018
comment
Это работает в моем случае, SQL Server 2014 и PHP 7.3, работающие на Windows Server. - person eduardo a; 22.03.2019

Я не заметил, чтобы кто-то упомянул другой способ преобразования результатов из базы данных MSSQL. Старая добрая функция iconv():

iconv (string $in_charset, string $out_charset, string $str): string;

В моем случае все остальное не дало значимой конверсии, кроме этой при получении результатов. Разумеется, это делается внутри цикла разбора результатов запроса — от CP1251 до UTF-8:

foreach ($records as $row=>$col) {
    $array[$row]['StatusName'] = iconv ('CP1251', 'UTF-8' , $records[$row]['StatusName']);
}

Некрасиво, но работает.

person Bud Damyanov    schedule 01.03.2019

Разве вы не можете просто преобразовать свои таблицы в кодировку вашего приложения? Или использовать utf-8 в обоих?

Однако я не знаю, поддерживает ли MSSQL кодировку на уровне таблицы.

Кроме того, попробуйте строковые функции MB (многобайтовые), если вышеперечисленное не работает.

person Sandro Gržičić    schedule 24.08.2009
comment
К сожалению, я не могу. Ибо это не моя база данных и не мой фреймворк. Преобразование специальных символов в объекты также не является вариантом, поскольку к этой базе данных также подключено некоторое программное обеспечение, не связанное с Интернетом. Я привык конвертировать с помощью iconv, но попробую MB. - person Maurice; 24.08.2009
comment
Тот же результат с мб. Кажется, при отправке данных в БД выполняется какое-то автоматическое преобразование. - person Maurice; 25.08.2009

Вы должны установить кодировку с помощью ini_set('mssql.charset', 'windows-1252') перед подключением. Если вы используете его после mssql_connect, это не будет иметь никакого эффекта.

person achos    schedule 31.07.2015

Просто добавление ini_set('mssql.charset', 'UTF-8'); не помогло мне в моем случае. Мне пришлось указать набор символов UTF-8 в столбце:

$age = 30;  
$name = utf8_encode("Joe");    

$select = sqlsrv_query($conn, "SELECT * FROM Users WHERE Age = ? AND Name = ?",
    array(array($age), array($name, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('UTF-8')));
person Maja S.    schedule 24.03.2017

Вы можете использовать функцию mysql_set_charset: http://it2.php.net/manual/en/function.mysql-set-charset.php

person mck89    schedule 24.08.2009
comment
mysql_set_charset предназначен для MySQL, но в вопросе дважды упоминается mssql (сервер sql). - person VolkerK; 24.08.2009