Przeczytałem, że powinienem użyć pieniądze, ale w dzisiejszym szybkim świecie może to już przestarzałe.Jakiego typu danych należy użyć do przechowywania wartości pieniężnych?
Co powinienem użyć?
Przeczytałem, że powinienem użyć pieniądze, ale w dzisiejszym szybkim świecie może to już przestarzałe.Jakiego typu danych należy użyć do przechowywania wartości pieniężnych?
Co powinienem użyć?
Nie, pieniądze powinny nadal działać.
Dlaczego powinien być money przestarzały? Wynosi on ponad 900 bilionów, setki razy więcej niż budżet rządu federalnego - jakie kwoty pieniędzy można ewentualnie przechowywać? -) (Przypuszczam, że być może Zimbabwe dollars może w końcu stanowić problem, ale wciąż resetowali go przez wielokrotności miliardy i biliony i kwietnia ubiegłego roku został ostatecznie zawieszony; używają dolarów lub innych walutach obcych teraz dla płatności & rachunkowość w Zimbabwe).
O ile maksymalna wielkość jest ważna, uważam, że dokładność dziesiętna jest równie ważna. Uważam, że IRS sugeruje, że pieniądze należy obliczyć do 4 miejsc po przecinku. Jaki rodzaj pieniędzy ma. –
Tak, 1 część na 10 000 - ale nie mogę uwierzyć, że PO mógł pomyśleć, że to będzie przestarzałe (przez co ...?), Więc domyśliłem się, że martwili się dużymi kwotami (gdyby nie dolary Zimbabwe) tak często resetowane, 900 bilionów z nich nie kupiłoby wykałaczki ;-). –
"To przekracza 900 bilionów, setki razy więcej niż budżet rządu federalnego ..." Ale jak to się ma do długu federalnego? : P –
Papuccino,
Nie polecam pieniądze typy i smallmoney chyba że jesteś pewien, że tylko arytmetyka masz zamiar zrobić, to dodawanie i odejmowanie. Jeśli masz do czynienia z kursami wymiany, procentami i tak dalej, ryzykujesz prawdziwe problemy z tymi typami.
Oto tylko jeden mały przykład pokazujący różnicę między używaniem pieniędzy, dziesiętnym i zmiennym w przypadku podziału. Można wymyślić przykłady, w których różnica jest znacznie bardziej dramatyczna.
declare @m1 money, @m2 money, @m3 money
declare @d1 decimal(19,4), @d2 decimal(19,4), @d3 decimal(19,4)
declare @f1 float, @f2 float, @f3 float;
set @m1 = 1.00;
set @m2 = 345.00;
set @m3 = @m1/@m2;
set @d1 = 1.00;
set @d2 = 345.00;
set @d3 = @d1/@d2;
set @f1 = 1.00;
set @f2 = 345.00;
set @f3 = @f1/@f2;
select @m3, @d3, @f3;
Wynik: 0,0028 0,0029 0,00289855072463768
W zależności od branży, mogą istnieć wytyczne lub przepisy, które pomogą Ci podjąć decyzję o odpowiednim typie danych. Nie ma jednej słusznej odpowiedzi.
Dodano Uwagi:
Masz rację, że pieniądze/pieniądze nie powinny być pieniądze, ale SQL Server (niewytłumaczalny) daje dokładnie taki wynik: typ pieniądze z ilorazu dwóch wartości pieniężnych. To jest fałszywe, ale jak widać z poniższym przykładzie jest to, co masz, mimo że nie ma sensu:
declare @m1 money, @m2 money;
declare @d1 decimal(19,4), @d2 decimal(19,4);
set @m1 = 1.00;
set @m2 = 345.00;
set @d1 = 1.00;
set @d2 = 345.00;
select @m1/@m2, @d1/@d2
Wynik: 0,0028 0.0028985507246376811
Wynik z typu pieniędzy, 0,0028, IS 3-4% mniej niż poprawny wynik.
Oczywiście istnieje wiele sytuacji, w których trzeba podzielić wartości walut. Niebezpieczeństwo korzystania z rodzaju pieniędzy jest takie, że iloraz jest niewłaściwy (i odpowiedź nie jest wystarczająco zbliżona do właściwej). Przykłady pytań wymagających podziału waluty:
Załóżmy, że wymienisz 320 juanów, a bank daje 47,3 USD. Jaki jest kurs wymiany, który otrzymałeś?
Załóżmy, że zainwestujesz 23 USD, a rok później 31 USD. Jaka jest twoja procentowa stopa zwrotu?
Oba te obliczenia wymagają dzielenia wartości walut.
Wierzę, że to jest fałszywy przykład ... Nie ma prawdziwego funta wprl gdzie byłbyś zobowiązany podzielić Pieniądze na Pieniądze i zdobyć Pieniądze jako outout. To nic nie znaczy ... To tak, jakby powiedzieć, że 3 gruszki/2 gruszki = 1,5 gruszki. To jest źle. Jednostki mają znaczenie. –
Zobacz moje dodane uwagi w odpowiedzi. –
Jeśli przeprowadzasz przeliczanie walut w warstwie bazy danych, to najmniejszy z problemów to wybór między int, float i decimal. – Anon
Zgadzam się, pieniądze podzielone przez pieniądze są nieprawdziwe. Ale pieniądze podzielone przez dni są prawdziwe. Jeśli dzielisz małe sumy pieniędzy przez liczbę dni, w których musisz wyłożyć koszty, najważniejsze jest, abyś obserwował to zjawisko.Przesyłam/konwertuję pieniądze, aby się uaktywnić, wykonuję obliczenia, zanim ostatecznie przechwycę wynik końcowy na typ danych pieniężnych. Mam nadzieję że to pomoże.
Zaskakuje mnie, że nikt wcześniej o tym nie wspominał.
money
ma 8 bajtów. decimal
to 5, 9, 13 lub 17 bajtów w zależności od precyzji (precyzja nie jest cyfrą dziesiętną po kropce dziesiętnej, jest to maksymalna całkowita liczba cyfr dziesiętnych, które będą przechowywane, zarówno po lewej, jak i po prawej stronie kropki dziesiętnej). Aby więc naśladować zakres wartości obsługiwanych przez money
(-922,337,203,685,477.5808 do 922,337,203,685,477.5807), potrzebujesz decimal(19,4)
.
+-------------------+---------------+
| decimal precision | Storage bytes |
+-------------------+---------------+
| 1 - 9 | 5 |
| 10-19 | 9 |
| 20-28 | 13 |
| 29-38 | 17 |
+-------------------+---------------+
Jeśli przechowywania 9 bajtów zamiast 8 nie wydaje się nic wielkiego, należy pamiętać, że money
jest rodowitym typ procesora, jak 64-bit bigint
, ale decimal
nie jest. Oznacza to, że sumowanie miliardów wartości money
będzie szybsze niż sumowanie wartości decimal
. Wykonanie innych obliczeń, takich jak podział, miałoby jeszcze większą różnicę.
Na mojej wirtualnej maszynie z programem SQL Server 2014 Express uruchomiłem ten prosty test. dbo.Numbers
to tabela z 10.000 wierszy z jedną kolumną int
o wartości od 1 do 10 000.
CREATE TABLE [dbo].[Numbers](
[Number] [int] NOT NULL,
CONSTRAINT [PK_Numbers] PRIMARY KEY CLUSTERED
(
[Number] ASC
))
wpadłem to w SQL Sentry Plan Explorer:
DECLARE @VarM money = 1234.5678;
SELECT
AVG(@VarM/N1.Number)
FROM
dbo.Numbers AS N1
CROSS JOIN dbo.Numbers AS N2
;
DECLARE @VarD decimal(19,4) = 1234.5678;
SELECT
AVG(@VarD/N1.Number)
FROM
dbo.Numbers AS N1
CROSS JOIN dbo.Numbers AS N2
;
plan wykonania jest taka sama dla obu zapytań (dobrze, istnieją różne niejawne konwersje Number
: do money
i decimal
), ale metę czas wynosi 15 sekund vs. 40 sekund. Jest to dla mnie bardzo zauważalne.
Oczywiście, trzeba wiedzieć, że money
ma tylko 4 miejsc po przecinku. Jeśli wykonujesz obliczenia, musisz znać typy (i ich pierwszeństwo, tj. Co jest domyślnie przekształcane w co) i upewnić się, że wyniki pośrednie są odpowiedniego typu, w razie potrzeby odrzucając operandy na odpowiednie typy. To ostrzeżenie dotyczy obliczeń dowolnych typów, a nie tylko money
. Kiedy podzielisz dwie wartości: int
, powinieneś wiedzieć, że wynik to int
i nie zdziw się, że 4/5 = 0
.
Pieniądze działają, ale ma problemy, takie jak przechowywanie 4 miejsc po przecinku, ale wydaje się, że przechowuje tylko 2, gdy wartości przechowywane są w całych centach ... – ErikE
co !!? Jeśli wartość jest w całych centach, są tylko dwa. –
Jeśli programista wstawi kilka wartości do kolumny "pieniądze", takich jak 'VALUES (12.34), (10.79), (18.43)', a następnie wybierze je, zobaczy te wartości jako wprowadzone, a nie jako '12.3400, 10.7900, 18.4300'. Jest to poważny problem, ponieważ pozwala mu sądzić, że typ danych "pieniądze" przechowuje tylko 2 miejsca dziesiętne. Następnie robi 'INSERT MyTable (PurchaseAmount) SELECT Akcje * PricePerShare' bez obcięcia do 2 miejsc po przecinku. Ups! Ponadto pieniądze można podzielić na pieniądze (chcę wydać 1000 USD na akcje o wartości 36 USD) i pomnożyć (chcę obliczyć odchylenie standardowe). – ErikE