Search code examples
sqloracle-databaseora-01858

oracle date format comparison ORA-01858


I have this query on production, which had no problem till yesterday:

 SELECT E.ID       
    FROM EXAM_STUD_ENTERANCE E,
         EXAM_REGISTRATION R
   WHERE     E.EXAM_REG_ID = R.ID
         AND E.USER_NAME ='user'          
         AND E.BLOCK = 1
         AND E.STATUS = 1
      AND TO_DATE (TO_CHAR (SYSDATE, 'DD/MM/YYYY HH24:MI:SS'),
                'DD/MM/YYYY HH24:MI:SS') >
            TO_DATE (
                  TO_CHAR (R.EXAM_DATE, 'DD/MM/YYYY')
               || ' ' || R.EXAM_START_TIME
              ,
               'DD/MM/YYYY HH24:MI:SS')

   AND TO_DATE (TO_CHAR (SYSDATE, 'DD/MM/YYYY HH24:MI:SS'),
                'DD/MM/YYYY HH24:MI:SS') <
            TO_DATE (
                  TO_CHAR (R.EXAM_DATE, 'DD/MM/YYYY')
               || ' ' || R.EXAM_END_TIME
              ,
               'DD/MM/YYYY HH24:MI:SS');

But now I receive an error

ORA-01858: a non-numeric character was found where a numeric was expected

Type of columns EXAM_START_TIME and EXAM_END_TIME are NVARCHAR2(100), and stores data like '16:40' ; EXAM_DATE is DATE


Solution

  • Yesterday someone inserted a bad value into one of those time columns

    Do a

    SELECT * FROM EDUMAN_EXAM.EXAM_REGISTRATION 
    WHERE 
      NOT( 
        REGEXP_LIKE(EXAM_START_TIME, '^\d\d:\d\d:\d\d$') AND
        REGEXP_LIKE(EXAM_END_TIME, '^\d\d:\d\d:\d\d$')
      )
    

    Find the bad data, and remove it

    Note: you posted an sql that indicates the time columns store hh:mm:ss and you said "it was working" but then you claimed that the time columns don't store seconds. If they do store seconds, then use the query as above. If they don't store seconds, reduce the regex pattern to \d\d:\d\d

    As a side commentary, you should never have made the decision to store this time data as a string. The DATETIME that holds the EXAM_START_DATE can just as easily hold a time, and if you just want the DATE without the time part, you can TRUNC(some_datetime) to remove the time component

    Store the data in a column of the proper type, and you won't get this issue, and you wont have to get into this ludicrous date -> string -> concatenate -> parse process on thousands of records