Jak zapanować nad separatorami dziesiętnymi liczb?


W aplikacjach sporo zamieszania robią liczby niecałkowite. Kluczem problemów jest nieszczęsny przecinek lub kropka, oddzielający część całkowitą od dziesiętnej. W jednych systemach preferuje się jako separator kropkę, w innych zaś przecinek. Formaty plików wejściowych czy wyjściowych też stosują różne separatory w zależności od widzimisię autora formatu pliku.

Oracle podsuwa nam parę przydatnych narzędzi.

Do formatowania liczb służy funkcja TO_CHAR.

 TO_CHAR( value [, format_mask])  

VALUE - nasza liczba
FORMAT_MASK - maska formatowania

 select to_char(260.45, 'FM999D00') from dual;  

TO_CHAR(260.45,'FM999D00')
260.45

W naszym przykładzie jako separator dziesiętny została ustawiona kropka. Dlaczego kropka? Kropka została pobrana z naszych lokalnych ustawień NLS.

SELECT * FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_NUMERIC_CHARACTERS';

PARAMETERVALUE
NLS_NUMERIC_CHARACTERS.,

Jeśli zmienimy parametr sesji - zmienimy też wyświetlony separator naszej liczby.

 alter session SET NLS_NUMERIC_CHARACTERS = ',.';  
SELECT * FROM NLS_SESSION_PARAMETERS where parameter = 'NLS_NUMERIC_CHARACTERS';
select to_char(260.45, 'FM999D00') from dual;

TO_CHAR(260.45,'FM999D00')
260,45

No tak, ale to są nasze lokalne ustawienia. Ale jak  takim razie zarządzać separatorem w bazie danych np podczas generowania plików?

Otóż funkcja TO_CHAR ma trzeci, rzadko używany parametr:

 TO_CHAR( value [, format_mask] [, nls_language] )  

NLS_LANGUAGE 
umożliwia ustawienie parametru NLS_NUMERIC_CHARACTERS -  czyli ustalenie separatorów liczb: pierwszy znak to separator dziesiętny a drugi - separator tysięcy.

Dzięki temu możemy dowolnie i z pełną odpowiedzialnością zarządzać separatorami.  

select 'Lokalne' , to_char(260.45, 'FM999D00') from dual
union all
select 'Przecinek' , to_char(260.45, 'FM999D00', 'NLS_NUMERIC_CHARACTERS = '',.''') from dual
union all
select 'Kropka' , to_char(260.45, 'FM999D00', 'NLS_NUMERIC_CHARACTERS = ''.,''') from dual;


'LOKALNE'TO_CHAR(260.45,'FM999D00')
Lokalne260,45
Przecinek260,45
Kropka260.45

Często kontrolę nad tym, jaki będzie użyty separator zostawiamy ustawieniom bazy danych. I często to działa.  Zdarzają się jednak sytuacje, gdy parametry te nie są takie, jakich byśmy się spodziewali. Na przykład po migracji na nowy serwer parametry te mogą nieświadomie ulec zmianie. Czasem też na serwerach testowych ustawienia parametrów różnią się od ustawień produkcyjnych co może powodować rozbieżności w sposobie działania aplikacji podczas testów i podczas pracy produkcyjnej.

Być może błędy te są łatwe do naprawy ale nie zawsze są łatwe do odnalezienia. I jeśli możemy praktycznie zerowym kosztem zapobiec takim sytuacjom - to czemu nie!

Komentarze