• Bazy danych
  • DECIMAL(p,s) w SQL - jak dobrać precyzję i skalę?

DECIMAL(p,s) w SQL - jak dobrać precyzję i skalę?

Radosław Stępień • 5 listopada 2026
Hierarchia typów danych SQL: NULL, STRING, DATE, TIMESTAMP, INT, BIGINT, DECIMAL, FLOAT, DOUBLE, BINARY, INTERVAL, BOOLEAN, ARRAY, MAP, STRUCT, VARIANT.

Spis treści

Kwota 19,99 zł w bazie po kilku operacjach zaczyna wyglądać jak 19,989999… i raport przestaje się zgadzać. Typ zwykle rozwiązuje problem: dla wartości wymagających dokładności wybierz DECIMAL(p, s), ale jego parametry i zachowanie zależą od silnika oraz wykonywanych działań.

Hierarchia typów danych SQL: od NULL do STRING, INTEGER, DECIMAL i innych.

DECIMAL przechowuje wartości dokładnie, jeśli dobierzesz właściwy zakres

  • p oznacza łączną liczbę cyfr, a s liczbę cyfr po separatorze dziesiętnym.
  • DECIMAL(10,2) pozwala zapisać do ośmiu cyfr przed separatorem i dwie po nim.
  • Konwersja do mniejszej skali może zaokrąglić wartość, zamiast zgłosić błąd.
  • Reguły obliczeń różnią się między silnikami, więc sprawdź typ wyniku dzielenia i mnożenia.
  • FLOAT i DOUBLE są przybliżone; dla kwot zwykle lepiej sprawdza się typ dziesiętny.

DECIMAL(10,2) nie oznacza dziesięciu cyfr przed przecinkiem

Zapis DECIMAL(p, s) określa pojemność kolumny: p to maksymalna liczba cyfr łącznie, a s wskazuje, ile z nich może wystąpić po separatorze. W definicji DECIMAL(10,2) zostaje więc osiem cyfr na część całkowitą i dwie na ułamkową.

W praktyce taki typ pasuje do ceny lub kwoty o dwóch miejscach po przecinku, ale niekoniecznie do każdej liczby związanej z pieniędzmi. Jeśli przechowujesz kurs waluty, stawkę podatku albo wynik pomiaru, dwa miejsca po separatorze mogą uciąć potrzebną precyzję. Dobierz skalę do danych źródłowych i reguł biznesowych, nie do wyglądu przykładowego raportu.

Dokładność nie chroni przed cichym zaokrągleniem

Kolumna dziesiętna może przechowywać wartość dokładnie, a mimo to dostać inną liczbę niż ta podana w zapytaniu. Dzieje się tak, gdy wejście ma więcej cyfr ułamkowych, niż dopuszcza skala kolumny. Dokumentacja Microsoft Learn dla DECIMAL i NUMERIC w SQL Server opisuje zaokrąglanie przy konwersji do niższej precyzji lub skali.

Przykładowo kwota 12,345 zapisana w kolumnie o skali 2 może zostać zaokrąglona do dwóch miejsc. To nie to samo co błąd przepełnienia: za mało miejsca na część całkowitą może uniemożliwić zapis, podczas gdy nadmiar cyfr po separatorze może zostać zaokrąglony. Testuj oba przypadki, szczególnie przed migracją danych.

Ten sam zapis typu nie gwarantuje identycznego zachowania w każdej bazie

Przy przejściu między PostgreSQL, MySQL i SQL Server najłatwiej przeoczyć granice skali oraz limity deklaracji. PostgreSQL pozwala jawnie zadeklarować precyzję numeric do 1000 cyfr, podczas gdy SQL Server ogranicza precyzję decimal do 38, a MySQL dopuszcza maksymalnie 65 cyfr dla DECIMAL. To różnice istotne przy przenoszeniu schematu, nie ciekawostka dokumentacyjna.

Jest też mniej oczywisty szczegół: PostgreSQL dopuszcza ujemną skalę, na przykład NUMERIC(2,-3), która zaokrągla wartości do tysięcy. Ta składnia nie jest przenośna do każdego systemu SQL. Przed migracją sprawdź definicje kolumn oraz wynikowe typy wyrażeń, bo zgodna nazwa typu nie oznacza zgodnych reguł.

Dzielenie może obciąć precyzję, zanim wynik trafi do kolumny

Załóżmy, że liczysz jednostkową cenę jako sumę 100,00 podzieloną przez 3. Oczekiwanym wynikiem może być wartość z wieloma cyframi po przecinku, lecz konkretna baza ustala precyzję i skalę wyniku według reguł dla działania, a dopiero potem ewentualnie konwertuje go do typu kolumny.

W SQL Server wynik dzielenia typów dziesiętnych ma wyliczaną precyzję i skalę, a całkowita precyzja nie może przekroczyć 38. Gdy wynik wymaga więcej miejsca, skala może zostać ograniczona, co może doprowadzić do zaokrąglenia. Z kolei PostgreSQL zaznacza, że obliczenia na numeric są dokładne tam, gdzie to możliwe, ale mogą być wolniejsze od typów całkowitych i zmiennoprzecinkowych. Typ wejściowy wpływa więc na wynik pośredni, nie tylko na zapis końcowy.

Uważam, że przy kwotach bezpieczniej jawnie rzutować argumenty działania i świadomie zaokrąglić wynik dopiero w wybranym miejscu, zamiast liczyć na domyślne reguły silnika. Na przykład użyj CAST(... AS DECIMAL(12,4)) dla obliczenia ceny jednostkowej, a później osobno zdecyduj, czy wynik prezentować i zapisywać z dwiema cyframi.

SytuacjaMożliwa przyczynaCo zrobić
Kwota po zapisie ma mniej cyfr ułamkowychSkala kolumny jest mniejsza niż precyzja wejściaZweryfikuj wymaganą skalę i zachowanie konwersji
Wstawienie dużej wartości kończy się błędemBrak miejsca na cyfry przed separatoremZwiększ precyzję albo ustal dozwolony zakres danych
Wynik dzielenia zaskakuje długościąSilnik wyznacza skalę wyrażenia według własnych regułSprawdź typ wyniku i użyj jawnego rzutowania
Po migracji liczby zachowują się inaczejSilniki mają różne limity i obsługę skaliPrzetestuj wartości graniczne i działania arytmetyczne

FLOAT nie zastępuje DECIMAL przy rozliczaniu kwot

FLOAT i DOUBLE zapisują wartości jako przybliżenia, dlatego nie każda liczba dziesiętna ma w nich dokładną reprezentację. Dokumentacja MySQL Reference Manual wskazuje DECIMAL jako typ dokładny, stosowany między innymi przy danych pieniężnych. W PostgreSQL real i double precision są opisane jako typy niedokładne, a numeric jako dokładny.

Reguła wyboru jest prosta. Jeśli wartość musi zachować ustaloną liczbę cyfr dziesiętnych, na przykład kwota faktury, stawka lub saldo, wybierz DECIMAL/NUMERIC; jeśli dane są pomiarami naukowymi, a dopuszczalne jest przybliżenie i ważna jest wydajność, rozważ typ zmiennoprzecinkowy. Pamiętaj też, że format wyświetlania to osobna sprawa: zera końcowe mogą być prezentowane inaczej niż oczekujesz, mimo że wartość jest poprawna.

Przed wdrożeniem sprawdź trzy przypadki graniczne

Najwięcej błędów wychodzi przy wartościach skrajnych, a nie przy zwykłym rekordzie z testowego środowiska. Przed wdrożeniem sprawdź największą dozwoloną kwotę, najmniejszy ułamek, który musi zostać zachowany, oraz rezultat dzielenia lub mnożenia używanego w aplikacji.

W testach uwzględnij także zapis z nadmiarem miejsc po separatorze i sprawdź, czy baza zaokrągla go zgodnie z oczekiwaniem. To krótki test, który często rozstrzyga, czy definicja DECIMAL(p,s) odpowiada rzeczywistemu zakresowi danych, a nie tylko przykładowej wartości w kodzie.

FAQ - Najczęstsze pytania

Parametr p określa łączną liczbę cyfr, a s liczbę cyfr po separatorze dziesiętnym. Dlatego DECIMAL(10,2) pozwala przechować osiem cyfr przed separatorem i dwie po nim.

Jeśli wejściowa liczba ma więcej cyfr po separatorze, niż dopuszcza skala kolumny, baza może zaokrąglić wartość podczas konwersji. Przykładowo 12,345 zapisane w kolumnie o skali 2 może zostać zaokrąglone. Brak miejsca na cyfry przed separatorem może natomiast spowodować błąd przepełnienia.

Silnik wyznacza precyzję i skalę wyniku działania według własnych reguł, zanim wynik trafi do kolumny. W SQL Server całkowita precyzja wyniku nie może przekroczyć 38, więc skala może zostać ograniczona. Warto jawnie rzutować argumenty, na przykład do DECIMAL(12,4), a zaokrąglenie wykonać świadomie w wybranym miejscu.

DECIMAL i NUMERIC są właściwsze dla kwot, stawek i sald, gdy trzeba zachować ustaloną liczbę cyfr dziesiętnych. FLOAT i DOUBLE przechowują wartości przybliżone, dlatego lepiej pasują do pomiarów, w których dopuszczalna jest niedokładność i liczy się wydajność.

Limity różnią się między silnikami: PostgreSQL pozwala zadeklarować precyzję numeric do 1000 cyfr, SQL Server ogranicza decimal do 38, a MySQL dopuszcza maksymalnie 65 cyfr dla DECIMAL. PostgreSQL obsługuje także ujemną skalę, na przykład NUMERIC(2,-3), która zaokrągla wartości do tysięcy. Przed migracją przetestuj definicje kolumn, wartości graniczne oraz wyniki mnożenia i dzielenia.

Oceń artykuł

Ocena: 4.67 Liczba głosów: 3

Tagi

decimal
float
skala
rzutowanie
migracja
Autor Radosław Stępień
Radosław Stępień
Dziedzina programowania i technologii rozwija się w zawrotnym tempie, co sprawia, że ciągłe śledzenie nowinek i głębokie zrozumienie procesów są kluczowe. Nazywam się Radosław Stępień i od 13 lat aktywnie działam w branży IT, dzieląc się swoją wiedzą i doświadczeniem. Moje zainteresowania skupiają się na praktycznych aspektach tworzenia oprogramowania, analizie trendów technologicznych oraz budowaniu satysfakcjonującej ścieżki kariery w tym dynamicznym sektorze. Staram się przedstawiać złożone zagadnienia w sposób przystępny, opierając się na sprawdzonych informacjach i własnych obserwacjach z wieloletniej pracy. Zależy mi na tym, aby treści, które tworzę, były nie tylko merytoryczne i aktualne, ale przede wszystkim pomocne dla każdego, kto chce zgłębić tajniki IT lub rozwijać się zawodowo.

Udostępnij artykuł

Napisz komentarz