【问题标题】:Encoding SQL_Latin1_General_CP1_CI_AS into UTF-8将 SQL_Latin1_General_CP1_CI_AS 编码为 UTF-8
【发布时间】:2012-04-24 21:05:51
【问题描述】:

我正在使用 DomDocument 使用 PHP 生成一个 XML 文件,并且我需要处理亚洲字符。我正在使用 pdo_mssql 驱动程序从 MSSQL2008 服务器中提取数据,并将 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);

我的查询是一个基本的 SELECT。

我知道将特殊字符存储到 SQL_Latin1_General_CP1_CI_AS 列中并不是很好,但理想情况下最好不更改它就使其工作,因为其他非 PHP 程序已经使用该列并且它工作正常。在 SQL Server Management Studio 中,我可以正确看到亚洲字符。

考虑到以上所有细节,我应该如何处理数据?

【问题讨论】:

  • 你试过utf8_encode() 吗?根据手册:Encodes an ISO-8859-1 string to UTF-8.
  • 当然,这就是我目前正在做的,但亚洲字符显示为“?”。即使我只是运行 SELECT 然后将数据放入文件中(无论是否为 utf8_encode),亚洲字符也会以“?”结尾。在文件中。
  • 令我惊讶的是,您实际上能够在LATIN1 中编码亚洲字符。 LATIN1 仅用于编码欧洲字符...

标签: php xml sql-server-2008 encoding utf-8


【解决方案1】:

不需要疯狂的东西。排序规则SQL_Latin1_General_CP1_CI_AS字符编码为:Windows-1252

这非常适合我:$str = mb_convert_encoding($str, 'UTF-8', 'Windows-1252');

【讨论】:

    【解决方案2】:

    对我来说,以上都不是直接的解决方案——尽管我确实使用了上述解决方案的一部分。这对我使用越南字母表很有用。如果您看到这篇文章并且以上方法都不适合您,请尝试:

        $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 代码而不是特殊字符。在使用 json_encode 发送之前,只需在字符串上使用 html_entity_decode() 即可修复。

    【讨论】:

    • 这是唯一适用于韩语和俄语的解决方案。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      你可以试试:

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

      【讨论】:

      • 这个对我有用!谢谢:print iconv("CP1252", "UTF-8", "$row[Nome] &lt;br&gt;");
      【解决方案5】:

      我知道这篇文章很旧,但唯一对我有用的是 iconv("CP850", "UTF-8//TRANSLIT", $var); 我对 SQL_Latin1_General_CP1_CI_AI 也有同样的问题,也许它也适用于 SQL_Latin1_General_CP1_CI_AS。

      【讨论】:

        【解决方案6】:

        我找到了解决方法,所以希望这对某人有所帮助。

        首先,SQL_Latin1_General_CP1_CI_AS 是 CP-1252 和 UTF-8 的奇怪组合。 基本字符是 CP-1252,所以这就是为什么我所要做的就是 UTF-8 并且一切正常。亚洲和其他 UTF-8 字符在 2 个字节上编码,php pdo_mssql 驱动程序似乎讨厌不同长度的字符,所以它似乎对 varchar(而不是 nvarchar)进行 CAST,然后所有 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);
        

        【讨论】:

        • 但是.. 但是.. 那是精神上的。真的没有更好的办法了吗?,不是mb_convert_encoding
        【解决方案7】:

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

        如果您当前的排序是LATIN1,您是否尝试过指定PDO::SQLSRV_ENCODING_SYSTEM 让PDO 知道您想使用当前系统编码而不是UTF-8?

        您甚至可以使用PDO::SQLSRV_ENCODING_BINARY,它以二进制形式返回数据(传输数据时不进行编码或翻译)。这样,您就可以自己处理字符编码。

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

        【讨论】:

        • PDO::SQLSRV_* 参数在SQL server 2008 上对我不起作用。我收到一些错误,它是未定义的或类似的东西。
        猜你喜欢
        • 2015-11-08
        • 2012-08-16
        • 1970-01-01
        • 2012-06-30
        • 2017-08-23
        • 2015-10-02
        • 2013-06-02
        • 2011-08-09
        • 2011-06-26
        相关资源
        最近更新 更多