Come avrai notato, il metodo basato su espressioni regolari è quasi impossibile da eseguire correttamente. Ad esempio, il tuo test dice che 1.234e-5
non è un numero valido, quando lo è realmente. Inoltre, hai perso numeri negativi. Cosa succede se qualcosa sembra un numero, ma quando provi a memorizzarlo causerà un overflow?
Invece, consiglierei di creare una funzione che tenti di eseguire effettivamente il cast su NUMERIC
(o FLOAT
se la tua attività lo richiede) e restituisce TRUE
o FALSE
a seconda che questo cast abbia avuto successo o meno.
Questo codice simulerà completamente la funzione 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;
Chiamando questa funzione sui tuoi dati ottieni i seguenti risultati:
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)
Non solo è più corretto e più facile da leggere, ma funzionerà anche più velocemente se i dati fossero effettivamente un numero.