Czy należy wybrać MONEY lub dziesiętne (x,y) typy danych w SQL Server?

Jestem ciekaw, czy istnieje prawdziwa różnica między typem danych money a czymś w rodzaju decimal(19,4) (Co pieniądze używają wewnętrznie, jak sądzę).

Zdaję sobie sprawę, że {[0] } jest specyficzne dla SQL Server. Chcę wiedzieć, czy istnieje przekonujący powód, aby wybrać jeden nad drugim; większość próbek SQL Server (np. baza danych AdventureWorks) używa money, a nie decimal do informacji o cenach.

Czy powinienem dalej korzystać z danych o pieniądzach, czy jest czy jest korzyść z używania dziesiętnego zamiast tego? Pieniądze są mniej znaków do wpisania, ale to nie jest ważny powód:)

Author: Peter Mortensen, 2009-02-24

12 answers

Nigdy przenigdy nie powinieneś używać pieniędzy. Nie jest precyzyjny i jest czystym śmieciem; Zawsze używaj dziesiętnych / liczbowych.

Uruchom to, aby zobaczyć, co mam na myśli:

DECLARE
    @mon1 MONEY,
    @mon2 MONEY,
    @mon3 MONEY,
    @mon4 MONEY,
    @num1 DECIMAL(19,4),
    @num2 DECIMAL(19,4),
    @num3 DECIMAL(19,4),
    @num4 DECIMAL(19,4)

    SELECT
    @mon1 = 100, @mon2 = 339, @mon3 = 10000,
    @num1 = 100, @num2 = 339, @num3 = 10000

    SET @mon4 = @mon1/@mon2*@mon3
    SET @num4 = @num1/@num2*@num3

    SELECT @mon4 AS moneyresult,
    @num4 AS numericresult

Wyjście: 2949.0000 2949.8525

Do niektórych ludzi, którzy mówili, że nie dzielimy pieniędzy na pieniądze:

Oto jedno z moich zapytań do obliczania korelacji, a zmiana tego na pieniądze daje złe wyniki.

select t1.index_id,t2.index_id,(avg(t1.monret*t2.monret)
    -(avg(t1.monret) * avg(t2.monret)))
            /((sqrt(avg(square(t1.monret)) - square(avg(t1.monret))))
            *(sqrt(avg(square(t2.monret)) - square(avg(t2.monret))))),
current_timestamp,@MaxDate
            from Table1 t1  join Table1 t2  on t1.Date = traDate
            group by t1.index_id,t2.index_id
 259
Author: SQLMenace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-21 16:15:43

SQLMenace powiedział, że pieniądze są niedokładne. Ale nie mnożysz/nie dzielisz pieniędzy przez pieniądze! Ile to 3 dolary razy 50 centów? 150 dolarów? Mnożysz / dzielisz pieniądze przez Skalary, które powinny być dziesiętne.

DECLARE
@mon1 MONEY,
@mon4 MONEY,
@num1 DECIMAL(19,4),
@num2 DECIMAL(19,4),
@num3 DECIMAL(19,4),
@num4 DECIMAL(19,4)

SELECT
@mon1 = 100,
@num1 = 100, @num2 = 339, @num3 = 10000

SET @mon4 = @mon1/@num2*@num3
SET @num4 = @num1/@num2*@num3

SELECT @mon4 AS moneyresult,
@num4 AS numericresult

Daje poprawny wynik:

moneyresult           numericresult
--------------------- ---------------------------------------
2949.8525             2949.8525

money jest dobre, o ile nie potrzebujesz więcej niż 4 cyfry dziesiętne i upewnij się, że Twoje Skalary-które nie reprezentują pieniędzy-są decimals.

 250
Author: configurator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-24 18:09:44

Wszystko jest niebezpieczne, jeśli nie wiesz, co robisz

Nawet precyzyjne typy dziesiętne nie mogą uratować dnia:

declare @num1 numeric(38,22)
declare @num2 numeric(38,22)
set @num1 = .0000006
set @num2 = 1.0
select @num1 * @num2 * 1000000

1.000000


Typy money są liczbami całkowitymi

Reprezentacje tekstowe smallmoney i decimal(10,4) mogą wyglądać podobnie, ale to nie czyni ich wymiennymi. Czy marudzisz, gdy widzisz daty zapisane jako varchar(10)? To jest to samo.

Behind the scenes, money/smallmoney są tylko bigint/int punkt dziesiętny w reprezentacji tekstowej money jest przesunięciem wizualnym, podobnie jak myślniki w dacie RRRR-MM-dd. SQL nie przechowuje ich wewnętrznie.

Odnośnie decimal vs money, Wybierz to, co jest odpowiednie dla Twoich potrzeb. Typy money istnieją, ponieważ przechowywanie wartości księgowych jako wielokrotności całkowite 1 / 10000th jednostki jest bardzo powszechne. Ponadto, jeśli masz do czynienia z rzeczywistymi pieniędzmi i obliczeniami wykraczającymi poza proste dodawanie i odejmowanie, ty nie powinno się tego robić na poziomie bazy danych! zrób to na poziomie aplikacji z biblioteką obsługującą Zaokrąglanie bankiera (IEEE 754)

 46
Author: Anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:41

Zdaję sobie sprawę, że WayneM stwierdził, że wie, że pieniądze są specyficzne dla SQL Server. Jednak on pyta, Czy istnieją jakieś powody, aby używać pieniędzy na dziesiętne lub odwrotnie i myślę, że jeden oczywisty powód nadal powinien być podany i że jest za pomocą dziesiętne oznacza, że jest to jedna rzecz mniej martwić się, jeśli kiedykolwiek trzeba zmienić DBMS-co może się zdarzyć.

Spraw, aby Twoje systemy były jak najbardziej elastyczne!

 37
Author: Dean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-13 00:28:10

Podoba mi się!do obserwowanych nr: 64222 Jest to bajt tańszy niż DECIMAL, a obliczenia wykonują się szybciej, ponieważ (pod pokrywami) operacje dodawania i odejmowania są zasadniczo operacjami całkowitymi. Przykład @SQLMenace-co jest wielkim ostrzeżeniem dla nieświadomych-równie dobrze można by zastosować do egerów INT, gdzie wynik byłby zerowy. Ale to nie jest powód, aby nie używać liczb całkowitych - tam, gdzie jest to właściwe.

Jest więc całkowicie "bezpieczny" i odpowiedni do użycia MONEY, gdy masz do czynienia z z is MONEY i używać go zgodnie z regułami matematycznymi, które się po nim następują (tak samo jak INTeger).

Byłoby lepiej, gdyby SQL Server promował dzielenie i mnożenie MONEYna DECIMALs (lub FLOAT s?)- możliwe, ale nie zdecydowali się na to; nie zdecydowali się też promować INTegerów do FLOATs, dzieląc je.

MONEY nie ma problemu z precyzją; to, że DECIMALs mają większy pośredni typ używany podczas obliczeń, jest tylko 'cechą' używania tego typu (i nie jestem pewien, jak daleko ta "funkcja" się rozszerza).

Aby odpowiedzieć na konkretne pytanie, "przekonujący powód"? Cóż, jeśli chcesz absolutnej maksymalnej wydajności w SUM(x) gdzie x może być DECIMAL lub MONEY, to MONEY będzie miał przewagę.

Również, nie zapominaj, że jest mniejszy kuzyn, SMALLMONEY-tylko 4 bajty, ale robi max out na 214,748.3647 - co jest dość małe jak na pieniądze - i tak nie jest często dobre dopasowanie.

Aby udowodnić punkt wokół za pomocą większego pośredniego typy, jeśli przypisujesz pośredni jawnie do zmiennej, DECIMAL ma ten sam problem:

declare @a decimal(19,4)
declare @b decimal(19,4)
declare @c decimal(19,4)
declare @d decimal(19,4)

select @a = 100, @b = 339, @c = 10000

set @d = @a/@b

set @d = @d*@c

select @d

Produkuje 2950.0000 (dobrze, więc przynajmniej DECIMAL zaokrąglone, a nie MONEY obcięte-tak samo jak liczba całkowita.)

 30
Author: dsz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-11 20:37:06

Jako punkt przeciwny do ogólnego ciągu pozostałych odpowiedzi. Zobacz wiele korzyści płynących z pieniędzy ... typ danych! in Sqlcat ' s Guide to Relational Engine

W szczególności chciałbym zwrócić uwagę na następujące

Pracując nad implementacjami klientów, znaleźliśmy kilka interesujących liczby wyników dotyczące typu danych o pieniądzach. Na przykład, gdy Usługi analityczne zostały ustawione na typ danych waluty (od double) do dopasuj typ danych SQL Server, tam na szybkość przetwarzania (rzędy / sek.). Aby uzyskać szybszą wydajność w SQL Server Integration Services (SSIS), aby załadować 1,18 TB w mniej niż trzydzieści minut, jak zanotowano w SSIS 2008-rekord świata w skuteczności ETL, był zaobserwowano, że zmiana czterech dziesiętnych (9,2) kolumn o wielkości 5 bajtów w tabeli linii TPC-H do money (8 bajtów) Poprawiono bulk prędkość wstawiania o 20% ... Powodem poprawy wydajności jest tabelaryczny strumień danych SQL Server (TDS) protokół, który ma kluczową zasadę projektowania, aby przesyłać dane w kompaktowej postaci binarnej i jak najbliżej pamięci wewnętrznej format SQL Server. Empirycznie, zaobserwowano to podczas SSIS 2008-world record ETL performance test przy użyciu Kernrate; protokół znacznie spadł, gdy typ danych został przełączony na money from decimal. To sprawia, że przekazywanie danych w sposób jak najbardziej efektywny. Złożony typ danych wymaga dodatkowego parsowania i cykli procesora do obsługi niż a Typ o stałej szerokości.

Więc odpowiedź na pytanie brzmi "to zależy". Trzeba być bardziej ostrożnym z pewnych operacji arytmetycznych, aby zachować precyzję, ale może okazać się, że względy wydajności sprawiają, że warto.

 12
Author: Martin Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-24 10:42:31

Właśnie natknęliśmy się 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 faktura sprzedaży), z których każda zawiera jedno lub więcej pól pieniędzy ze względów historycznych, a my musimy wykonać proporcjonalną kalkulację, aby ustalić, ile całkowitego podatku faktury ma znaczenie dla każdej linii na kuponie sprzedaży. Nasze obliczenia to

vat proportion = total invoice vat x (voucher line value / total invoice value)

To daje prawdziwe pieniądze / pieniądze obliczenie powodujące błędy skali w części podziału, które następnie mnoży się do nieprawidłowej proporcji vat. Gdy te wartości są następnie dodawane, kończymy z sumą proporcji vat, które nie sumują się do całkowitej wartości Faktury. Gdyby któraś z wartości w nawiasach była dziesiętna (zaraz rzucę jedną z nich jako taką), proporcja vat byłaby prawidłowa.

Gdy nawiasów nie było pierwotnie to działało, chyba ze względu na większe wartości zaangażowana, skutecznie symulowała większą skalę. Dodaliśmy nawiasy, ponieważ najpierw wykonywano mnożenie, co w niektórych rzadkich przypadkach podważało precyzję dostępną do obliczeń, ale spowodowało to znacznie częstszy błąd.

 10
Author: Kaideejee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-21 02:03:47

Chcę przedstawić inne spojrzenie na pieniądze vs. liczbowe, w dużej mierze oparte na mojej własnej wiedzy i doświadczeniu... Moim punktem widzenia są tutaj pieniądze, ponieważ pracowałem z nimi przez długi czas i nigdy tak naprawdę nie używałem liczb...

MONEY Pro:

  • Natywny Typ Danych . Wykorzystuje natywny typ danych ( integer) tak samo jak rejestr procesora (32 lub 64 bit), więc obliczenia nie wymagają niepotrzebnego obciążenia, więc jest mniejszy i szybciej ... Pieniądze potrzebują 8 bajtów, a numeryczne (19, 4) 9 bajtów (12,5% większe)...

    Pieniądze są szybsze, o ile są używane do tego, aby były przeznaczone (jako pieniądze). Jak szybko? Mój prosty SUM test na 1 milionie danych pokazuje, że pieniądze to 275 ms, a numeryczne 517 ms... To jest prawie dwa razy szybciej ... Dlaczego Sum test? Zobacz następny Pro punkt

  • Najlepsze Dla Pieniędzy . Pieniądze są najlepsze do przechowywania pieniędzy i wykonywania operacji, na przykład w księgowości. Single raport może uruchomić miliony dodatków (suma) i kilka mnożenia po operacji sumy. W przypadku bardzo dużych aplikacji księgowych jest ona [11]} prawie dwa razy szybsza [12]} i jest niezwykle istotna...
  • niska precyzja pieniądza . Pieniądze w prawdziwym życiu nie muszą być bardzo precyzyjne. To znaczy, wiele osób może dbać o 1 cent USD, ale co powiesz na 0.01 cent USD? Faktycznie, w moim kraju banki już nie dbają o centy (cyfra po przecinku); Nie wiem o nas bank lub inny kraj...

Money Con:

  • Ograniczona Precyzja . Pieniądz ma tylko cztery cyfry (po przecinku), więc musi zostać przeliczony przed wykonaniem operacji takich jak podział... Ale z drugiej strony money nie musi być tak precyzyjny i ma być używany jako pieniądze, a nie tylko liczba...
Ale... Duże, ale tutaj jest nawet aplikacja zaangażowane prawdziwe pieniądze, ale nie używać go w wielu operacji sumy, jak w księgowości. W przypadku stosowania dużo podziałów i mnożenia zamiast tego nie powinieneś używać pieniędzy...
 5
Author: Susilo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-21 16:28:29

Nie powinieneś używać pieniędzy, gdy musisz mnożyć / dzielić wartość. Pieniądze są przechowywane w ten sam sposób, w jaki przechowywana jest liczba całkowita, podczas gdy dziesiętny jest przechowywany jako punkt dziesiętny i cyfry dziesiętne. Oznacza to, że pieniądze w większości przypadków spadną dokładność, podczas gdy dziesiętny zrobi to tylko po konwersji z powrotem do pierwotnej skali. Pieniądz jest punktem stałym, więc jego skala nie zmienia się podczas obliczeń. Jednak ponieważ jest to punkt stały, gdy zostanie wydrukowany jako ciąg dziesiętny (jako w przeciwieństwie do stałej pozycji w ciągu Bazy 2), wartości do skali 4 są reprezentowane dokładnie. Więc do dodawania i odejmowania, pieniądze są w porządku.

Dziesiętny jest reprezentowany wewnętrznie w bazie 10, a zatem pozycja punktu dziesiętnego jest również oparta na bazie 10. Co sprawia, że jego część ułamkowa reprezentuje dokładnie jego wartość, tak jak w przypadku pieniędzy. Różnica polega na tym, że wartości pośrednie dziesiętne mogą utrzymać dokładność do 38 cyfr.

Z pływającym liczba punktowa, wartość jest przechowywana w postaci binarnej tak, jakby była liczbą całkowitą, a pozycja dziesiętna (lub binarna) punktu jest względem bitów reprezentujących liczbę. Ponieważ jest to binarny punkt dziesiętny, liczba bazowa 10 traci dokładność zaraz po punkcie dziesiętnym. 1/5, lub 0.2, nie może być przedstawiony dokładnie w ten sposób. Ani pieniądze, ani dziesiętne nie cierpią z tego ograniczenia.

Łatwo jest przeliczyć pieniądze na dziesiętne, wykonać obliczenia, a następnie zapisać wynikowa wartość z powrotem do pola pieniędzy lub zmiennej.

Z mojego POV, chcę rzeczy, które przydarzają się liczbom, po prostu się zdarzają, bez konieczności poświęcania im zbyt wiele myśli. Jeśli wszystkie obliczenia mają zostać przekonwertowane na dziesiętne, to dla mnie Chciałbym po prostu użyć dziesiętnego. Zachowałbym pole pieniędzy na cele wystawowe.

Pod względem wielkości nie widzę wystarczającej różnicy, by zmienić zdanie. Pieniądze zajmują 4-8 bajtów, podczas gdy dziesiętne mogą wynosić 5, 9, 13 i 17. 9 bajtów może pokryć cały zakres, że 8 bajtów pieniędzy może. Pod względem indeksowym (porównywanie i wyszukiwanie powinno być porównywalne).

 2
Author: Gerard ONeill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-18 19:10:35

Znalazłem powód, aby używać dziesiętnego zamiast pieniędzy w temacie dokładności.

DECLARE @dOne   DECIMAL(19,4),
        @dThree DECIMAL(19,4),
        @mOne   MONEY,
        @mThree MONEY,
        @fOne   FLOAT,
        @fThree FLOAT

 SELECT @dOne   = 1,
        @dThree = 3,    
        @mOne   = 1,
        @mThree = 3,    
        @fOne   = 1,
        @fThree = 3

 SELECT (@dOne/@dThree)*@dThree AS DecimalResult,
        (@mOne/@mThree)*@mThree AS MoneyResult,
        (@fOne/@fThree)*@fThree AS FloatResult
Po prostu przetestuj i podejmij decyzję.
 1
Author: QMaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-21 11:49:00

Właśnie zobaczyłem ten wpis na blogu: pieniądze a dziesiętne w SQL Server.

Co w zasadzie mówi, że pieniądze mają problem z precyzją...
declare @m money
declare @d decimal(9,2)

set @m = 19.34
set @d = 19.34

select (@m/1000)*1000
select (@d/1000)*1000

Dla typu money Otrzymasz 19.30 zamiast 19.34. Nie jestem pewien, czy istnieje scenariusz aplikacji, który dzieli pieniądze na części 1000 do obliczeń, ale ten przykład ujawnia pewne ograniczenia.

 0
Author: Harsha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-21 16:18:23

Wszystkie poprzednie posty przynoszą ważne punkty, ale niektóre nie odpowiadają dokładnie na pytanie.

Pytanie brzmi: Dlaczego ktoś wolałby pieniądze, skoro już wiemy, że są mniej precyzyjnym typem danych i mogą powodować błędy, jeśli są używane w złożonych obliczeniach?

Używasz pieniędzy, gdy nie chcesz wykonywać skomplikowanych obliczeń i możesz wymienić tę precyzję na inne potrzeby.

Na przykład, gdy nie musisz wykonywać powyższych obliczeń i musisz zapisać 1 bajt (pieniądze zajmują 8 bajtów i decimal (19,4) zajmuje 9 bajtów).

Kolejny przykład, kiedy nie musisz wykonywać powyższych obliczeń i potrzebujesz szybkości przetwarzania ogromnej ilości danych.

Kolejny przykład, gdy nie musisz wykonywać powyższych obliczeń i musisz importować z prawidłowych ciągów tekstowych waluty. Spróbuj zrobić to z innymi typami liczbowymi: wybierz Konwertuj (pieniądze, '$1,000.68')

 0
Author: Weber K.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-22 22:35:41