Som du måske har bemærket, er en regex-baseret metode næsten umulig at udføre korrekt. For eksempel siger din test, at 1.234e-5
er ikke gyldigt nummer, når det virkelig er. Du gik også glip af negative tal. Hvad hvis noget ligner et tal, men når du forsøger at gemme det, vil det forårsage overløb?
I stedet vil jeg anbefale at oprette en funktion, der forsøger at caste til NUMERIC
(eller FLOAT
hvis din opgave kræver det) og returnerer TRUE
eller FALSE
afhængig af om denne rollebesætning var vellykket eller ej.
Denne kode vil fuldt ud simulere funktionen ISNUMERIC()
:
CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$
STRICT
LANGUAGE plpgsql IMMUTABLE;
Hvis du kalder denne funktion på dine data, får du følgende resultater:
WITH test(x) AS ( VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
('123.456'), ('abc'), ('1..2'), ('1.2.3.4'), ('1x234'), ('1.234e-5'))
SELECT x, isnumeric(x) FROM test;
x | isnumeric
----------+-----------
| f
. | f
.0 | t
0. | t
0 | t
1 | t
123 | t
123.456 | t
abc | f
1..2 | f
1.2.3.4 | f
1x234 | f
1.234e-5 | t
(13 rows)
Ikke alene er det mere korrekt og lettere at læse, det vil også fungere hurtigere, hvis data faktisk var et tal.