A view, function and TO_DATE causing an error.

10-11  Source: Network gathering  Views:0 

Advertisement
I have the following statement which calls a view, VW_DIST_RPT_WORK_LIST which in turn calls a function which returns either 'Null' or a date string e.g. '07 Oct 2003' as a VARCHAR2 (alias PROJECTED_DELIVERY_DATE).
Statement:
SELECT CUSTOMER_NAME, PROTOCOL_REFERENCE, SHIPPING_REFERENCE, CUSTOMER_REFERENCE, COUNTRY, PROJECTED_DELIVERY_DATE, STATUS, NOTES,
TO_DATE(PROJECTED_DELIVERY_DATE)
FROM VW_DIST_RPT_WORK_LIST
WHERE EXPECTED_DESP_DT IS NOT NULL
AND UPPER(PROJECTED_DELIVERY_DATE) NOT LIKE('NULL%')
AND EXPECTED_DESP_DT <= TO_DATE('07/10/2003', 'DD/MM/YYYY')
AND TO_DATE(PROJECTED_DELIVERY_DATE) <= TO_DATE('31/12/2003', 'DD/MM/YYYY') --< Problem here
I need to be able to specify a date filter on the PROJECTED_DELIVERY_DATE field and hence used the TO_DATE(PROJECTED_DELIVERY_DATE) <= TO_DATE('31/12/2003', 'DD/MM/YYYY') but this is generating an ORA-01858: a non-numeric character was found where a numeric character was expected.
I think the problem lies with the fact that this field can contain 'Null' which cannot be converted to a date using TO_DATE. I've tried adding a NOT LIKE ('NULL%') statement to catch any nulls which may be creeping in bu this doesn't solve the problem.
I've added TO_DATE(PROJECTED_DELIVERY_DATE) to the select above to determine if the nulls are being caught and if the TO_DATE in performing the conversion correctly which it is on both counts.
Any ideas anyone ?
The answer provided above by Monika will work for this situation. However, you should seriously think whether you should be using a string for date datatype. Ideally, you should rewrite the function that returns PROJECTED_DELIVERY_DATE and change the return type to DATE. The least you should do is to return NULL (instead of the string 'NULL') from the function. Oracle handles nulls perfectly, there is no reason you should write code to handle nulls;
One more thing. Looking at the type of error you are receiving, it seems that you are using rule based optimizer. Why do I think so? Because, in rule based optimizer, the conditions are evaluated in a specific order (viz, bottoms-up for AND clauses). To show this, look at the following simple demonstration. I did this in Oracle 8.1.6 (also in 9.2.0.4.0 on Windows).
-- Check the database version
select * from v$version;
BANNER
Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
PL/SQL Release 8.1.6.1.0 - Production
CORE 8.1.6.0.0 Production
TNS for Solaris: Version 8.1.6.0.0 - Production
NLSRTL Version 3.4.0.0.0 - Production
-- Create the test table
create table test (a number(2));
insert into test(a) values (0);
insert into test(a) values (1);
insert into test(a) values (2);
insert into test(a) values (3);
insert into test(a) values (4);
insert into test(a) values (5);
insert into test(a) values (6);
insert into test(a) values (7);
commit;
-- See that I have not analyzed the table. This will make use of RULE based optimizer
select * from test
where a > 0
and 1/a < .25;
and 1/a < .25
ERROR at line 3:
ORA-01476: divisor is equal to zero
-- Look at the query clause. Even though I specifically asked for records where a is positive
-- the evaluation path of rule based optimizer started at the bottom and as it evaluated the
-- first row with a=0, and caused an error.
-- Now look at the query below. I just re-arranged the conditions so that a > 0 is evaluated
-- first. As a result, the row with a=0 is ignored and the query executes without any problem.
select * from test
where 1/a < .25
and a > 0;
A
5
6
7
-- Now I analyze the table to create statistics. This will make the query use the
-- cost based optimizer (since optimizer goal is set to CHOOSE)
analyze table test compute statistics;
Table analyzed.
-- Now I issue the erring query. See it executes without any problem. This indicates that
-- the cost based optimizer was intelligent enough to evaluate the proper path instead of
-- looking only at the syntax.
select * from test
where a > 0
and 1/a < .25;
A
5
6
7
Does the above example seem familiar to your case? Even though you had the AND UPPER(PROJECTED_DELIVERY_DATE) NOT LIKE('NULL%') in your query, a record with PROJECTED_DELIVERY_DATE = 'NULL' was evaluated first and that caused the error.
Summary
1. Use dates for dates and strings for strings
2. Use cost based optimizer
Thanks
Suman
Related articles