Pregunta

I am using the following code with an Oracle ADO.Net provider (DevArt's dotConnect Universal). Funny thing is that it works sometimes and then most times it throws 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();
            }
        }
¿Fue útil?

Solución 2

Try changing ON A.SRC_ID_VALUE = B.PRICE_TIER_KEY to ON A.SRC_ID_VALUE = to_char(B.PRICE_TIER_KEY).

From the manual: "When comparing a character value with a numeric value, Oracle converts the character data to a numeric value.". That implicit conversion is not always safe, you need to force Oracle to convert the number to a string instead.

Otros consejos

ORA-01722 is a data conversion error. It happens when we attempt to turn a string into a number when the string contains a non-numeric value. This can happen explicitly with a TO_NUMBER() cast or implicitly by using columns of different data types in a JOIN or a WHERE clause.

So you can now see that you've posted all the wrong information: what matters is the data structure and contents of the tables involved. The most likely candidates for trouble are the two columns in the join: SRC_ID_VALUE and PRICE_TIER_KEY. Are these both numeric columns or both strings? If one is numeric and the other isn't, does the string one contain only numeric data?

This matters because Oracle will cast the string column to a number before attempting the comparison.

For instance, if table1 has this data ...

 1234
10789

... and table2 has this data ...

'1234'
'45o7'

the first rows will join fine but the second row will hurl ORA-01722 and derail the query.

The way around this is to convert the numeric column to a string using TO_CHAR(). This will prevent Oracle using any index on that column. Which probably doesn't matter with your case, as you're mostly likely just doing full table scans on both tables, but it might matter with a more precise query.


"I think that is a horrible feature in Oracle."

Casting a string to a number changes the sort order. This ...

'1', '10', '2', '21', '3'

... becomes this ...

1, 2, 3, 10, 21

Of course it can't use the original index.

There is a workaround but it is somewhat involved.

  1. Build a function to test an input string and which returns a number if it's numeric or null if it's not.
  2. Build a function-based index using that function:

    create index src_id_num_fbi on GHX_MEMBER_TIER(is_a_number(SRC_ID_VALUE)) ;

  3. Use that function in your query:

    ... ON is_a_number(A.SRC_ID_VALUE) = B.PRICE_TIER_KEY

Only you can decide whether this is worth the effort.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top