PHP OCI8 无法从 NCHAR 读取 Unicode 字符 (Oracle 11g)

PHP OCI8 Unable to read Unicode chars from NCHAR (Oracle 11g)

我花了几天时间尝试通过 PHP7 OCI8 从 Oracle 11g 读取 Unicode 字符(简体中文名称)(尝试使用 PDO_OCI 和 ODBC 以及 PHP5 ,同样的问题)在 Linux Ubuntu 服务器 14.04 上。

这是 Oracle 11g 设置:

NLS_LANGUAGE    AMERICAN
NLS_TERRITORY   AMERICA
NLS_CHARACTERSET    WE8MSWIN1252
NLS_SORT    BINARY
NLS_NCHAR_CHARACTERSET  AL16UTF16
NLS_COMP    BINARY
NLS_LENGTH_SEMANTICS    BYTE
NLS_NCHAR_CONV_EXCP FALSE

重要 我试图阅读的 table 列被定义为 NCHAR(40)。 我使用 php-7.0.8 NTS、oci8-2.0.11(来自 PECL)并安装了 Oracle instantclient

这是我正在使用的 php 代码:

<?php
$fp = fopen('output.txt','w');
$conn = oci_connect('MYUSER', 'MYPASSWORD', 'xxx.xxx.xxx.xxxx/DBTEST','AL32UTF8');

$query = "SELECT ABALPH FROM CRPDTA.F0101 WHERE ROWNUM <= 1 ORDER BY NULL";
$stid = oci_parse($conn, $query);
oci_execute($stid, OCI_NO_AUTO_COMMIT);

while ($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
    fwrite($fp, $row['ABALPH']."\n");
}
fclose($fp);
?>

然后我可以看到英文名字,但我将 ¿¿¿¿我认为这与 NCHAR(40) 数据类型有关。

请注意,我已经直接设置了 Oracle 环境变量(通过导出 and/or putenv())。当我使用 sqlplus 命令时,我可以将可读的中文名称导出到我设置的文件中 export NLS_LANG ="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

知道如何解决这个问题吗?我将不胜感激! 此致,塞尔吉奥

我想我在 this blog post 中找到了解决方案。

看了文章的评论,基本上NCHAR字段需要转换成RAW/HEX:

$query = "SELECT UTL_RAW.cast_to_raw(convert(ABALPH,'AL32UTF8')) FROM CRPDTA.F0101 WHERE ROWNUM <= 1 ORDER BY NULL";

如果您在 PHP 中使用 oci8 扩展名,则无需进一步将十六进制转换为 UTF8,因为根据 post,它会由 PHP 自动完成。但是,如果您使用 PDO_OCI,那么您需要先使用 hex2bin() 转换您的十六进制字段,然后再将其用作 UTF8 字符串。

希望这对您有所帮助。

在 PHP OCI8 或 PDO_OCI 中没有对 NCHAR 或 NCLOB 的原生支持。现在很多人都在使用UTF8,所以他们不需要N*支持。