Как хранить и извлекать расширенные символы ASCII в MSSQL
Я был удивлен, что не смог найти прямой ответ на этот вопрос путем поиска.
у меня есть веб-приложение на PHP, которое принимает пользовательский ввод. Из-за характера приложения пользователи могут часто использовать расширенные символы ASCII (a.к. a. "ALT codes").
моя конкретная проблема на данный момент с кодом ALT 26, который является стрелкой вправо (→). Это будет сопровождаться другим текстом, который будет храниться в том же поле (например, 'this→that').
мой тип столбца-NVARCHAR.
вот что я пробовал:
- Я пробовал не делать никаких преобразований и просто вставлять значение как обычно, но значение сохраняется как - thisâ??that.
- Я попытался преобразовать значение в UCS-2 в PHP, используя - iconv('UTF-8', 'UCS-2', $value), но я получаю сообщение об ошибке, говорящее- Unclosed quotation mark after the character string 't'.. Запрос заканчивается следующим образом:- UPDATE myTable SET myColumn = 'this�!that'.
- Я пробовал сделать приведенное выше преобразование и затем добавление N перед указанным значением, но я получаю то же сообщение об ошибке. Запрос выглядит следующим образом: - UPDATE myTable SET myColumn = N'this�!that'.
- Я попытался удалить преобразование UCS-2 и просто добавить N перед указанным значением, и запрос снова работает, но значение сохраняется как - thisâ that.
- Я пробовал использовать - utf8_decode($value)в PHP, но тогда стрелка просто заменяется вопросительным знаком.
так может кто-нибудь ответить (казалось бы, простой) вопрос о том, как я могу сохранить это значение в своей базе данных, а затем получить его, как он был первоначально набран?
я использую PHP 5.5 и MSSQL 2012. Если какой-либо вопрос о версии драйвера/ОС вступает в игру, это сервер Linux, подключающийся через FreeTDS. Изменить это невозможно.
4 ответов
вы можете попробовать base64 кодирование ввода, это довольно тривиально обрабатывать с помощью PHP base64_encode() и base64_decode() и он должен обрабатывать то, что ваши пользователи бросают на него. 
(edit: вы, по-видимому, также можете сделать кодировка base64 на стороне SQL Server. Это не похоже на то, что он должен нести ответственность за ИМХО, но это вариант.)
вроде freetds.conf - это неправильно. Вам нужна версия протокола TDS >= 7.0 для поддержки unicode. Посмотреть подробнее.
редактировать freetds.conf:
[global]
# TDS protocol version
tds version = 7.4
client charset = UTF-8
также убедитесь, что PHP настроен правильно:
ini_set('mssql.charset', 'UTF-8');
похоже, у вас есть this→!that, ASCII аналог UTF-8 закодирован this→!that.
положить вещи сразу после предложений, сделанных здесь, не решит всю проблему волшебным образом. Особенно если у вас уже есть данные в таблице(с) что скорее всего.
нужно, чтобы сделать новый старт чтобы найти правильный путь.
- создайте новую таблицу с хотя бы одним столбцом nvarchar, скажем TestTable(Column1)
- создать пустой UTF-8 закодировано -требуется для жестко закодированных входов во время тестов - PHP файл. test.php
- на freetds.confобязательно добавить параметрclient charset = UTF-8под[global]или . Это набор символов, используемый для связи между FreeTDS и SQL Server.
принятый ответ, кажется, делает работу; да, вы можете закодировать его в base64 и затем декодировать его снова, но затем все приложения, которые используют эту удаленную базу данных, должны изменить и поддерживать поля, чтобы быть base64 закодирован. Я думаю, что если есть удаленная база данных MS SQL Server, может быть другое приложение (или приложения), которое может ее использовать, поэтому приложение также должно быть изменено для поддержки как plain, так и base64 кодировка. И Вам также придется справиться с обоими обычный текст и base64 преобразованный текст.
Я немного поискал, и я нашел, как отправить текст UNICODE на MS SQL Server с помощью команд MS SQL и PHP для преобразования байтов UNICODE в шестнадцатеричные числа.
если вы идете в документации PHP для mssql_fetch_array (http://php.net/manual/ru/function.mssql-fetch-array.php#80076), вы увидите в комментариях довольно хорошее решение, которое преобразует текст в Unicode hex значений и передает эти данные шестигранные напрямую для MS SQL Server так:
преобразование текста Юникода в шестнадцатеричные данные
// sending data to database 
$utf8 = 'Δοκιμή με unicode → Test with Unicode';  // some Greek text for example
$ucs2 = iconv('UTF-8', 'UCS-2LE', $utf8); 
// converting UCS-2 string into "binary" hexadecimal form 
$arr = unpack('H*hex', $ucs2); 
$hex = "0x{$arr['hex']}"; 
// IMPORTANT! 
// please note that value must be passed without apostrophes 
// it should be "... values(0x0123456789ABCEF) ...", not "... values('0x0123456789ABCEF') ..." 
mssql_query("INSERT INTO mytable (myfield) VALUES ({$hex})", $link);
теперь весь текст фактически хранится в NVARCHAR поле базы данных правильно как UNICODE, и это все, что вам нужно сделать, чтобы отправить и сохранить его как обычный текст, а не закодированный.
чтобы получить этот текст, вам нужно попросить MS SQL Server отправить обратно кодированный текст UNICODE следующим образом:
получение текста Unicode из MS SQL Сервер
// retrieving data from database 
// IMPORTANT! 
// please note that "varbinary" expects number of bytes 
// in this example it must be 200 (bytes), while size of field is 100 (UCS-2 chars) 
// myfield is of 50 length, so I set VARBINARY to 100
$result = mssql_query("SELECT CONVERT(VARBINARY(100), myfield) AS myfield FROM mytable", $link); 
while (($row = mssql_fetch_array($result, MSSQL_BOTH))) 
{ 
    // we get data in UCS-2 
    // I use UTF-8 in my project, so I encode it back 
    echo '1. '.iconv('UCS-2LE', 'UTF-8', $row['myfield'])).PHP_EOL; 
    // or you can even use mb_convert_encoding to convert from UCS-2LE to UTF-8
    echo '2. '.mb_convert_encoding($row['myfield'], 'UTF-8', 'UCS-2LE').PHP_EOL;
} 
таблица MS SQL с данными UNICODE после вставки
результат вывода с помощью страницы PHP для отображения значений
Я не уверен, что вы можете добраться до моей тестовой страницы здесь, но вы можете попробовать увидеть живые результаты: http://dbg.deve.wiznet.gr/php56/mssql/test1.php
 
            
