我花了几天时间试图在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字符串。
希望这能有所帮助。