Bạn nên chọn các kiểu dữ liệu TIỀN hoặc DECIMAL (x, y) trong SQL Server?


442

Tôi tò mò liệu có hay không có sự khác biệt thực sự giữa moneykiểu dữ liệu và một cái gì đó giống như decimal(19,4)(đó là những gì tiền sử dụng trong nội bộ, tôi tin).

Tôi biết rằng đó moneylà cụ thể cho SQL Server. Tôi muốn biết nếu có một lý do thuyết phục để chọn cái này hơn cái kia; hầu hết các mẫu SQL Server (ví dụ: cơ sở dữ liệu AdventureWorks) sử dụng moneyvà không sử dụng decimalcho những thứ như thông tin về giá.

Tôi có nên tiếp tục sử dụng kiểu dữ liệu tiền hay thay vào đó là lợi ích của việc sử dụng số thập phân? Tiền có ít ký tự để nhập, nhưng đó không phải là lý do hợp lệ :)


12
DECIMAL(19, 4) là một lựa chọn phổ biến, kiểm tra cái này cũng kiểm tra ở đây Định dạng tiền tệ thế giới để quyết định sử dụng bao nhiêu số thập phân, hy vọng sẽ giúp.
shaijut

Tôi tự hỏi tại sao loại dữ liệu tiền có 4 số thập phân .. chứ không phải 2. tức là 100 xu bằng một đô la nên chỉ cần 2 chữ số thập phân? Để lưu trữ một bản ghi số tiền ít hơn $ 9999,99, tôi sẽ sử dụng loại dữ liệu thập phân (6,2). Tôi không quan tâm đến việc chia hoặc nhân các phép tính, chỉ lưu trữ và tính tổng ..
Allan F

Câu trả lời:


326

Không bao giờ nên sử dụng tiền. Nó không chính xác, và nó là rác nguyên chất; luôn luôn sử dụng số thập phân / số.

Chạy cái này để xem ý tôi là gì:

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

Đầu ra: 2949.0000 2949,8525

Đối với một số người nói rằng bạn không chia tiền theo tiền:

Đây là một trong những truy vấn của tôi để tính toán tương quan và thay đổi điều đó thành tiền cho kết quả sai.

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

61
"Không bao giờ" là một từ mạnh mẽ. "Tiền" rất hữu ích để truyền kết quả cho loại đó để hiển thị cho người dùng theo cách nhạy cảm về văn hóa, nhưng bạn nói đúng là nó rất tệ khi sử dụng cho các phép tính.
Joel Coehoorn

36
Ví dụ của bạn không có ý nghĩa, vì không ai sẽ nhân hai đối tượng loại tiền. Nếu bạn muốn chứng minh quan điểm của mình, bạn cần so sánh nhân một số tiền với số thập phân với số thập phân với số thập phân.
Brian

27
.. nhưng vẫn còn khó hiểu tại sao tiền * tiền sẽ không có độ chính xác của tiền.
Học

4
@ Học: nó có độ chính xác của tiền. Tuy nhiên, bạn vẫn kết thúc với các lỗi làm tròn có thể tích lũy theo thời gian. Kiểu thập phân không sử dụng số học nhị phân: nó đảm bảo nó có cùng kết quả 10 cơ sở mà bạn sẽ làm khi làm nó trên giấy.
Joel Coehoorn

55
Nhân và chia của moneytrên moneysang một bên, này 'minh họa' là hấp dẫn. Đó là một thực tế được ghi nhận moneycó độ chính xác cố định và rất hạn chế. Trong những trường hợp như vậy, đầu tiên nên nhân lên, sau đó chia. Thay đổi thứ tự của các toán tử trong ví dụ này và bạn sẽ nhận được kết quả giống hệt nhau. Một moneybản chất là một int 64 bit, và nếu bạn đã xử lý ints, bạn sẽ nhân lên trước khi chia.
Andriy M

272

SQLMenace cho biết tiền không chính xác. Nhưng bạn không nhân / chia tiền với tiền! Bao nhiêu là 3 đô la 50 xu? 150 đô la? Bạn nhân / chia tiền theo vô hướng, nên là số thập phân.

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

Kết quả trong kết quả chính xác:

Moneyresult numresult
--------------------- ----------------------------- ----------
2949,8525 2949,8525

moneylà tốt miễn là bạn không cần nhiều hơn 4 chữ số thập phân và bạn chắc chắn rằng số vô hướng của mình - không đại diện cho tiền - là decimals.


57
một hóa đơn đô la có thể giúp bạn kiếm được bao nhiêu xu? một câu trả lời cho điều này đòi hỏi tiền / tiền.
Học

48
@ Học trong trường hợp đó kết quả không phải là tiền, mà là nổi. (Phân tích thứ nguyên cơ bản.)
Richard

11
@ Học: Bạn có hỏi cơ sở dữ liệu bao nhiêu xu một đô la không? Dù sao, điều đó sẽ trả lại kết quả đúng. Vấn đề của anh là tiền / tiền chỉ chính xác đến bốn chữ số (là 0,2949), sau đó khi nhân với 10000, nó trở thành 2949.0000.
cấu hình

26
@mson Anh ấy đúng và không đưa ra những lời chỉ trích cá nhân như bạn đã làm dựa trên một nhận xét một dòng, nó không hữu ích. Nếu anh ta không chia 0,01 đô la mà thay vào đó là 0,01, thì kết quả là 100 đô la thay vì 100. Có 100 xu bằng một đô la, không phải 100 đô la. Đơn vị rất quan trọng! Chắc chắn có một nơi lớn để lặn, và có thể nhân tiền, bằng tiền.
andrewb

19
Nếu tôi muốn chi 1000 đô la để mua cổ phiếu có giá 36 đô la, đó có phải là cách sử dụng hợp pháp money / moneykhông? Câu trả lời là toàn bộ các đơn vị không có ký hiệu đô la kèm theo, đó là chính xác! Đây là một kịch bản hoàn toàn hợp lý, cho thấy rằng do các trường hợp cạnh kỳ lạ như thế này, moneykhông phải là loại dữ liệu tốt để sử dụng, vì kết quả luôn bị cắt lại để phù hợp moneythay vì tuân theo các quy tắc thông thường về độ chính xác và tỷ lệ. Nếu bạn muốn tính độ lệch chuẩn của một tập hợp các moneygiá trị thì sao? Vâng, Sqrt(Sum(money * money))(đơn giản hóa) thực sự có ý nghĩa.
ErikE

59

Mọi thứ đều nguy hiểm nếu bạn không biết mình đang làm gì

Ngay cả các loại thập phân có độ chính xác cao cũng không thể lưu trong ngày:

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

1,000000 <- Nên là 0,6000000


Các moneyloại là số nguyên

Các đại diện văn bản của smallmoneydecimal(10,4)có thể trông giống nhau, nhưng điều đó không làm cho chúng có thể thay thế cho nhau. Bạn co rúm người khi nhìn thấy ngày được lưu trữ dưới dạng varchar(10)? Đây là điều tương tự.

Đằng sau hậu trường, money/ smallmoneychỉ là một bigint/ int Dấu thập phân trong biểu diễn văn bản moneylà lông tơ trực quan, giống như dấu gạch ngang trong một ngày yyyy-mm-dd. SQL không thực sự lưu trữ những thứ đó trong nội bộ.

Về decimalvs money, chọn bất cứ điều gì phù hợp với nhu cầu của bạn. Các moneyloại tồn tại vì lưu trữ giá trị kế toán dưới dạng bội số nguyên của 1/10000 đơn vị là rất phổ biến. Ngoài ra, nếu bạn đang xử lý tiền thực tế và các phép tính ngoài phép cộng và trừ đơn giản, bạn không nên làm điều đó ở cấp cơ sở dữ liệu! Thực hiện ở cấp ứng dụng với thư viện hỗ trợ Làm tròn Ngân hàng (IEEE 754)


1
Bạn có thể giải thích những gì đã xảy ra trong ví dụ này?
Serge Popov

4
Quy mô tràn. Ở quy mô nhỏ, số (a, b) * số (c, d) mang lại số (a-b + c-d + 1, max (b, d)). Tuy nhiên, nếu (a + b + c + d)> 38, SQL giới hạn tỷ lệ, cướp chính xác từ phía phân số để đệm phía số nguyên, gây ra lỗi làm tròn.
Anon

Tất cả các tính toán số dễ bị mất độ chính xác do tỷ lệ: thay vào đó, hãy chọn 1000000 * @ num1 * @ num2
Mitch Wheat

Ví dụ của Anon là phiên bản và cơ sở dữ liệu cụ thể. nhưng điểm cẩn thận là hợp lệ. trong phiên bản 1.1 của sqlanywhere, ví dụ này cung cấp chính xác 0.600000. (Tôi biết chúng ta đang nói về ms sql ở đây). một điểm khác về loại tiền bị thiếu trong cơ sở dữ liệu khác, có các cách gọi số thập phân hoặc số là tiền, chẳng hạn như tạo miền.
gg89

3
Tôi nghĩ rằng đây là câu trả lời sáng suốt nhất bởi vì bạn đã giải thích không chỉ đơn giản là các lỗi được truyền bá, mà là những gì thực sự xảy ra đằng sau hậu trường, và tại sao TIỀN lại tồn tại ngay từ đầu. Tôi không chắc tại sao phải mất 4 năm để có câu trả lời này, nhưng có lẽ đó là vì có quá nhiều sự tập trung vào "vấn đề" tính toán, và không quá nhiều về số tiền và số tiền so với số thập phân.
Steve Sether

44

Tôi nhận ra rằng WayneM đã tuyên bố rằng anh ta biết rằng tiền dành riêng cho SQL Server. Tuy nhiên, anh ta đang hỏi liệu có bất kỳ lý do nào để sử dụng tiền trên số thập phân hoặc ngược lại không và tôi nghĩ một lý do rõ ràng vẫn phải được nêu và đó là sử dụng số thập phân có nghĩa là một điều ít phải lo lắng hơn nếu bạn phải thay đổi DBMS của mình - điều đó có thể xảy ra.

Làm cho hệ thống của bạn linh hoạt nhất có thể!


1
Có thể, nhưng về lý thuyết, bạn có thể khai báo một tên miền có tên Money trong một DBMS khác (hỗ trợ khai báo tên miền).
người tranh luận

Là một người hiện đang chuyển đổi cơ sở dữ liệu SQL Server sang Amazon Redshift, tôi có thể xác nhận rằng đây là sự cố chính hãng. Cố gắng tránh các loại dữ liệu được đặt vào một nền tảng cơ sở dữ liệu cụ thể trừ khi có những lý do kinh doanh hợp lý để sử dụng chúng.
Nathan Griffiths

@Nathn đưa ra hệ thống loại yếu của Redshift so với PostgreSQL hoặc SQL Server, ví dụ như không có dateloại nào , tôi muốn nói rằng bạn sẽ luôn gặp vấn đề như vậy. Bạn nên nói "Không sử dụng các loại không dùng nữa khi cơ sở dữ liệu đã cung cấp các loại tốt hơn, tuân thủ tiêu chuẩn hơn và cảnh báo chống lại các loại không dùng nữa".
Panagiotis Kanavos

@PanagiotisKanavos - tiền không bị mất
Martin Smith

@MartinSmith đã sốc khi thấy điều này, vì nó thực sự không thể xử lý các giá trị tiền như BTC vào năm 2017. Hoặc phân biệt giữa số tiền GBP và EUR - mặc dù chúng chuyển sang ngang giá: P. Dù sao, chuyển sang Redshift mang đến nhiều nỗi đau
Panagiotis Kanavos

32

Vâng, tôi thích MONEY! Đó là một byte rẻ hơn DECIMALvà các tính toán thực hiện nhanh hơn bởi vì (dưới vỏ bọc) các phép toán cộng và trừ về cơ bản là các phép toán số nguyên. Ví dụ của SQLMenace là một cảnh báo tuyệt vời cho việc không biết rằng có thể áp dụng tương tự cho các INTví dụ, trong đó kết quả sẽ bằng không. Nhưng đó không phải là lý do để không sử dụng số nguyên mà phù hợp .

Vì vậy, nó hoàn toàn 'an toàn' và phù hợp để sử dụng MONEYkhi những gì bạn đang giải quyết MONEYvà sử dụng nó theo các quy tắc toán học mà nó tuân theo (giống như INTeger).

Sẽ tốt hơn nếu SQL Server thúc đẩy sự phân chia và nhân của MONEYs thành DECIMAL(hoặc FLOATs?) - có thể, nhưng họ đã không chọn làm điều này; họ cũng không chọn quảng bá INTcho người khác đến FLOATs khi chia chúng.

MONEYkhông có vấn đề chính xác; việc DECIMALcó một loại trung gian lớn hơn được sử dụng trong quá trình tính toán chỉ là một 'tính năng' của việc sử dụng loại đó (và tôi thực sự không chắc chắn rằng 'tính năng' đó kéo dài bao xa).

Để trả lời câu hỏi cụ thể, một "lý do thuyết phục"? Chà, nếu bạn muốn hiệu suất tối đa tuyệt đối ở một SUM(x)nơi xcó thể DECIMALhoặc MONEY, thì MONEYsẽ có lợi thế.

Ngoài ra, đừng quên người anh em họ nhỏ hơn, điều SMALLMONEYchỉnh 4 byte, nhưng nó tối đa hóa ở mức 214,748.3647- khá nhỏ đối với tiền ăn tiền và vì vậy thường không phù hợp.

Để chứng minh điểm xung quanh bằng cách sử dụng các loại trung gian lớn hơn, nếu bạn chỉ định rõ ràng trung gian cho một biến, thì cũng DECIMALgặp phải vấn đề tương tự:

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

Sản xuất 2950.0000(được, vì vậy, ít nhất là DECIMALđược làm tròn chứ không phải MONEYcắt ngắn giống như một số nguyên.)


21
MONEYlà một byte nhỏ hơn một lớn DECIMAL , với độ chính xác lên đến 19 chữ số. Tuy nhiên, hầu hết các tính toán tiền tệ trong thế giới thực (lên tới 9,99 đô la) có thể phù hợp với một DECIMAL(9, 2), chỉ cần năm byte. Bạn có thể lưu kích thước, bớt lo lắng về các lỗi làm tròn làm cho mã của bạn dễ mang theo hơn.

Mặc dù @Jonof ALLTrades là chính xác, bạn cũng có thể lấy lại hiệu suất số nguyên bằng cách sử dụng một số nguyên có chứa đồng xu hoặc xu và lưu byte bổ sung mã hóa vị trí của dấu thập phân và phải được kiểm tra khi cộng các số thập phân với nhau.
DSz

"Vì vậy, nó hoàn toàn 'an toàn' và phù hợp để sử dụng TIỀN khi những gì bạn đang giải quyết là TIỀN và sử dụng nó theo các quy tắc toán học tuân theo" -> tuy nhiên, hãy xem câu trả lời của Anon: "Mọi thứ đều nguy hiểm nếu bạn không biết những gì bạn đang làm ". Bạn không bao giờ có thể dự đoán cách mọi người sẽ truy vấn hệ thống bạn đang tạo, tốt nhất để tránh khả năng sử dụng sai khi bạn có thể. Thu được rất ít trong lưu trữ không đáng là IMHO.
Nathan Griffiths

1
Hãy thử lưu trữ một giá trị Bitcoin. Nó có 8 số thập phân
Panagiotis Kanavos

13

Chúng ta vừa gặp một vấn đề rất giống nhau và giờ đây tôi rất là +1 vì không bao giờ sử dụng Tiền ngoại trừ trong bản trình bày cấp cao nhất. Chúng tôi có nhiều bảng (hiệu quả là một chứng từ bán hàng và hóa đơn bán hàng), mỗi bảng chứa một hoặc nhiều trường Tiền vì lý do lịch sử và chúng tôi cần thực hiện một phép tính pro-rata để tính ra tổng số hóa đơn Thuế có liên quan đến mỗi dòng trên chứng từ bán hàng. Tính toán của chúng tôi là

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

Điều này dẫn đến việc tính toán tiền / tiền trong thế giới thực, gây ra lỗi quy mô trên phần phân chia, sau đó nhân lên thành một tỷ lệ không chính xác. Khi các giá trị này được thêm vào sau đó, chúng tôi sẽ kết thúc bằng một tỷ lệ tỷ lệ không cộng với tổng giá trị hóa đơn. Nếu một trong các giá trị trong ngoặc là một số thập phân (tôi sắp bỏ một trong số chúng như vậy) thì tỷ lệ vat sẽ chính xác.

Khi các dấu ngoặc không có ở đây ban đầu được sử dụng để làm việc, tôi đoán vì các giá trị lớn hơn có liên quan, nó đã mô phỏng hiệu quả ở quy mô cao hơn. Chúng tôi đã thêm dấu ngoặc vì nó thực hiện phép nhân trước tiên, trong một số trường hợp hiếm hoi thổi độ chính xác có sẵn cho phép tính, nhưng điều này hiện đã gây ra lỗi phổ biến hơn nhiều này.


8
Nhưng nó chỉ làm như vậy bởi vì một nhà phát triển không biết gì đã bỏ qua các quy tắc tính thuế VAT và các giới hạn chính xác được ghi lại bằng tiền.
TomTom

1
@TomTom nhưng điểm bạn đang đưa ra về khả năng sử dụng sai loại dữ liệu này là một đối số có lợi cho việc tránh sử dụng nó.
Nathan Griffiths

@Nathan Không. Tôi chỉ ra rằng đối số được đưa ra như một lý do để không bao giờ sử dụng nó về cơ bản là nhà phát triển không đủ năng lực, vì vậy đối số là không có thật.
TomTom

1
@TomTom thật đáng buồn là có nhiều nhà phát triển không đủ năng lực (cũng như nhiều người tuyệt vời) và đối với tôi, trừ khi tôi có thể đảm bảo dữ liệu này sẽ được truy vấn trong tương lai và không ai sẽ mắc phải những sai lầm được mô tả ở đây , tốt hơn để sai ở phía thận trọng và sử dụng một loại thập phân. Điều đó nói rằng, khi đọc tất cả các câu trả lời này, tôi có thể thấy có một số trường hợp sử dụng cụ thể trong đó tiền sẽ là loại tối ưu để sử dụng, tôi sẽ không sử dụng trừ khi có trường hợp sử dụng rất tốt cho nó (ví dụ: cột sẽ chỉ bao giờ được tổng hợp bởi SUM, tải số lượng lớn dữ liệu tài chính).
Nathan Griffiths

@TomTom không chỉ là giới hạn chính xác. Các đại diện nội bộ cũng có thể gây ra vấn đề. Tiền là một loại tiện lợi để bắt các nhà phát triển không biết gì, không phải là một loại tuyệt vời mà các nhà phát triển đang lạm dụng. Ví dụ vat, bất kể các quy tắc để tính toán nó, rõ ràng sẽ khiến các nhà phát triển không biết gì tránh xa khi họ áp dụng cụ thể cho chung.
Gerard ONeill

12

Như một điểm đối với lực đẩy chung của các câu trả lời khác. Xem nhiều lợi ích của loại dữ liệu tiền Money! trong Hướng dẫn về công cụ quan hệ của SQLCAT

Cụ thể tôi sẽ chỉ ra những điều sau đây

Làm việc trên các triển khai của khách hàng, chúng tôi đã tìm thấy một số con số hiệu suất thú vị liên quan đến loại dữ liệu tiền. Ví dụ: khi Dịch vụ phân tích được đặt thành loại dữ liệu tiền tệ (từ gấp đôi) để khớp với loại dữ liệu tiền của SQL Server, tốc độ xử lý (hàng / giây) được cải thiện 13%. Để có được hiệu suất nhanh hơn trong Dịch vụ tích hợp máy chủ SQL (SSIS) để tải 1,18 TB trong vòng ba mươi phút, như đã lưu ý trong SSIS 2008 - hiệu suất ETL kỷ lục thế giới, người ta đã quan sát thấy việc thay đổi bốn cột thập phân (9,2) với kích thước là 5 byte trong bảng LINECEM của TPC-H thành tiền (8 byte) đã cải thiện tốc độ chèn hàng loạt thêm 20% ... Lý do cho sự cải thiện hiệu suất là do giao thức Luồng dữ liệu dạng bảng (TDS) của SQL Server, có nguyên tắc thiết kế chính để truyền dữ liệu ở dạng nhị phân nhỏ gọn và càng gần với định dạng lưu trữ nội bộ của SQL Server. Theo kinh nghiệm, điều này đã được quan sát trong SSIS 2008 - thử nghiệm hiệu suất ETL kỷ lục thế giới bằng cách sử dụng Kernrate; giao thức giảm đáng kể khi loại dữ liệu được chuyển sang tiền từ số thập phân. Điều này làm cho việc chuyển dữ liệu hiệu quả nhất có thể. Một kiểu dữ liệu phức tạp cần phân tích cú pháp và chu kỳ CPU bổ sung để xử lý hơn kiểu chiều rộng cố định.

Vì vậy, câu trả lời cho câu hỏi là "nó phụ thuộc". Bạn cần cẩn thận hơn với các thao tác số học nhất định để duy trì độ chính xác nhưng bạn có thể thấy rằng các cân nhắc về hiệu suất làm cho điều này đáng giá.


Làm thế nào bạn sẽ lưu trữ bitcoin sau đó?
Panagiotis Kanavos

@PanagiotisKanavos - Tôi không biết nữa. Tôi chưa bao giờ nhìn vào bitcoin và thực tế không biết gì về nó!
Martin Smith

6

Tôi muốn đưa ra một cái nhìn khác về TIỀN so với SỐ, chủ yếu dựa vào chuyên môn và kinh nghiệm của riêng tôi ... Quan điểm của tôi ở đây là TIỀN, vì tôi đã làm việc với nó trong một thời gian dài và chưa bao giờ thực sự sử dụng SỐ MỘT .. .

KIẾM TIỀN:

  • Kiểu dữ liệu gốc . Nó sử dụng kiểu dữ liệu riêng ( số nguyên ) giống như thanh ghi CPU (32 hoặc 64 bit), vì vậy phép tính không cần chi phí không cần thiết để nó nhỏ hơnnhanh hơn ... TIỀN cần 8 byte và SỐ (19, 4 ) cần 9 byte (lớn hơn 12,5%) ...

    TIỀN nhanh hơn miễn là nó được sử dụng cho nó có nghĩa là (như tiền). Nhanh như thế nào? SUMThử nghiệm đơn giản của tôi trên 1 triệu dữ liệu cho thấy TIỀN là 275 ms và NUMERIC 517 ms ... Nhanh gấp đôi ... Tại sao thử nghiệm SUM? Xem điểm Pro tiếp theo

  • Tốt nhất cho tiền . TIỀN là tốt nhất để lưu trữ tiền và thực hiện các hoạt động, ví dụ, trong kế toán. Một báo cáo có thể chạy hàng triệu bổ sung (SUM) và một vài phép nhân sau khi thao tác SUM được thực hiện. Đối với các ứng dụng kế toán rất lớn, nó nhanh gần gấp đôi và nó cực kỳ quan trọng ...
  • Độ chính xác thấp của tiền . Tiền trong cuộc sống thực không cần phải rất chính xác. Ý tôi là, nhiều người có thể quan tâm khoảng 1 cent USD, nhưng khoảng 0,01 cent USD thì sao? Trên thực tế, ở nước tôi, các ngân hàng không còn quan tâm đến xu (chữ số sau dấu phẩy thập phân); Tôi không biết về ngân hàng Hoa Kỳ hoặc quốc gia khác ...

KIẾM TIỀN:

  • Độ chính xác hạn chế . TIỀN chỉ có bốn chữ số (sau dấu phẩy), do đó, nó phải được chuyển đổi trước khi thực hiện các thao tác như chia ... Nhưng một lần nữa money, không cần phải chính xác và được sử dụng như tiền, không chỉ là một con số...

Nhưng ... Lớn, nhưng đây thậm chí là ứng dụng của bạn liên quan đến tiền thật, nhưng không sử dụng nó trong nhiều hoạt động SUM, như trong kế toán. Thay vào đó, nếu bạn sử dụng nhiều phép chia và phép nhân thì bạn không nên sử dụng TIỀN ...


1
Nếu bạn định nói rằng tiền nhanh hơn số thập phân, bạn cần cho chúng tôi biết những thứ như rdbms, trên phần cứng nào, chạy HĐH nào, với dữ liệu cụ thể nào đang chạy truy vấn cụ thể mà bạn đang nói đến. Hơn nữa, nếu nó không HOÀN TOÀN chính xác, tôi KHÔNG thực hiện bất kỳ hoạt động tài chính nào với nó, bởi vì nhân viên thuế sẽ khá khó chịu khi nhận lại số xấu. Bạn quan tâm đến hàng nghìn xu nếu bạn đang giao dịch với tiền Mỹ chẳng hạn. Nếu tiền không làm điều đó, nó không thể sử dụng được.
Haakon Løtveit

3
@ HaakonLøtveit toàn bộ chủ đề Hỏi & Đáp này là về kiểu dữ liệu "tiền" của SQL Server, vì vậy tôi không nghĩ họ cần chỉ định điều này trong câu trả lời. Tiền có thể được sử dụng nhanh hơn số thập phân trong một số trường hợp (ví dụ: tải dữ liệu), xem câu trả lời của Martin Smith để biết thêm chi tiết. Tôi đồng ý với phần lớn câu trả lời này, trong đó có một số trường hợp sử dụng nhất định có thể khiến Tiền trở thành lựa chọn hiệu quả hơn thập phân, tuy nhiên trừ khi có trường hợp rất hấp dẫn khi sử dụng, tôi nghĩ nên tránh.
Nathan Griffiths

1
Bitcoin có 8 số thập phân. Bạn thậm chí không thể lưu trữ nó trong một moneycột
Panagiotis Kanavos

4

Tất cả các bài viết trước mang lại điểm hợp lệ, nhưng một số không trả lời chính xác câu hỏi.

Câu hỏi là: Tại sao ai đó thích tiền hơn khi chúng ta đã biết đây là loại dữ liệu ít chính xác hơn và có thể gây ra lỗi nếu được sử dụng trong các phép tính phức tạp?

Bạn sử dụng tiền khi bạn không thực hiện các phép tính phức tạp và có thể đánh đổi độ chính xác này cho các nhu cầu khác.

Ví dụ: khi bạn không phải thực hiện các tính toán đó và cần nhập dữ liệu từ các chuỗi văn bản tiền tệ hợp lệ. Chuyển đổi tự động này chỉ hoạt động với loại dữ liệu TIỀN:

SELECT CONVERT(MONEY, '$1,000.68')

Tôi biết bạn có thể tạo thói quen nhập khẩu của riêng bạn. Nhưng đôi khi bạn không muốn tạo lại thói quen nhập với các định dạng ngôn ngữ cụ thể trên toàn thế giới.

Một ví dụ khác, khi bạn không phải thực hiện các phép tính đó (bạn chỉ cần lưu trữ một giá trị) và cần lưu 1 byte (tiền mất 8 byte và thập phân (19,4) mất 9 byte). Trong một số ứng dụng (CPU nhanh, RAM lớn, IO chậm), như chỉ cần đọc lượng dữ liệu khổng lồ, điều này cũng có thể nhanh hơn.


2

Bạn không nên sử dụng tiền khi bạn cần nhân / chia trên giá trị. Tiền được lưu trữ giống như cách một số nguyên được lưu trữ, trong khi số thập phân được lưu trữ dưới dạng dấu thập phân và chữ số thập phân. Điều này có nghĩa là tiền sẽ giảm độ chính xác trong hầu hết các trường hợp, trong khi thập phân sẽ chỉ làm như vậy khi được chuyển đổi trở lại quy mô ban đầu. Tiền là điểm cố định, vì vậy quy mô của nó không thay đổi trong quá trình tính toán. Tuy nhiên, vì đó là điểm cố định khi nó được in dưới dạng chuỗi thập phân (trái ngược với vị trí cố định trong chuỗi cơ sở 2), các giá trị lên tới thang 4 được thể hiện chính xác. Vì vậy, để cộng và trừ, tiền là tốt.

Một số thập phân được biểu thị trong cơ sở 10 bên trong và do đó, vị trí của dấu thập phân cũng dựa trên số 10 cơ sở. Điều này làm cho phần phân số của nó thể hiện chính xác giá trị của nó, giống như với tiền. Sự khác biệt là các giá trị trung gian của số thập phân có thể duy trì độ chính xác lên tới 38 chữ số.

Với số dấu phẩy động, giá trị được lưu trữ dưới dạng nhị phân như thể nó là một số nguyên và vị trí của điểm thập phân (hoặc nhị phân, ahem) có liên quan đến các bit đại diện cho số. Vì là dấu thập phân nhị phân, 10 số cơ sở mất độ chính xác ngay sau dấu thập phân. 1/5 hoặc 0,2, không thể được trình bày chính xác theo cách này. Cả tiền và thập phân đều không bị giới hạn này.

Thật dễ dàng để chuyển đổi tiền thành số thập phân, thực hiện các tính toán và sau đó lưu trữ giá trị kết quả trở lại vào một trường hoặc biến tiền.

Từ POV của tôi, tôi muốn những thứ xảy ra với những con số chỉ xảy ra mà không cần phải suy nghĩ quá nhiều về chúng. Nếu tất cả các tính toán sẽ được chuyển đổi thành số thập phân, thì với tôi tôi chỉ muốn sử dụng số thập phân. Tôi sẽ tiết kiệm trường tiền cho mục đích hiển thị.

Kích thước khôn ngoan Tôi không thấy đủ sự khác biệt để thay đổi suy nghĩ của mình. Tiền mất 4 - 8 byte, trong khi số thập phân có thể là 5, 9, 13 và 17. 9 byte có thể bao gồm toàn bộ phạm vi mà 8 byte tiền có thể. Index-khôn ngoan (so sánh và tìm kiếm nên được so sánh).


Cảm ơn các Upvote. Tôi đang xem xét điều này và trong khi tôi nhận được những gì tôi đang cố nói, tôi cũng có thể thấy nó rất khó hiểu. Có lẽ tôi sẽ viết lại nó sau với một số ví dụ so với số thập phân.
Gerard ONeill

2

Tôi tìm thấy một lý do về việc sử dụng số thập phân hơn tiền trong chủ đề chính xác.

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

DecimalResult> 1.000000

MoneyResult> 0,9999

FloatResult> 1

Chỉ cần kiểm tra nó và đưa ra quyết định của bạn.


2
Chúng tôi rất muốn nghe (đọc, đó là) kết luận của bạn .
Peter Mortensen

@PeterMortensen Tôi nghĩ rằng nếu tôi muốn có sự hoàn chỉnh và chính xác giữa các loại Tiền và Số thập phân thì quyết định của tôi phải là Số thập phân.
QMaster

1
Xem xét cập nhật câu trả lời của bạn với kết quả thực tế ở trên. Sau đó, kết luận của bạn sẽ rõ ràng ngay lập tức đối với bất kỳ ai đang đọc :-)
Agreax

1
@Ageax Kết quả được thêm vào câu trả lời.
QMaster

1

Tôi vừa thấy mục blog này: Tiền so với số thập phân trong SQL Server .

Về cơ bản nói rằng tiền có vấn đề chính xác ...

declare @m money
declare @d decimal(9,2)

set @m = 19.34
set @d = 19.34

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

Đối với moneyloại, bạn sẽ nhận được 19,30 thay vì 19,34. Tôi không chắc chắn nếu có một kịch bản ứng dụng chia tiền thành 1000 phần để tính toán, nhưng ví dụ này không phơi bày một số hạn chế.


15
Đây không phải là "vấn đề", đó là "theo thông số kỹ thuật": «Các loại dữ liệu moneysmallmoneychính xác đến một phần mười đơn vị tiền tệ mà chúng đại diện.» như đã nói trong msdn.microsoft.com/en-us/l Library / ms179882.aspx vì vậy bất cứ ai nói "đó là rác rưởi" không biết anh ấy đang nói về cái gì.
Albireo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.