编码SQL_Latin1_General_CP1_CI_AS成UTF-8(Encoding SQL_

2019-06-23 13:43发布

我生成与PHP中使用的DomDocument一个XML文件,我需要处理亚洲字符。 我从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中我可以正确地看到亚洲字符。

考虑到上述所有的细节,我应该如何处理这些数据?

Answer 1:

我发现如何解决它,所以希望这会有所帮助的人。

首先,SQL_Latin1_General_CP1_CI_AS是CP-1252和UTF-8的一个奇怪的混合。 的基本特征是CP-1252,所以这就是为什么我所要做的就是UTF-8和一切工作。 亚洲和其它UTF-8字符被编码于2个字节和PHP pdo_mssql驾驶员似乎讨厌不同长度的字符看起来是这样做CAST到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);


Answer 2:

我知道这个帖子是老了,但只是为我工作的事情是的iconv(“CP850”,“UTF-8 // TRANSLIT”,是$ var); 我有同样的问题与SQL_Latin1_General_CP1_CI_AI,也许它SQL_Latin1_General_CP1_CI_AS工作了。



Answer 3:

你可以试试这样:

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>");
}


Answer 4:

默认情况下, PDO使用PDO::SQLSRV_ENCODING_UTF8用于发送/接收数据。

如果您目前的整理是LATIN1 ,你尝试过specifiying PDO::SQLSRV_ENCODING_SYSTEMPDO知道你想使用当前的系统编码,而不是UTF-8

你甚至可以使用PDO::SQLSRV_ENCODING_BINARY这在二进制形式返回数据(无编码或翻译transfering数据时进行)。 通过这种方式,你可以在你的身边处理字符编码。

这里更多的文档: http://ca3.php.net/manual/en/ref.pdo-sqlsrv.php



Answer 5:

感谢@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']);



Answer 6:

对我来说,以上都不是很直接的解决方案 - 虽然我没有使用上述解决方案的组成部分。 这为我工作与越南字母。 如果你遇到这个帖子并没有为你上面的工作,尝试:

    $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这些数据,并为(杜)获得HTML代码,而不是特殊字符。 修复与json_encode发送之前刚刚使用的字符串html_entity_decode()。



文章来源: Encoding SQL_Latin1_General_CP1_CI_AS into UTF-8