我在Oracle ADO.Net提供程序(DevArt的dotConnect Universal)中使用以下代码。有趣的是,它有时会起作用,然后大多数时候会抛出Devart.Data.Oracle.OracleException: ORA-01722: invalid number
string sql = "SELECT DISTINCT B.PRICE_TIER_KEY,b.label, a.INSERT_DATE AS PriceEffectiveDate,B.PROGRAM_KEY AS PRICE_PROGRAM_KEY FROM GHX_MEMBER_TIER A INNER JOIN VHA_INT_PRICE_TIER B ON A.SRC_ID_VALUE = B.PRICE_TIER_KEY WHERE RowNum <=100";
DbProviderFactory dpf = DbProviderFactories.GetFactory(System.Configuration.ConfigurationManager.ConnectionStrings["Con_ORA_DevArt"].ProviderName);
DbConnection conn = dpf.CreateConnection();
conn.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Con_ORA_DevArt"].ConnectionString;
DbCommand dbcmd = dpf.CreateCommand();
dbcmd.Connection = conn;
//dbcmd.Connection = uniConnection1;
dbcmd.CommandText = sql;
dbcmd.CommandType = CommandType.Text;
dbcmd.CommandTimeout = 0;
DataTable table = new DataTable();
try
{
System.Data.Common.DbDataAdapter da = dpf.CreateDataAdapter();
da.SelectCommand = dbcmd;
// Fill the DataTable.
da.Fill(table);
}
catch (Exception ex)
{
throw;
}
finally
{
if (conn != null && conn.State != ConnectionState.Closed)
{
conn.Close();
conn.Dispose();
}
if (dbcmd != null)
{
dbcmd.Dispose();
}
}
答案 0 :(得分:5)
ORA-01722是数据转换错误。当字符串包含非数字值时,我们尝试将字符串转换为数字时会发生这种情况。这可以通过TO_NUMBER()强制转换显式发生,也可以通过在JOIN或WHERE子句中使用不同数据类型的列隐式发生。
所以你现在可以看到你发布了所有错误的信息:重要的是数据结构和所涉及的表的内容。最容易出错的候选者是联接中的两列:SRC_ID_VALUE和PRICE_TIER_KEY。这些都是数字列还是两个字符串?如果一个是数字而另一个不是数字,那么字符串1是否只包含数字数据?
这很重要,因为Oracle会在尝试比较之前将字符串列转换为数字。
例如,如果table1有这个数据......
1234
10789
...而table2有这个数据......
'1234'
'45o7'
第一行将正常连接,但第二行将抛出ORA-01722并使查询脱轨。
解决这个问题的方法是使用TO_CHAR()将数字列转换为字符串。这将阻止Oracle使用该列上的任何索引。这可能与你的情况无关,因为你很可能只是在两个表上进行全表扫描,但它可能更精确的查询。
“我认为这在甲骨文中是一个可怕的特征。”
将字符串转换为数字会更改排序顺序。这......
'1','10','2','21','3'
......变成这个......
1,2,3,10,21
当然它不能使用原始索引。
有一种解决方法,但它有点涉及。
使用该函数构建基于函数的索引:
在GHX_MEMBER_TIER上创建索引src_id_num_fbi(is_a_number(SRC_ID_VALUE));
在查询中使用该功能:
... ON is_a_number(A.SRC_ID_VALUE)= B.PRICE_TIER_KEY
只有你能决定这是否值得付出努力。
答案 1 :(得分:4)
尝试将ON A.SRC_ID_VALUE = B.PRICE_TIER_KEY
更改为ON A.SRC_ID_VALUE = to_char(B.PRICE_TIER_KEY)
。
从the manual:“将字符值与数值进行比较时,Oracle会将字符数据转换为数值。”隐式转换并不总是安全的,您需要强制Oracle将数字转换为字符串。