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


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

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

这是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

重要我试图读取的表列被定义为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);
?>

然后我可以看到英文名字,但我会在我的txt文件(UTF8 w/o BOM格式(中找到中文名字。我认为这与NCHAR(40(数据类型有关。

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

你知道如何解决这个问题吗?我将不胜感激!此致,Sergio

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

我想我在这篇博客文章中找到了解决方案。

阅读文章的评论,基本上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,因为根据帖子,这是由PHP自动完成的。但是,如果使用PDO_OCI,则需要先使用hex2bin()转换十六进制字段,然后再将其用作UTF8字符串。

希望这能有所帮助。