您好,我正在尝试将名称存储到 Oracle 数据库中并使用 PHP 和 oci8 取回它们。
但是,如果我插入é
直接进入 Oracle 数据库并使用 oci8 将其取回 我刚刚收到e
我是否必须对所有特殊字符(包括é
)转换为 html 实体(即:é
)在插入数据库之前...或者我错过了什么?
Thx
更新:3 月 1 日 18:40
发现这个函数:http://www.php.net/manual/en/function.utf8-decode.php#85034 http://www.php.net/manual/en/function.utf8-decode.php#85034
function charset_decode_utf_8($string) {
if(@!ereg("[\200-\237]",$string) && @!ereg("[\241-\377]",$string)) {
return $string;
}
$string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e","'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'",$string);
$string = preg_replace("/([\300-\337])([\200-\277])/e","'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'",$string);
return $string;
}
似乎有效,但不确定它是否是最佳解决方案
更新:3 月 8 日 15:45
Oracle 的字符集是 ISO-8859-1。
在 PHP 中我添加了:
putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1");
强制 oci8 连接使用该字符集。
检索é
现在可以使用 PHP 中的 oci8 了! (为了varchars
, 但不是CLOBs
不得不做utf8_encode
提取它)
然后我尝试将数据从 PHP 保存到 Oracle...但它不起作用...从 PHP 到 Oracle 的某个地方é
成为一个?
更新:3 月 9 日 14:47
于是越来越近。
添加 NLS_LANG 变量后,直接进行 oci8 插入é
works.
问题实际上出在PHP方面。
通过使用 ExtJs 框架,在提交表单时,它使用以下方式对其进行编码encodeURIComponent
.
So é
发送为%C3%A9
然后重新编码为é
.
然而它现在的长度是2 (strlen($my_sent_value) = 2)
而不是 1。
如果在 PHP 中我尝试: $my_sent_value ==é
= FALSE
我认为如果我能够将 PHP 中的所有这些字符重新编码回字节大小 1 的长度,然后将它们插入到 Oracle 中,它应该可以工作。
但仍然没有运气
更新:3 月 10 日 11:05
我一直认为我是如此接近(却又如此遥远)。
putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9");
工作非常零星。
我创建了一个小的 php 脚本来测试:
header('Content-Type: text/plain; charset=ISO-8859-1');
putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9");
$conn= oci_connect("user", "pass", "DB");
$stmt = oci_parse($conn, "UPDATE temp_tb SET string_field = '|é|'");
oci_execute($stmt, OCI_COMMIT_ON_SUCCESS);
运行一次并直接登录 Oracle 数据库后,我看到 STRING FIELD 设置为|¿|
。显然这不是我从之前的经历中所期望的。
但是,如果我快速刷新该 PHP 页面两次......它就有效了!
在Oracle中我正确地看到了|é|
.
看起来环境变量可能没有在第一次执行脚本时正确设置或发送,但可用于第二次执行。
我的下一个实验是将变量导出到 PHP 的环境中,但是,我需要为此重置 Apache...所以我们将看看会发生什么,希望它能起作用。