I realise that the structure of the data in database I am working with leaves a lot to be desired, but I have no control over that, so bear with me.
What I have is a field ADDRESSES.COMPANY that may or may not be an integer ID. Sometimes it’s a string. When it is an integer, however, I want to do a join to another table COMPANIES. The original query (pre-join) looks like this:
SELECT *
FROM (SELECT ROWNUM AS ROW_NUM, INNERQUERY.*
FROM ( SELECT *
FROM ADDRESSES, COMPANIES
) INNERQUERY) OUTERQUERY
WHERE ROW_NUM <= 50 AND ROW_NUM > 0
If I try to join normally, I get an error ORA-01722: invalid number… for obvious reasons (it’s not always a number to attempt to join on, or at least I assume that’s what it must mean because it’s true!). My query after trying to join:
SELECT *
FROM (SELECT ROWNUM AS ROW_NUM, INNERQUERY.*
FROM ( SELECT *
FROM ADDRESSES, COMPANIES
WHERE ADDRESSES.COMPANY(+) = COMPANIES.ID
) INNERQUERY) OUTERQUERY
WHERE ROW_NUM <= 50 AND ROW_NUM > 0
The only two potential solutions I can come up with are both using the TO_NUMBER() function, which I assumed would evaluate a non-numerical string to 0. I tried:
SELECT *
FROM (SELECT ROWNUM AS ROW_NUM, INNERQUERY.*
FROM ( SELECT *
FROM ADDRESSES, COMPANIES
WHERE TO_NUMBER(ADDRESSES.COMPANY)(+) = COMPANIES.ID
) INNERQUERY) OUTERQUERY
WHERE ROW_NUM <= 50 AND ROW_NUM > 0
which errors with ORA-00936: missing expression (on line 7). I assumed my guess at the appropriate place to use it was incorrect and tried the following instead:
SELECT *
FROM (SELECT ROWNUM AS ROW_NUM, INNERQUERY.*
FROM ( SELECT *, TO_NUMBER(ADDRESSES.COMPANY) AS COMPANYID
FROM ADDRESSES, COMPANIES
WHERE COMPANYID(+) = COMPANIES.ID
) INNERQUERY) OUTERQUERY
WHERE ROW_NUM <= 50 AND ROW_NUM > 0
which errors with ORA-00923: FROM keyword not found where expected on line 3.
When my first attempt didn’t work, I was sure that my second would. But I am baffled by the error. Am I just completely clueless about Oracle syntax and/or behaviour, or is it something else? Is there a solution to my problem?
1.
WHERE TO_NUMBER(ADDRESSES.COMPANY)(+) = COMPANIES.IDYou cannot do this.
JOINS
2.
You cannot reference a column by alias in the same scope this alias was defined (unless it is an order by clause).
The correct way to perform an outer join in this case would be to use ansi join syntax:
It doesn’t make much sense to use
to_numberon string columns, as it will yield you the same invalid number error on the first non-numeric value it encounters during join.You may try, however, casting number to char, as it has been advised.
But you have to keep in mind that it would probably drop your perfomance, as you won’t be able to use index whenever you transform your column.