Jestem ciekawy, czy istnieje prawdziwa różnica między money
typem danych a czymś podobnym decimal(19,4)
( jak sądzę, z czego pieniądze korzystają wewnętrznie).
Wiem, że money
jest to specyficzne dla SQL Server. Chcę wiedzieć, czy istnieje ważny powód, aby wybierać między sobą; większość próbek SQL Server (np. baza danych AdventureWorks) używa, money
a nie decimal
takich informacji jak cena.
Czy powinienem po prostu nadal używać typu danych pieniędzy, czy zamiast tego jest korzyść z używania dziesiętnego? Pieniądze to mniej znaków do wpisania, ale to nie jest prawidłowy powód :)
sql-server
types
Wayne Molina
źródło
źródło
DECIMAL(19, 4)
jest popularnym wyborem sprawdź to również sprawdź tutaj Formaty walut światowych, aby zdecydować, ile miejsc po przecinku użyć, w czym nadzieja pomaga.Odpowiedzi:
Nigdy nie powinieneś używać pieniędzy. Nie jest precyzyjne i jest czystym śmieciem; zawsze używaj liczb dziesiętnych / numerycznych.
Uruchom to, aby zobaczyć, co mam na myśli:
Wyjście: 2949.0000 2949.8525
Do niektórych osób, które powiedziały, że nie dzielisz pieniędzy przez pieniądze:
Oto jedno z moich zapytań do obliczenia korelacji, a zamiana tego na pieniądze daje złe wyniki.
źródło
money
namoney
bok tej „ilustracji” jest manipulacyjne. Jest to udokumentowany fakt, którymoney
ma stałą i bardzo ograniczoną precyzję. W takich przypadkach należy najpierw pomnożyć, a następnie podzielić. Zmień kolejność operatorów w tym przykładzie, a otrzymasz identyczne wyniki.money
Zasadniczo jest 64-bitowy int, a jeśli były do czynienia z wskazówki, byś pomnożyć przed podziałem.SQLMenace powiedział, że pieniądze są niedokładne. Ale nie mnożysz / nie dzielisz pieniędzy przez pieniądze! Ile wynoszą 3 dolary razy 50 centów? 150 centów? Mnożysz / dzielisz pieniądze przez skalary, które powinny być dziesiętne.
Rezultaty prawidłowego wyniku:
money
jest dobry, o ile nie potrzebujesz więcej niż 4 cyfr dziesiętnych i upewniasz się, że twoje skalary - które nie reprezentują pieniędzy - sądecimal
s.źródło
money / money
? Odpowiedź to całe jednostki bez dołączonego znaku dolara, co jest poprawne! Jest to całkowicie rozsądny scenariusz, sugerujący, że ze względu na takie dziwne przypadki brzegowe, takie jak ten,money
nie jest dobrym typem danych do użycia, ponieważ wynik jest zawsze przycinany z powrotem w celu dopasowania,money
zamiast przestrzegać normalnych reguł dotyczących precyzji i skalowania. Co jeśli chcesz obliczyć odchylenie standardowe zestawumoney
wartości? Tak,Sqrt(Sum(money * money))
(uproszczony) faktycznie ma sens.Wszystko jest niebezpieczne, jeśli nie wiesz, co robisz
Nawet precyzyjne typy dziesiętne nie mogą uratować dnia:
1,000000 <- Powinien wynosić 0,6000000
Te
money
typy są liczbami całkowitymiTekstowe reprezentacje
smallmoney
idecimal(10,4)
mogą wyglądać podobnie, ale to nie czyni ich wymiennymi. Czy kulisz się, gdy widzisz daty zapisane jakovarchar(10)
? To jest to samo.Za kulisami
money
/smallmoney
są po prostubigint
/int
Punktem dziesiętnym w reprezentacji tekstowejmoney
jest puch wizualny, podobnie jak myślniki z datą rrrr-mm-dd. SQL tak naprawdę nie przechowuje ich wewnętrznie.Jeśli chodzi o
decimal
vsmoney
, wybierz to, co jest odpowiednie do twoich potrzeb. Temoney
typy istnieją, ponieważ przechowywanie wartości księgowych jako wielokrotności całkowitych 1/10000 jednostki jest bardzo powszechne. Ponadto, jeśli masz do czynienia z rzeczywistymi pieniędzmi i obliczeniami wykraczającymi poza zwykłe dodawanie i odejmowanie, nie powinieneś robić tego na poziomie bazy danych! Zrób to na poziomie aplikacji, korzystając z biblioteki obsługującej zaokrąglanie przez bankiera (IEEE 754)źródło
Zdaję sobie sprawę, że WayneM stwierdził, że wie, że pieniądze są specyficzne dla SQL Server. Jednak pyta, czy istnieją jakieś powody, aby używać pieniędzy w systemie dziesiętnym lub odwrotnie, i myślę, że należy podać jeden oczywisty powód, a mianowicie w systemie dziesiętnym, o jedną rzecz mniej martw się, jeśli kiedykolwiek będziesz musiał zmienić DBMS - co może się zdarzyć.
Uczyń swoje systemy tak elastycznymi, jak to możliwe!
źródło
date
typu, powiedziałbym, że zawsze będziesz mieć takie problemy. Powinieneś powiedzieć „Nie używaj przestarzałych typów, gdy baza danych już zapewnia lepsze, bardziej zgodne ze standardami typy i ostrzega przed przestarzałymi typami ”.Cóż, lubię
MONEY
! Jest to bajt tańszy niżDECIMAL
, a obliczenia wykonują się szybciej, ponieważ (pod przykryciem) operacje dodawania i odejmowania są zasadniczo liczbami całkowitymi. @ Przykład SQLMenace - który jest doskonałym ostrzeżeniem dla nieświadomych - może być również zastosowany doINT
eger, gdzie wynik byłby zerowy. Ale to nie jest powód, aby nie używać liczb całkowitych - w stosownych przypadkach .Jest więc całkowicie „bezpieczny” i odpowiedni do użycia,
MONEY
gdy masz do czynienia z tym, z czym masz do czynieniaMONEY
i stosuj go zgodnie z matematycznymi zasadami, które on przestrzega (tak samo jak npINT
.Czy byłoby lepiej, gdyby SQL Server promował dzielenie i mnożenie
MONEY
naDECIMAL
s (lubFLOAT
s?) - być może, ale nie zdecydowali się tego zrobić; nie zdecydowali się też promowaćINT
egerówFLOAT
podczas dzielenia ich.MONEY
nie ma problemu z precyzją; to, żeDECIMAL
podczas obliczeń może zostać użyty większy typ pośredni, jest po prostu „cechą” używania tego typu (i nie jestem pewien, jak daleko sięga ta „cecha”).Aby odpowiedzieć na konkretne pytanie, „ważny powód”? Cóż, jeśli chcesz bezwzględną wydajność maksymalnie w
SUM(x)
którymx
mogłyby byćDECIMAL
lubMONEY
, wtedyMONEY
będzie miał przewagę.Nie zapomnij też, że jest mniejszym kuzynem
SMALLMONEY
- tylko 4 bajty, ale osiąga maksimum przy214,748.3647
- co jest dość małe jak na pieniądze - i dlatego często nie jest dobrze dopasowane.Aby dowieść sensu przy użyciu większych typów pośrednich, jeśli przypisujesz pośrednio jawnie do zmiennej,
DECIMAL
występuje ten sam problem:Daje
2950.0000
(okej, więc przynajmniejDECIMAL
zaokrąglaj, a nieMONEY
obcinaj - tak samo jak liczba całkowita).źródło
MONEY
jest o jeden bajt mniejszy niż dużyDECIMAL
, z dokładnością do 19 cyfr. Jednak większość rzeczywistych obliczeń pieniężnych (do 9,99 mln USD) mieści się wDECIMAL(9, 2)
, co wymaga zaledwie pięciu bajtów. Możesz zaoszczędzić rozmiar, mniej przejmować się błędami zaokrąglania i uczynić kod bardziej przenośnym.Właśnie natrafiliśmy na bardzo podobny problem i jestem teraz bardzo +1 za to, że nigdy nie używam pieniędzy, z wyjątkiem prezentacji na najwyższym poziomie. Mamy wiele tabel (w rzeczywistości kupon sprzedaży i fakturę sprzedaży), z których każda zawiera jedno lub więcej pól pieniędzy z powodów historycznych, i musimy wykonać proporcjonalne obliczenia, aby obliczyć, ile całkowitej faktury podatku dotyczy każdego wiersz na kuponie sprzedaży. Nasze obliczenia to
Powoduje to obliczanie pieniędzy / pieniędzy w świecie rzeczywistym, co powoduje błędy skali w części podziału, która następnie mnoży się do nieprawidłowej proporcji kadzi. Po późniejszym dodaniu tych wartości otrzymujemy sumę proporcji kadzi, które nie sumują się do całkowitej wartości faktury. Gdyby jedna z wartości w nawiasach była dziesiętna (mam zamiar rzucić jedną z nich jako taką), proporcja kadzi byłaby poprawna.
Kiedy nawiasy klamrowe nie były tam pierwotnie działały, myślę, że ze względu na większe wartości, efektywnie symulował większą skalę. Dodaliśmy nawiasy, ponieważ najpierw wykonywał mnożenie, co w niektórych rzadkich przypadkach podważyło dokładność dostępną do obliczeń, ale teraz spowodowało to znacznie częstszy błąd.
źródło
Jako kontrapunkt dla ogólnego ciągu innych odpowiedzi. Zobacz wiele zalet pieniędzy… Typ danych! w Przewodniku SQLCAT po silniku relacyjnym
W szczególności chciałbym zwrócić uwagę na następujące kwestie
Tak więc odpowiedź na pytanie brzmi „to zależy”. Należy zachować ostrożność przy niektórych operacjach arytmetycznych, aby zachować precyzję, ale może się okazać, że warto wziąć pod uwagę względy wydajności.
źródło
Chcę przedstawić inne spojrzenie na PIENIĄDZE w porównaniu z NUMERYCZNYM, w dużej mierze oparte na mojej własnej wiedzy i doświadczeniu ... Moim punktem widzenia są PIENIĄDZE, ponieważ pracowałem z tym przez długi czas i nigdy tak naprawdę nie korzystałem z NUMERYCZNEGO dużo… .
MONEY Pro:
Rodzimy typ danych . Używa rodzimego typu danych ( liczba całkowita ) tak samo jak rejestr procesora (32- lub 64-bitowy), więc obliczenia nie wymagają zbędnego narzutu, więc są mniejsze i szybsze ... PIENIĄDZE potrzebują 8 bajtów i NUMERYCZNE (19, 4 ) potrzebuje 9 bajtów (o 12,5% więcej) ...
PIENIĄDZE są szybsze, o ile są wykorzystywane, ponieważ miały być (jako pieniądze). Jak szybko? Mój prosty
SUM
test na 1 milionie danych pokazuje, że PIENIĄDZE to 275 ms, a NUMERIC 517 ms ... To prawie dwa razy szybciej ... Dlaczego test SUM? Zobacz następny punkt ProMONEY Con:
money
nie musi być tak precyzyjne i ma służyć jako pieniądze, a nie tylko numer...Ale ... Duże, ale tutaj twoja aplikacja dotyczy prawdziwych pieniędzy, ale nie używaj ich w wielu operacjach SUM, na przykład w rachunkowości. Jeśli zamiast tego używasz wielu podziałów i mnożenia, nie powinieneś używać PIENIĘDZY ...
źródło
money
kolumnieWszystkie poprzednie posty przynoszą ważne punkty, ale niektóre nie odpowiadają dokładnie na pytanie.
Pytanie brzmi: dlaczego ktoś wolałby pieniądze, skoro wiemy, że jest to mniej precyzyjny typ danych i może powodować błędy, jeśli jest stosowany w złożonych obliczeniach?
Używasz pieniędzy, kiedy nie wykonujesz skomplikowanych obliczeń i możesz wymienić tę precyzję na inne potrzeby.
Na przykład, gdy nie trzeba wykonywać tych obliczeń i trzeba zaimportować dane z prawidłowych ciągów tekstowych waluty. Ta automatyczna konwersja działa tylko z typem danych MONEY:
Wiem, że możesz stworzyć własną procedurę importu. Ale czasami nie chcesz odtwarzać procedury importu z formatami regionalnymi specyficznymi dla całego świata.
Kolejny przykład, gdy nie musisz wykonywać tych obliczeń (musisz tylko zapisać wartość) i musisz zaoszczędzić 1 bajt (pieniądze zajmują 8 bajtów, a dziesiętne (19,4) - 9 bajtów). W niektórych aplikacjach (szybki procesor, duża pamięć RAM, wolne IO), np. Po prostu odczytywanie dużej ilości danych, może to być również szybsze.
źródło
Nie powinieneś używać pieniędzy, gdy musisz wykonać pomnożenie / podział wartości. Pieniądze są przechowywane w taki sam sposób, jak liczba całkowita, podczas gdy dziesiętny jest przechowywany jako przecinek dziesiętny i cyfry dziesiętne. Oznacza to, że pieniądze spadną dokładność w większości przypadków, podczas gdy dziesiętne zrobi to tylko po przywróceniu do pierwotnej skali. Pieniądze są stałym punktem, więc ich skala nie zmienia się podczas obliczeń. Ponieważ jednak jest to punkt stały, gdy jest drukowany jako ciąg dziesiętny (w przeciwieństwie do stałej pozycji w łańcuchu podstawowym 2), wartości do skali 4 są dokładnie reprezentowane. Więc dodawanie i odejmowanie pieniędzy jest w porządku.
Dziesiętny jest reprezentowany wewnętrznie w podstawie 10, a zatem pozycja punktu dziesiętnego jest również oparta na liczbie podstawowej 10. Co sprawia, że jego ułamkowa część dokładnie reprezentuje jego wartość, tak jak w przypadku pieniędzy. Różnica polega na tym, że pośrednie wartości dziesiętne mogą zachować dokładność do 38 cyfr.
W przypadku liczby zmiennoprzecinkowej wartość jest zapisywana w postaci binarnej, tak jakby była liczbą całkowitą, a pozycja punktu dziesiętnego (lub binarnego, ahem) jest względna do bitów reprezentujących liczbę. Ponieważ jest to binarny przecinek dziesiętny, podstawowe liczby 10 tracą precyzję zaraz po przecinku. 1/5, czyli 0,2, nie może być dokładnie przedstawiona w ten sposób. Ograniczenia nie dotyczą ani pieniędzy, ani dziesiętnych.
Łatwo jest przekonwertować pieniądze na dziesiętne, wykonać obliczenia, a następnie zapisać wynikową wartość z powrotem w polu pieniężnym lub zmiennej.
Z mojego POV chcę, aby rzeczy, które zdarzają się z liczbami, po prostu się wydarzyły, bez konieczności zbytniego zastanawiania się nad nimi. Jeśli wszystkie obliczenia zostaną przekonwertowane na dziesiętne, to dla mnie chciałbym użyć dziesiętnego. Zaoszczędziłbym pole pieniędzy do celów wyświetlania.
Pod względem wielkości nie widzę wystarczającej różnicy, aby zmienić zdanie. Pieniądze zajmują 4 - 8 bajtów, podczas gdy dziesiętne mogą być 5, 9, 13 i 17. 9 bajtów może obejmować cały zakres, w jakim może być 8 bajtów pieniędzy. Pod względem indeksu (porównywanie i wyszukiwanie powinny być porównywalne).
źródło
Znalazłem powód używania dziesiętnego zamiast pieniędzy w temacie dokładności.
Wynik dziesiętny> 1,000000
MoneyResult> 0,9999
Wynik Float> 1
Po prostu przetestuj i podejmij decyzję.
źródło
Właśnie zobaczyłem ten wpis na blogu: Pieniądze vs. dziesiętne w SQL Server .
Co w zasadzie mówi, że pieniądze mają problem z precyzją ...
Za ten
money
typ otrzymasz 19,30 zamiast 19,34. Nie jestem pewien, czy istnieje scenariusz aplikacji, który dzieli pieniądze na 1000 części do obliczeń, ale ten przykład narzuca pewne ograniczenia.źródło
money
ismallmoney
typy danych są dokładne z dokładnością do dziesięciu tysięcznych reprezentowanych przez nich jednostek monetarnych.” jak powiedziano w msdn.microsoft.com/en-us/library/ms179882.aspx, więc każdy, kto mówi „to śmieci”, nie wie o czym mówi.