[oracle] Getting Error - ORA-01858: a non-numeric character was found where a numeric was expected

You can solve the problem by checking if your date matches a REGEX pattern. If not, then NULL (or something else you prefer).

In my particular case it was necessary because I have >20 DATE columns saved as CHAR, so I don't know from which column the error is coming from.

Returning to your query:

1. Declare a REGEX pattern.
It is usually a very long string which will certainly pollute your code (you may want to reuse it as well).

define REGEX_DATE = "'your regex pattern goes here'"

Don't forget a single quote inside a double quote around your Regex :-)

A comprehensive thread about Regex date validation you'll find here.

2. Use it as the first CASE condition:

To use Regex validation in the SELECT statement, you cannot use REGEXP_LIKE (it's only valid in WHERE. It took me a long time to understand why my code was not working. So it's certainly worth a note.

Instead, use REGEXP_INSTR
For entries not found in the pattern (your case) use REGEXP_INSTR (variable, pattern) = 0 .

    DEFINE REGEX_DATE = "'your regex pattern goes here'"

    SELECT   c.contract_num,
         CASE
            WHEN REGEXP_INSTR(c.event_dt, &REGEX_DATE) = 0 THEN NULL
            WHEN   (  MAX (TO_CHAR (TO_DATE (c.event_dt, 'YYYY-MM-DD'), 'MMDD'))
                    - MIN (TO_CHAR (TO_DATE (c.event_dt, 'YYYY-MM-DD'), 'MMDD')))
                 / COUNT (c.event_occurrence) < 32
            THEN
              'Monthly'
            WHEN       (  MAX (
                            TO_CHAR (TO_DATE (c.event_dt, 'YYYY-MM-DD'), 'MMDD'))
                        - MIN (
                            TO_CHAR (TO_DATE (c.event_dt, 'YYYY-MM-DD'), 'MMDD')))
                     / COUNT (c.event_occurrence) >= 32
                 AND   (  MAX (
                            TO_CHAR (TO_DATE (c.event_dt, 'YYYY-MM-DD'), 'MMDD'))
                        - MIN (
                            TO_CHAR (TO_DATE (c.event_dt, 'YYYY-MM-DD'), 'MMDD')))
                     / COUNT (c.event_occurrence) < 91
            THEN
              'Quarterley'
            ELSE
              'Yearly'
         END
FROM     ps_ca_bp_events c
GROUP BY c.contract_num;