Safe functions for casting numbers and timestamp in Oracle SQL
In the process of importing data which can be irregular from a flat file it is convenient to import all values as character strings, in this case Oracle’s varchar2, and then cast them into the proper format using the built-in datatype converters as e.g. to_number. The problem occurs when some value which is not convertible is stored in the column. This could be either because table column-overflow in the import process or because the value is optional and may be null or other non-set value. In this case the import methods doesn’t work.
Here are two methods I find useful for solving these problems, resulting in two PL/SQL functions embedding the functions used by oracle, but with a controlled exception where null values are stored and the error logged. Working on tables with several million rows I find this approach more useful than halting the process.
Safe number converter
CREATE OR REPLACE FUNCTION safe_to_number (p varchar2) RETURN number IS retval number; BEGIN IF p IS NULL THEN retval := null; ELSE retval := to_number(p); END IF; return retval; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Could not change value to number'); retval := null; return retval; END;
Safe timestamp converter
create or replace function safe_to_timestamp ( p_str in varchar2 , p_mask in varchar2) return timestamp is d date; begin d := to_timestamp(p_str, p_mask); return d; exception when others then DBMS_OUTPUT.PUT_LINE('Could not change value to timestamp'); return null; end;
I use these after the tables are imported as straight string-tables, to create a copy, but with the correct data format.
CREATE TABLE formatted_table as SELECT safe_to_timestamp(playdatetime,'YYYY-MM-DD HH24.MI.SS.FF') playdatetime, safe_to_timestamp(dateval,'YYYY-MM-DD HH24.MI.SS.FF') dateval, safe_to_number(id_table) id_table FROM unformatted_table;