Кодирование SQL Latin1 общий CP1 CI как в UTF-8
я генерирую XML-файл с PHP, используя DomDocument, и мне нужно обрабатывать азиатские символы. Я извлекаю данные с сервера MSSQL2008, используя драйвер pdo_mssql, и применяю utf8_encode() к значениям атрибутов XML. Все работает нормально, пока нет специальных символов.
сервер MS SQL Server 2008 SP3
база данных, таблица и параметры сортировки столбцов-все SQL_Latin1_General_CP1_CI_AS
Я использую PHP 5.2.17
вот мой объект PDO:
$pdo = new PDO("mssql:host=MyServer,1433;dbname=MyDatabase", user123, password123);
мой запрос является основным выбором.
Я знаю, что хранение специальных символов в Столбцах sql_latin1_general_cp1_ci_as не здорово, но в идеале было бы неплохо заставить его работать, не изменяя его, потому что другие программы, отличные от PHP, уже используют этот столбец, и он отлично работает. В SQL Server Management Studio я правильно вижу азиатские символы.
учитывая все детали выше, как я должен обрабатывать Дейта?
6 ответов
Я нашел, как его решить, поэтому, надеюсь, это будет полезно кому-то.
во-первых, SQL_Latin1_General_CP1_CI_AS-странная смесь CP-1252 и UTF-8. Основные символы-CP-1252, поэтому все, что мне нужно было сделать, это UTF-8, и все работало. Азиатские и другие символы UTF-8 кодируются на 2 байтах, а драйвер php pdo_mssql, похоже, ненавидит символы различной длины, поэтому он, похоже, выполняет приведение к varchar (вместо nvarchar) , а затем все 2 байтовые символы станьте вопросительными знаками ('?').
я исправил его, бросив его в двоичный файл, а затем я перестрою текст с помощью php:
SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) FROM MY_TABLE;
в php:
//Binary to hexadecimal
$hex = bin2hex($bin);
//And then from hex to string
$str = "";
for ($i=0;$i<strlen($hex) -1;$i+=2)
{
$str .= chr(hexdec($hex[$i].$hex[$i+1]));
}
//And then from UCS-2LE/SQL_Latin1_General_CP1_CI_AS (that's the column format in the DB) to UTF-8
$str = iconv('UCS-2LE', 'UTF-8', $str);
Я знаю, что этот пост старый, но единственное, что работа для меня была iconv ("CP850", "UTF-8 / / транслит", $var); У меня были те же проблемы с SQL_Latin1_General_CP1_CI_AI, возможно, он работает и для SQL_Latin1_General_CP1_CI_AS.
можно попробовать так:
header("Content-Type: text/html; charset=utf-8");
$dbhost = "hostname";
$db = "database";
$query = "SELECT *
FROM Estado
ORDER BY Nome";
$conn = new PDO( "sqlsrv:server=$dbhost ; Database = $db", "", "" );
$stmt = $conn->prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED, PDO::SQLSRV_ENCODING_SYSTEM) );
$stmt->execute();
while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) )
{
// CP1252 == code page Latin1
print iconv("CP1252", "ISO-8859-1", "$row[Nome] <br>");
}
по умолчанию PDO
использует PDO::SQLSRV_ENCODING_UTF8
для отправки/получения данных.
если ваш текущий collate LATIN1
, вы пробовали указывающий PDO::SQLSRV_ENCODING_SYSTEM
пусть PDO
знайте, что вы хотите использовать текущую системную кодировку вместо UTF-8
?
вы даже можете использовать PDO::SQLSRV_ENCODING_BINARY
который возвращает данные в двоичной форме (при передаче данных не выполняется кодирование или перевод). Таким образом, вы можете обрабатывать кодировку символов на своей стороне.
больше документации вот:http://ca3.php.net/manual/en/ref.pdo-sqlsrv.php
спасибо @SGr за ответ.
Я нашел лучший способ сделать это:
SELECT CAST(CAST(MY_COLUMN AS VARBINARY(MAX)) AS VARCHAR(MAX)) as MY_COLUMN FROM MY_TABLE;
а также попробуйте с:SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE;
и в PHP вы должны просто преобразовать его в UTF-8:
$string = iconv('UCS-2LE', 'UTF-8', $row['MY_COLUMN']);
для меня ни одно из вышеперечисленных решений не было прямым решением,хотя я использовал части вышеперечисленных решений. Это сработало для меня с вьетнамским алфавитом. Если вы столкнулись с этим сообщением, и ни одна из вышеперечисленных работ для вас, попробуйте:
$req = "SELECT CAST(MY_COLUMN as VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE";
$stmt = $conn->prepare($req);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$str = pack("H*",$row['MY_COLUMN']);
$str = mb_convert_encoding($z, 'HTML-ENTITIES','UCS-2LE');
print_r($str);
}
и небольшой бонус-я должен был json_encode эти данные и был (duh) получать html-код вместо специальных символов. для исправления просто используйте html_entity_decode () в строках перед отправкой с json_encode.