我想保存在Oracle数据库(10克)Unicode数据(希腊)。 我创建了一个简单的表:
据我所知,NVARCHAR2总是使用UTF-16编码所以它必须是罚款所有(人)语言。
然后我试图插入数据库的字符串。 我已经硬编码串码(“你好吗?”在希腊文)。 然后,我设法得到它从数据库返回并显示它。
class Program
{
static string connectionString = "<my connection string>";
static void Main (string[] args) {
string textBefore = "Τι κάνεις;";
DeleteAll ();
SaveToDatabase (textBefore);
string textAfter = GetFromDatabase ();
string beforeData = String.Format ("Before: {0}, ({1})", textBefore, ToHex (textBefore));
string afterData = String.Format ("After: {0}, ({1})", textAfter, ToHex (textAfter));
Console.WriteLine (beforeData);
Console.WriteLine (afterData);
MessageBox.Show (beforeData);
MessageBox.Show (afterData);
Console.ReadLine ();
}
static void DeleteAll () {
using (var oraConnection = new OracleConnection (connectionString)) {
oraConnection.Open ();
var command = oraConnection.CreateCommand ();
command.CommandText = "delete from UNICODEDATA";
command.ExecuteNonQuery ();
}
}
static void SaveToDatabase (string stringToSave) {
using (var oraConnection = new OracleConnection (connectionString)) {
oraConnection.Open ();
var command = oraConnection.CreateCommand ();
command.CommandText = "INSERT into UNICODEDATA (ID, UNICODESTRING) Values (11, :UnicodeString)";
command.Parameters.Add (":UnicodeString", stringToSave);
command.ExecuteNonQuery ();
}
}
static string GetFromDatabase () {
using (var oraConnection = new OracleConnection (connectionString)) {
oraConnection.Open ();
var command = oraConnection.CreateCommand ();
command.CommandText = "Select * from UNICODEDATA";
var erpReader = command.ExecuteReader ();
string s = String.Empty;
while (erpReader.Read ()) {
string text = erpReader.GetString (1);
s += text + ", ";
}
return s;
}
}
static string ToHex (string input) {
string bytes = String.Empty;
foreach (var c in input)
bytes += ((int)c).ToString ("X4") + " ";
return bytes;
}
}
下面是不同的输出:
在消息框中发送到数据库之前,文本:
在消息框中,从数据库中获取后的文字:
控制台输出:
请你可以建议我可能是错在这里做什么?
Answer 1:
我可以看到问题的五种可能的地区:
你是如何真正去文成.NET应用程序? 如果在STRING的硬编码的文字,你确定编译器承担源文件正确的编码?
有可能是你怎么想发送给数据库中的问题。
有可能是与它如何被存储在数据库中的一个问题。
有可能是与你怎么在数据库中获取它的一个问题。
有可能是与如何你又显示它以后的问题。
现在地区2-4声音就像他们就不太可能是一个问题比1和5你怎么算账显示的文本? 你居然取出来在.NET数据库,或者您使用的蟾蜍或类似的东西来尝试看看吧?
如果你再从.NET编写出来的,我建议你跳过数据库完全 - 如果你只是显示字符串本身,你怎么看?
我中有你可能会发现在有用的文章调试Unicode的问题 。 特别是集中在其中编码可以走错了每一个地方,并确保当你“显示”为你倾倒出确切的Unicode字符(如整数),这样你就可以检查这些,而不是仅仅不管你当前字体想要一个字符串显示。
编辑:好的,所以数据库某处问题所涉及。
我强烈建议你删除像ASP和HTML东西的方程。 写一个简单的控制台应用程序, 什么也不做 ,但插入的文本,并再次把它拿来。 使其前后转储个人Unicode字符(如整数)。 然后尝试,看看有什么在数据库中(例如,使用蟾蜍)。 我不知道甲骨文功能字符串转换成单独的Unicode字符序列,然后转换这些字符为整数,但是这将很可能是未来的事情我会尝试。
编辑:两个以上建议(很好看的控制台应用程序,顺便说一句)。
指定参数的数据类型,而不是只给它的对象。 例如:
command.Parameters.Add (":UnicodeString", OracleType.NVarChar).Value = stringToSave;
考虑使用Oracle自己的驱动程序,而不是一个内置到.NET的。 你可能想反正要做到这一点,因为它通常总计是更快,更可靠的,我相信。
Answer 2:
你可以决定哪些字符集数据库使用的NCHAR与查询:
SQL> SELECT VALUE
2 FROM nls_database_parameters
3 WHERE parameter = 'NLS_NCHAR_CHARACTERSET';
VALUE
------------
AL16UTF16
检查你的数据库配置是正确的,你可以运行在SQL以下*加:
SQL> CREATE TABLE unicodedata (ID NUMBER, unicodestring NVARCHAR2(100));
Table created
SQL> INSERT INTO unicodedata VALUES (11, 'Τι κάνεις;');
1 row inserted
SQL> SELECT * FROM unicodedata;
ID UNICODESTRING
---------- ---------------------------------------------------
11 Τι κάνεις;
Answer 3:
还有一两件事值得一提。
如果您正在使用Oracle客户端,并希望包括在CommandText Unicode字符,你应该folloing行添加到您的应用程序的启动:
System.Environment.SetEnvironmentVariable("ORA_NCHAR_LITERAL_REPLACE", "TRUE");
这将允许你,如果你需要它,使用的语法如下:
command.CommandText = "INSERT into UNICODEDATA (ID, UNICODESTRING) Values (11, N'Τι κάνεις;')";
Answer 4:
一些调查后,在这里我们去:
字符串输入= “•”; 炭S =输入[0];
//table kuuku with column kuku(nvarchar2(100))
string connString = "your connection";
//CLEAN TABLE
using (System.Data.OracleClient.OracleConnection cn = new System.Data.OracleClient.OracleConnection(connString))
{
cn.Open();
System.Data.OracleClient.OracleCommand cmd = new System.Data.OracleClient.OracleCommand("delete from kuku ", cn);
cmd.ExecuteNonQuery();
cn.Close();
}
//INSERT WITH PARAMETER BINDING - UNICODE SAVED
using (System.Data.OracleClient.OracleConnection cn = new System.Data.OracleClient.OracleConnection(connString))
{
cn.Open();
System.Data.OracleClient.OracleCommand cmd = new System.Data.OracleClient.OracleCommand("insert into kuku (kuku) values(:UnicodeString)", cn);
cmd.Parameters.Add(":UnicodeString", System.Data.OracleClient.OracleType.NVarChar).Value = input + " OK" ;
cmd.ExecuteNonQuery();
cn.Close();
}
//INSERT WITHOUT PARAMETER BINDING - UNICODE NOT SAVED
using (System.Data.OracleClient.OracleConnection cn = new System.Data.OracleClient.OracleConnection(connString))
{
cn.Open();
System.Data.OracleClient.OracleCommand cmd = new System.Data.OracleClient.OracleCommand("insert into kuku (kuku) values('" +input+" WRONG')", cn);
cmd.ExecuteNonQuery();
cn.Close();
}
//FETCH RESULT
using (System.Data.OracleClient.OracleConnection cn = new System.Data.OracleClient.OracleConnection(connString))
{
cn.Open();
System.Data.OracleClient.OracleCommand cmd = new System.Data.OracleClient.OracleCommand("select kuku from kuku", cn);
System.Data.OracleClient.OracleDataReader dr = cmd.ExecuteReader();
if(dr.Read())
{
string output = (string) dr[0];
char sa = output[0];
}
cn.Close();
}
}
Answer 5:
在阅读记录,尝试
Encoding utf = Encoding.Default;
var utfBytes = odatareader.GetOracleString(0).GetNonUnicodeBytes();//OracleDataReader
Console.WriteLine(utf.GetString(utfBytes));
Answer 6:
解决方案:设置NLS_LANG!
详细信息:我刚刚有同样的问题,而实际上有确切作为谢尔盖Bazarnik的调查描述了同样的情况。 使用绑定变量它的工作原理,没有他们就没有。
解决的办法是设置NLS_LANG在适当的位置。 因为我有Windows服务器我将它设置在Windows注册表下HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient11g_home1
请注意,regitry位置可能difer所以最简单的方法是搜索注册表“ORACLE_HOME”字符串。 其它系统也如Linux,UNIX可以设置此不同的方式(出口NLS_LANG ...)
在我来说,我把"NLS_LANG"="CROATIAN_CROATIA.UTF8"
。 因为我没有这个变量设置它去为缺省值。 更改注册表后,你应该重新启动过程。 在我的情况,我重新启动IIS。
至于原因,这与绑定变量的作品可能是因为它实际上发生在服务器端,而没有它实际上是在客户端发生。 因此,即使是DB可以插入正确的价值观 - 在这之前发生,客户端确实不需要的修正,因为它认为这是应该做的。 这是因为NLS_LANG默认为简单的代码页。 但是在做有用的任务,这产生了一个问题,它(如图调查看起来很难理解)。
如果您有多个Oracle版本,一定要纠正注册表中的所有版本(在我的情况甲骨文10例有效设置,但甲骨文11没有NLS_LANG设置的话)。
文章来源: How to save unicode data to oracle?