Как хранить и извлекать расширенные символы 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