Nie sądzę, że jest jakiś prosty sposób; a wykonanie dynamicznego sprawdzenia jest stosunkowo łatwe (patrz przykład poniżej). Ale jako dość zawiłe podejście możesz przekonwertuj łańcuch na liczbę i z powrotem na łańcuch przy użyciu modelu formatu stworzonego z Twojej precyzji i skali:
Testowane tylko z kilkoma wartościami, ale wydaje się, że jak dotąd działa:
z t jako ( wybierz '0,123' jako wartość, 3 jako dokładność, 3 jako skalę z podwójnej unii wybierz '.123', 2, 2 z podwójnej unii wybierz '.123', 1, 3 z dual union wszystkie wybierz '.123', 2, 2 z dual union wszystkie wybierz '1234', 4, 0 z dual union wszystkie wybierz '1234', 3, 1 z dual union wszystkie wybierz '123', 2, 0 z dual union wszystkie wybierz '.123', 0, 3 z dual union wszystkie wybierz '-123.3', 4, 1 z dual union wszystkie wybierz '123456.789', 6, 3 z dual union wszystkie wybierz '123456.789', 7, 3 z dual union wszystkie wybierz '101.23253232', 3, 8 z dual union wszystkie wybierz '101.23253232', 11, 8 z dual) wybierz wartość, precyzja, skala, isNumber(wartość, precyzja, skala) isNum, isNumber2(value, Precision, scale ) isNum2 from t;WARTOŚĆ SKALA PRECYZJI ISNUM ISNUM2------------ ---------- ---------- --------- -----------0,123 3 3 0,123 0,123 0,123 2 2 0,12 0,123 1 3,1 23 0,123 2 2,12 1234 4 0 1234 1234 1234 3 1 123 2 0,123 0 3 -123,3 4 1 -123,3 -123,3 123456.789 6 3 123456.789 7 3 101.23253232 3 8 101.23253232 11 8 101.2325332 101.32532
Korzystanie z GDY INNE
nie jest idealne i można to zastąpić konkretnymi programami obsługi wyjątków. Założyłem, że chcesz, aby ta wartość zwracała wartość null, jeśli liczba jest nieprawidłowa, ale oczywiście możesz zwrócić cokolwiek lub zgłosić własny wyjątek.
isNum2
kolumna pochodzi z drugiej, znacznie prostszej funkcji, która po prostu wykonuje rzutowanie dynamicznie - czego wiem, że nie chcesz robić, to tylko dla porównania:
FUNKCJA TWÓRZ LUB ZAMIEŃ IsNumber2(pVALUE VARCHAR2, pPRECISION NUMBER, pSCALE NUMBER) RETURN NUMBERIS str VARCHAR2(80); num NUMBER;BEGIN str :='SELECT CAST(:v AS NUMBER(' || pPRECISION ||','|| pSCALE ||')) FROM DUAL'; EXECUTE IMMEDIATE str INTO num UŻYWAJĄC pVALUE; RETURN numer;WYJĄTEK GDY INNE TO RETURN NULL;END IsNumber2;/
Pamiętaj jednak, że cast
zaokrągla się, jeśli określona skala jest zbyt mała dla wartości; Być może zbyt mocno zinterpretowałem „zgodne z” w pytaniu, ponieważ w tym przypadku się mylę. Jeśli chcesz coś takiego jak '.123', 2, 2
być dozwolone (podając .12
), a następnie drugi GetFormat
wywołanie i zaznaczenie „scale too large” może zostać usunięte z mojego IsNumber
. Mogą być też inne niuanse, które przeoczyłem lub źle zinterpretowałem.
Warto również zauważyć, że początkowy to_number()
opiera się na ustawieniach NLS dla danych i dopasowywania sesji - szczególnie separator dziesiętny; i nie pozwoli na separator grup.
Prostsze może być zdekonstruowanie przekazanej wartości liczbowej na jej wewnętrzną reprezentację i sprawdzenie, czy jest ona porównywalna z precyzją i skalą… chociaż dynamiczna trasa oszczędza dużo czasu i wysiłku.