Requirement :
Generic query/function to check if the value provided in a varchar column in a table is actually a number & the precision does not exceed the allowed precision.
Available values:
Table_Name, Column_Name, Allowed Precision, Allowed Scale
General advise would be to create a function & use to_number() to validate the value however it won't validate the allowed length (precision-scale).
My solution:
Validate Number using Regexp NOT REGEXP_LIKE(COLUMN_NAME, '^-?[0-9.]+$')
Validate Length of left component (before decimal) (I have no idea what's its actually called) because for scale, oracle automatically rounds off if required. As the actual column is varchar i will use substr, instr to find the component on the left of decimal point.
As above Regexp allows number like 123...123124..55 I will also validate the number of decimal points. [If > 1 then error]
Query to find invalid number's:
Select * From Table_Name
Where
(NOT REGEXP_LIKE(COLUMN_NAME, '^-?[0-9.]+$')
OR
Function_To_Fetch_Left_Component(COLUMN_NAME) > (Precision-Scale)
/* Can use regexp_substr now but i already had a function for that */
OR
LENGTH(Column_Name) - LENGTH(REPLACE(Column_Name,'.','')) > 1
/* Can use regexp_count aswell*/)
I was happy & satisfied with my solution until a column with only '.' value escaped my check and I saw the limitation of my checks. Although adding another check to validate this as well will solve my problem the solution as a whole looks very inefficient to me.
I will really appreciate a better solution [in any way].
Thanks in advance.