Jak zapewne zauważyłeś, metoda oparta na wyrażeniach regularnych jest prawie niemożliwa do wykonania poprawnie. Na przykład twój test mówi, że 1.234e-5
nie jest prawidłowym numerem, kiedy tak naprawdę jest. Poza tym przegapiłeś liczby ujemne. Co jeśli coś wygląda jak liczba, ale gdy spróbujesz ją zapisać, spowoduje to przepełnienie?
Zamiast tego polecam utworzyć funkcję, która próbuje faktycznie rzutować na NUMERIC
(lub FLOAT
jeśli Twoje zadanie tego wymaga) i zwraca TRUE
lub FALSE
w zależności od tego, czy ta obsada się powiodła, czy nie.
Ten kod w pełni symuluje funkcję 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;
Wywołanie tej funkcji na Twoich danych daje następujące wyniki:
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)
Jest nie tylko bardziej poprawny i łatwiejszy do odczytania, ale będzie również działał szybciej, jeśli dane są faktycznie liczbą.