您好我正在尝试将名称存储到Oracle数据库中,并使用PHP和oci8将其恢复。
但是,如果我将é
直接插入Oracle数据库并使用oci8获取它,我只会收到e
在插入数据库之前,我是否必须将所有特殊字符(包括é
)编码为html实体(即:é
)...或者我遗漏了什么?
THX
更新:3月1日18:40
找到了这个功能: 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插入。
问题实际上是在PHP方面。
通过使用ExtJs框架,在提交表单时,使用encodeURIComponent
对其进行编码
因此é
以%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 ...所以我们会看到会发生什么,希望它可以正常工作。
答案 0 :(得分:2)
我认为你知道这些事实:
é
)。 HTML实体用于HTML。 Oracle不是Web浏览器; - )您还必须知道HTML实体未绑定到特定的字符集;相反,它们习惯于在不依赖于字符集的环境中表现角色。
你不清楚地谈论ISO-8859-1和UTF-8。你想用什么字符集? ISO-8859-1易于使用,但它只能以一些拉丁语言(例如西班牙语)存储文本,并且它缺少像€符号这样的常见字符。 UTF-8使用起来比较棘手,但它可以存储Unicode联盟定义的所有字符(包括您需要的所有内容)。
一旦做出决定,您必须配置Oracle以在此类字符集中保存数据并选择适当的列类型。例如,VARCHAR2适用于纯ASCII,NVARCHAR2适用于UTF-8。
答案 1 :(得分:2)
这是我最终为解决这个问题而做的事情:
修改运行PHP的守护程序的配置文件:
NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
因此oci8连接使用ISO-8859-1。
然后在我的PHP配置中将默认内容类型设置为ISO-8859-1:
default_charset = "iso-8859-1"
当我从PHP通过oci8插入Oracle表时,我这样做:
utf8_decode($my_sent_value)
当从Oracle接收数据时,打印变量应该正常工作:
echo $my_received_value
然而,当通过ajax发送数据时,我不得不使用:
utf8_encode($my_received_value)
答案 2 :(得分:0)
如果您真的无法更改oracle将使用的字符集,那么在将数据存储到数据库之前,如何对Base64进行编码。这样,您可以接受来自任何字符集的字符并将它们存储为ISO-8859-1(因为Base64将输出完全映射到ISO-8859-1的ASCII字符集的子集)。 Base64编码将平均增加37%的字符串长度
如果您的数据只会以HTML格式显示,那么您也可以按照建议存储HTML实体,但请注意,每个未编码字符的单个实体最多可包含10个字符,例如θ是ϑ
答案 3 :(得分:0)
我不得不面对这个问题:LatinAmerican特殊字符存储为“?”或者我的Oracle数据库中的“¿”...我无法更改NLS_CHARACTER_SET,因为我们不是数据库所有者。
所以,我找到了一个解决方法:
1)ASP.NET代码 创建一个将字符串转换为十六进制字符的函数:
public string ConvertirStringAHex(String input)
{
Encoding encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
Byte[] stringBytes = encoding.GetBytes(input);
StringBuilder sbBytes = new StringBuilder(stringBytes.Length);
foreach (byte b in stringBytes)
{
sbBytes.AppendFormat("{0:X2}", b);
}
return sbBytes.ToString();
}
2)将上述函数应用于要编码的变量,如此
myVariableHex = ConvertirStringZHex( myVariable );
在ORACLE中,使用以下内容:
PROCEDURE STORE_IN_TABLE( iTEXTO IN VARCHAR2 )
IS
BEGIN
INSERT INTO myTable( SPECIAL_TEXT )
VALUES ( UTL_RAW.CAST_TO_VARCHAR2(HEXTORAW( iTEXTO ));
COMMIT;
END;
当然,iTEXTO是Oracle参数,它从ASP.NET代码接收“myVariableHex”的值。
希望它有所帮助...如果有什么需要改进的话请不要犹豫发表您的意见。
来源: http://www.nullskull.com/faq/834/convert-string-to-hex-and-hex-to-string-in-net.aspx https://forums.oracle.com/thread/44799