Como você deve ter notado, o método baseado em regex é quase impossível de fazer corretamente. Por exemplo, seu teste diz que
1.234e-5
não é um número válido, quando realmente é. Além disso, você perdeu números negativos. E se algo se parecer com um número, mas quando você tentar armazená-lo causará estouro? Em vez disso, eu recomendaria criar uma função que tente realmente converter para
NUMERIC
(ou FLOAT
se sua tarefa exigir) e retorna TRUE
ou FALSE
dependendo se este elenco foi bem sucedido ou não. Este código simulará totalmente a função
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;
Chamar esta função em seus dados obtém os seguintes resultados:
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)
Além de ser mais correto e fácil de ler, também funcionará mais rápido se os dados forem realmente um número.