Кодирование 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.