tags:

views:

114

answers:

2

I have a master table (hereafter called SURVEY) and a detail table (hereafter called ANSWERS.) Unsurprisingly, ANSWERS has answers to SURVEY questions. ANSWERS has a VARCHAR2 column named TEXT. Some ANSWERS.TEXT values are truly text but some are actually numerics. Fortunately, I always know which rows contain text and which contain numbers-as-text.

This is the way it is. I can't change this.

Back in the day, when certain ANSWERS rows were saved, their TEXT values were cherry-picked and put into the SURVEY table in properly typed columns. A trivial one-table select would fetch SURVEYs and the special values.

But now, with the addition of a new application, we've removed the special columns. Instead, we now have to fetch the appropriate ANSWERS rows' TEXT values instead.

I have created a query that simulates the old trivial select statement. It works great... mostly.

Here's a snippet:

select survey.*, 
       j2.overall_score
  from survey,
       (select to_number(trim(ANSWER.text)) overall_score, 
               survey.id survey_id 
          from ANSWER, 
               [edited - more SQL that gets the 'score' row from ANSWERS]) j2      
 where
   survey.id=j2.survey_id
   and overall_score > 70    

You might note the j2. In the real query, there are six such columns, j1 through j6. When I run the query, it looks just like the old query. You can't tell it's really being assembled from a master/detail. That's a relief!

My problem, however, is that the 'overall_score > 70' phrase causes a '1722 invalid number' error. Oracle is as happy as a clam when I don't include the phrase, so all the output is passing through j2's to_number() function and looks good. But if I add the conditional, I fail.

The 'overall_score' part of the where clause is being added dynamically based upon search criteria entered from a web page.

I need some fu that tells Oracle I really do know what I'm doing, please do it. If there is non-numeric data, ok, let j2's to_number() fail. Cool. But otherwise, just do it.

Any wise words? I'm a contractor and time is nearly up. This is a new requirement :-/

+9  A: 

I think that the optimizer is probably merging the inline view with the rest of the query, which means that the condition overall_score > 70 may be evaluated for rows that don't match the rest of the view's predicates, thereby hitting rows that don't contain numeric values in text.

If that's what happening, you should be able to prevent it by adding a hint in the first line of the query:

select /*+ NO_MERGE(j2) */ ...

Alternatively, it could be pushing the predicate into the view, in which case you would need the NO_PUSH_PRED hint. If you can generate an execution plan for the query, it will probably show what the exact issue is.

Dave Costa
Will do. The DBA is creating me a plan table now :-D
Tony Ennis
Explain output is too long to post. I'm using oracle's UTLXPLS to see the result. What do you use?
Tony Ennis
I created a view of the unqualified query. Then I select from the view with the overall_score > 70. This also failed. That's curious unless Oracle's optimizer is smart enough to optimize views' internals when used in a select. I checked the data again, the column in question is always a numeric-as-text for the 'overall score' row.
Tony Ennis
Added NO_MERGE(j2) and NO_PUSH_PRED(j2) (and in fact for all j1..6) and got the same result.
Tony Ennis
Thank you for the help.
Tony Ennis
Oracle will happily optimise a view's internals when used in a larger select. It just squishes the full SQL together as if the view wasn't there - the view just makes things easier for the person putting together the SQL.
Nick Pierpoint
I bet a materialzed view would have done the trick. I don't have the rights to create one to try it, however.
Tony Ennis
+3  A: 

We created a special version of to_number which internally catches the '1722 invalid number' exception and returns 0 instead of. Replacing to_number with this new function in th sql eliminated this problem for us.

asalamon74
I'm dead in the water now. I'll try it but I suppose if my SQL is valid then no crud will get through.
Tony Ennis
This allows my query to run. Thank you.
Tony Ennis