PDO_ODBC 的字符编码问题

Posted

技术标签:

【中文标题】PDO_ODBC 的字符编码问题【英文标题】:Character encoding issue with PDO_ODBC 【发布时间】:2011-03-28 21:14:07 【问题描述】:

当使用 PDO_ODBC 和以下代码从 php 访问 Microsoft SQL 数据库时,我遇到了编码问题。从数据库输出的文本是乱码。

$dsn = "odbc:DRIVER=SQL Server;SERVER=$hostname;DATABASE=$database;charset=UTF-8";
$pdo = new PDO($dsn,$username,$password);
$sql = "SELECT text FROM atable";
$result = $PDO->query($sql);
while($data = $result->fetchObject())
  $values[] = $data->text; 

dpm($values);

(来源:bayimg.com)

这是通过 Drupal 模块完成的。 Drupal 中的所有内容都可以使用 UTF-8。最干净的解决方案是能够以 UTF-8 从数据库中检索数据,或者在输出之前将其转换为 UTF-8。

我试过这些都没有成功

$dsn = "odbc:DRIVER=SQL Server;SERVER=$hostname;DATABASE=$database;client_charset=utf-8" $dsn = "odbc:DRIVER=SQL Server;SERVER=$hostname;DATABASE=$database;charset=utf-8" $pdo->exec('SET NAMES utf8')new PDO(...) 之后 $pdo->exec('SET CHARACTER SET utf8');new PDO(...) 之后

PS:代码目前是在 Windows 上开发的,但它也必须在 GNU/Linux 上运行。

【问题讨论】:

【参考方案1】:

在 Linux 上运行并使用 FreeTDS 驱动程序时,可以使用 freetds.conf 文件中的 client charset 设置来配置客户端的字符集。为了在使用 PDO ODBC 和 unixODBC 时使用 freetds.conf 文件,需要使用 ODBC-combined configuration 配置 ODBC 数据源。使用ODBC-only configuration 配置ODBC 数据源时,不使用文件freetds.conf。有了这个,我就能够从 MS SQL Server 数据库中检索和插入 UTF-8 数据。

作为一名 Linux/Unix 人员,我无法理解/找到如何配置在 Windows 上使用 PDO ODBC 时使用的字符集的方法。我的模糊理解是,在系统级别配置时,可以将 ODBC 数据源配置为使用 de SQL Server 数据库的字符集或转换为客户端计算机字符集。

【讨论】:

如果我使用 ODBC-only 配置并连接 PHP PDO odbc,我无法获取 UTF-8 数据。【参考方案2】:

将字符编码设置为 UTF-8 时,您还需要将查询编码为 UTF-8 并对结果进行解码。该字符集告诉驱动程序您本机使用 UTF8。因此,您需要将 UTF8 转换回 PHP 可以理解的格式(ASCII 或 mbstring)。

$dsn = "odbc:DRIVER=SQL Server;SERVER=$hostname;DATABASE=$database;charset=UTF-8";
$pdo = new PDO($dsn,$username,$password);
$sql = utf8_encode("SELECT text FROM atable");
$result = $PDO->query($sql);
while($data = $result->fetchObject())
  $values[] = utf8_decode($data->text); 
  // possibly also: $values[] = utf8_decode($data[utf8_encode('text')]);

dpm($values);

【讨论】:

好吧,如前所述,这是通过 Drupal 模块完成的。 Drupal 期望所有字符串都是 UTF-8 编码的,它还输出其编码设置为 UTF-8 的页面。一旦将 ODBC 数据源配置为使用 UTF-8(请参阅我的答案),PDO 就会返回使用 dpm() 函数正确输出的 UTF-8 编码数据。对来自 PDO 的数据调用 utf8_decode() 会产生乱码输出,因为字符串将显示在 UTF-8 编码的页面中。【参考方案3】:

您可以在连接字符串中使用 ClientCharset 属性(不带空格)设置所需的字符编码。 就我而言,它是 UTF-8。

$connection_string = "DRIVER=FreeTDS;SERVER=$serverip;Port=1433;DATABASE=$dbname;ClientCharset=UTF-8";

$conn = odbc_connect($connection_string,$username,$pwd);

详情请参考以下页面..

https://www.freetds.org/userguide/dsnless.html

【讨论】:

【参考方案4】:

您可以使用此代码来解决您的问题:

$result = odbc_exec($this->con, $sql);    
$data = fetch2Array($result);

 private function fetch2Array($result)    
    $rows = array();

    while($myRow = odbc_fetch_array( $result )) 
        $rows[] = $this->arrayToUTF($myRow);
    
    return $rows;


private function arrayToUTF($arr)
    foreach ($arr as $key => $value) 
        $arr[$key] = utf8_encode($value);
    
    return $arr;

【讨论】:

关于 PDO 解决方案的问题请求,此答案未使用 PDO。此外,建议的解决方案与 Veggivore 几年前的解决方案是多余的(即使用 utf8_encode() 转换值)。【参考方案5】:

您可以使用此代码来解决您的问题:

第一 发布数据转换

'$word = iconv("UTF-8","Windows-1254",$_POST['search']);'

还有 读取数据转换

while($data = $result->fetchObject())
  $values[] = iconv("Windows-1254", "UTF-8",$data->text));

SQL 字符串

$sql = "SELECT * FROM yourtables WHERE text LIKE '%$word%'";
or
$sql = "SELECT * FROM yourtables";

【讨论】:

以上是关于PDO_ODBC 的字符编码问题的主要内容,如果未能解决你的问题,请参考以下文章

Java Myeclipse里的中文字符编码问题

SpringMVC中的字符编码问题

Python 字符编码问题的处理

字符编码Java字符编码详细解答及问题探讨

字符编码问题

C# XML 字符串编码问题