Kiểu dữ liệu tốt nhất để lưu trữ giá trị tiền tệ trong cơ sở dữ liệu MySQL


Câu trả lời:


227

Một cái gì đó như Decimal(19,4)thường hoạt động khá tốt trong hầu hết các trường hợp. Bạn có thể điều chỉnh tỷ lệ và độ chính xác để phù hợp với nhu cầu của các số bạn cần lưu trữ. Ngay cả trong SQL Server, tôi có xu hướng không sử dụng " money" vì nó không chuẩn.


52
Một điểm về kích thước: theo MSDN ( msdn.microsoft.com/en-us/l Library / ms187746.aspx), Decimal (10,4) và Decimal (19,4) đều sử dụng 9 byte dung lượng lưu trữ, vì vậy có thể như cũng mùa xuân cho thêm 9 chữ số của quy mô.
Adam Nofsinger

1
Bài viết MSDN là về SQL Server nhưng câu hỏi là về MySQL. (Tôi đã gặp các nhà phát triển nghĩ rằng cả hai đều giống nhau nên tốt nhất để rõ ràng.)
cja

5
Lợi ích của việc sử dụng (19,4)thay vì là (19,2)gì?
ry Bổ trợ

1
Lợi ích của tôi là điều này .. Tôi cần tất cả các hàng trong bảng của mình bằng một số tiền cụ thể. Giả sử số tiền đó là $ 10,00. Khi hàng mới được thêm vào, mỗi hàng thay đổi số lượng. Nếu có 3 hàng trong bảng. 10/3 = 3.3333333333 ... nhưng chỉ với 2 số thập phân, chúng được lưu trữ là 3,33. Vì vậy, khi bạn tổng hợp những thứ đó lên, 3,33 + 3,33 + 3,33 = 9,99. Chúng tôi mất một xu! Thậm chí còn tệ hơn trên một tập dữ liệu lớn hơn. Lưu trữ ở 19,4 và tổng số tổng của bạn, sau đó làm tròn sản lượng thành 19,2 ..
Rick

49

Điều duy nhất bạn phải coi chừng là nếu bạn di chuyển từ cơ sở dữ liệu này sang cơ sở dữ liệu khác, bạn có thể thấy rằng DECIMAL (19,4) và DECIMAL (19,4) có nghĩa là những thứ khác nhau

( http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html )

    DBASE: 10,5 (10 số nguyên, 5 số thập phân)
    MYSQL: 15,5 (15 chữ số, 10 số nguyên (15-5), 5 thập phân)

Liên kết bây giờ đã chết, thật không may.
Marco Aurélio Deleu

1
@ MarcoAurélioDeleu - Tôi đã thay đổi liên kết để trỏ đến trang trên Wayback Machine, vì vậy bạn có thể thấy nó được nhìn lại vào năm 2009.
Tony

17

Nó cũng quan trọng để tìm ra có bao nhiêu vị trí thập phân có thể cần thiết cho tính toán của bạn.

Tôi đã làm việc trên một ứng dụng giá cổ phiếu yêu cầu tính toán giá của một triệu cổ phiếu. Giá cổ phiếu được trích dẫn phải được lưu trữ đến 7 chữ số chính xác.


7
Đó là một điểm tốt - đặc biệt là trong các ứng dụng tài chính, "giá" chắc chắn không bao hàm "tiền"
Mike Woodhouse

17

Phản ứng của Assaf về

Phụ thuộc vào số tiền bạn có ...

Nghe có vẻ thiếu sót, nhưng thực ra nó rất hay.

Chỉ hôm nay chúng tôi mới gặp sự cố khi một bản ghi không được chèn vào bảng Tỷ lệ của chúng tôi, vì một trong các cột (GrossRate) được đặt thành Decimal (11,4) và bộ phận Sản phẩm của chúng tôi vừa có hợp đồng cho các phòng trong một khu nghỉ mát tuyệt vời ở Bora Bora, nơi bán với giá vài triệu Franc Thái Bình Dương mỗi đêm ... một thứ không bao giờ được chống lại khi lược đồ cơ sở dữ liệu được thiết kế 10 năm trước.


2
Đó là lý do tại sao tôi đề nghị thập phân (19,4). Nghe có vẻ quá mức cần thiết, nhưng bạn không bao giờ biết khi nào bạn sẽ cần lưu trữ một lượng thực sự lớn trong lĩnh vực đó.
Kibbee

2
@Kibbee: Tôi sẽ không đồng ý với bạn về các yêu cầu của chúng tôi cho đến hôm nay. (Trong 6 năm (11,4) là hoàn toàn ổn ...)
Scott Ferguson

@Kibbee Điều này nghe giống như meme 640 Kb :)
Nikita Bosik

13

Đối với các ứng dụng kế toán, việc lưu trữ các giá trị dưới dạng số nguyên là rất phổ biến (một số thậm chí còn đi xa hơn khi nói đó là cách duy nhất). Để có ý tưởng, hãy lấy số lượng giao dịch (giả sử 100,23 đô la) và nhân với 100, 1000, 10000, v.v. để có được độ chính xác bạn cần. Vì vậy, nếu bạn chỉ cần lưu trữ xu và có thể làm tròn lên hoặc xuống một cách an toàn, chỉ cần nhân với 100. Trong ví dụ của tôi, điều đó sẽ tạo ra 10023 làm số nguyên để lưu trữ. Bạn sẽ tiết kiệm không gian trong cơ sở dữ liệu và so sánh hai số nguyên là nhiều dễ dàng hơn so với hai phao. 0,02 đô la của tôi.


Làm thế nào để bạn lưu trữ 6.125 (6/8)?
PeterToTheThứ ba

Tôi đoán anh ấy sẽ lưu trữ nó dưới dạng một số nguyên 6125.
Jimmy Knoot

2
Làm thế nào điều này sẽ tốt hơn DECIMAL? Bạn cần phải rất cẩn thận về việc luôn dịch đồng xu, nhà máy hoặc millrays sang đô la vào những thời điểm thích hợp.

Tôi đã đọc rằng hiệu suất thường nhanh hơn với INT so với DECIMAL, ngay cả trong các phiên bản mới nhất của MySQL. Cũng dễ dàng hơn khi bạn cần đưa các giá trị này vào PHP hoặc một cái gì đó và so sánh các giá trị.
Dane Bendixen

9

nhập cảnh siêu muộn nhưng GAAP là một quy tắc tốt ..

Nếu ứng dụng của bạn cần xử lý các giá trị tiền lên tới một nghìn tỷ thì điều này sẽ hoạt động: 13,2 Nếu bạn cần tuân thủ GAAP (Nguyên tắc kế toán được chấp nhận chung) thì hãy sử dụng: 13,4

Thông thường, bạn nên tính tổng giá trị tiền của mình ở mức 13,4 trước khi làm tròn sản lượng thành 13,2.

Nguồn: Kiểu dữ liệu tốt nhất để lưu trữ giá trị tiền tệ trong MySQL


5

Bạn có thể sử dụng một cái gì đó như DECIMAL(19,2)mặc định cho tất cả các giá trị tiền tệ của mình, nhưng nếu bạn chỉ lưu trữ các giá trị thấp hơn 1.000 đô la, điều đó sẽ lãng phí không gian cơ sở dữ liệu có giá trị.

Đối với hầu hết các triển khai, DECIMAL(N,2)sẽ là đủ, trong đó giá trị của Nít nhất là số chữ số trước .tổng số lớn nhất bạn từng mong muốn được lưu trữ trong trường đó + 5. Vì vậy, nếu bạn không bao giờ mong đợi lưu trữ bất kỳ giá trị nào lớn hơn 999999,99, DECIMAL(11,2)thì quá đủ (cho đến khi kỳ vọng thay đổi).

Nếu bạn muốn tuân thủ GAAP , bạn có thể đi theo DECIMAL(N,4), trong đó giá trị của Nít nhất là số chữ số trước .tổng số lớn nhất bạn từng mong muốn được lưu trữ trong trường đó + 7.


3

Nó phụ thuộc vào bản chất của dữ liệu. Bạn cần phải chiêm ngưỡng nó trước.

Trường hợp của tôi

  • số thập phân (13,4) không dấu để ghi lại các giao dịch tiền
    • lưu trữ hiệu quả (dù sao 4 byte cho mỗi bên của dấu thập phân) 1
    • Tuân thủ GAAP
  • số thập phân (19,4) không dấu cho tổng hợp
    • chúng tôi cần nhiều không gian hơn cho tổng số nhiều giao dịch nhiều tỷ đồng
    • bán tuân thủ với loại dữ liệu tiền tệ của MS sẽ không bị tổn thương 2
    • nó sẽ chiếm nhiều dung lượng hơn trên mỗi bản ghi (11 byte - 7 trái & 4 phải), nhưng điều này tốt vì có ít bản ghi cho tổng hợp 1
  • số thập phân (10,5) cho tỷ giá hối đoái
    • chúng thường được trích dẫn với 5 chữ số hoàn toàn để bạn có thể tìm thấy các giá trị như 1.2345 & 12.345 nhưng không phải 12345.67890
    • nó là quy ước rộng rãi, nhưng không phải là một tiêu chuẩn được mã hóa (ít nhất là theo kiến ​​thức tìm kiếm nhanh của tôi)
    • bạn có thể đặt số thập phân (18,9) với cùng một bộ lưu trữ, nhưng các hạn chế kiểu dữ liệu là cơ chế xác thực tích hợp có giá trị

Tại sao (M, 4)?

  • có những loại tiền được chia thành một ngàn đồng xu
  • có các khoản tương đương tiền như "Unidad de Fermento", "CLF" được biểu thị bằng 4 chữ số thập phân quan trọng 3 , 4
  • nó tuân thủ GAAP

Đánh đổi

  • độ chính xác thấp hơn:
    • ít chi phí lưu trữ
    • tính toán nhanh hơn
    • rủi ro tính toán thấp hơn
    • sao lưu và khôi phục nhanh hơn
  • độ chính xác cao hơn:
    • khả năng tương thích trong tương lai (số có xu hướng tăng lên)
    • tiết kiệm thời gian phát triển (bạn sẽ không phải xây dựng lại một nửa hệ thống khi các giới hạn được đáp ứng)
    • giảm rủi ro sản xuất do độ chính xác lưu trữ không đủ

Tương thích cực

Mặc dù MySQL cho phép bạn sử dụng số thập phân (65,30), 31 cho tỷ lệ và 30 cho độ chính xác dường như là giới hạn của chúng tôi nếu chúng tôi muốn mở tùy chọn chuyển.

Tỷ lệ và độ chính xác tối đa trong RDBMS phổ biến nhất:

            Cân chính xác
Oracle 31 31
T-SQL 38 38
MySQL 65 30
PostgreSQL 131072 16383

6 , 7 , 8 , 9

Hợp lý cực độ

  1. Tại sao (27,4)?
    • bạn không bao giờ biết khi nào hệ thống cần lưu trữ đô la Zimbabwe

Tháng 9 năm 2015 Chính phủ Zimbabwe tuyên bố sẽ đổi đô la Zimbabwe lấy đô la Mỹ với tỷ giá từ 1 USD đến 35 triệu đô la Zimbabwe 5

Chúng tôi có xu hướng nói "ừ, chắc chắn ... tôi sẽ không cần những con số điên rồ đó". Chà, người Zimbabwe cũng từng nói như vậy. Cách đây không lâu.

Hãy tưởng tượng bạn cần ghi lại một giao dịch trị giá 1 triệu USD bằng đô la Zimbabwe (có thể là không thể xảy ra ngày hôm nay, nhưng ai biết điều này sẽ như thế nào sau 10 năm nữa?).

  1. (1 triệu USD) * (35 Quadrylion ZWL) = (10 ^ 6) * (35 * 10 ^ 15) = 35 * 10 ^ 21
  2. chúng tôi cần:
    • 2 chữ số để lưu trữ "35"
    • 21 chữ số để lưu trữ số không
    • 4 chữ số bên phải dấu thập phân
  3. điều này làm cho số thập phân (27,4) tiêu tốn của chúng tôi 15 byte cho mỗi mục nhập
  4. chúng tôi có thể thêm một chữ số ở bên trái mà không mất phí - chúng tôi có số thập phân (28,4) cho 15 byte
  5. Bây giờ chúng tôi có thể lưu trữ 10 triệu đô la giao dịch bằng USD được thể hiện bằng đô la Zimbabwe hoặc bảo đảm khỏi một cuộc đình công khác của lạm phát hiperinf, hy vọng sẽ không xảy ra

0

Mặc dù điều này có thể muộn, nhưng nó sẽ hữu ích cho người khác. Từ kinh nghiệm và nghiên cứu của tôi, tôi đã biết và chấp nhận thập phân (19, 6). Đó là khi làm việc với php và mysql. khi làm việc với số tiền lớn và tỷ giá hối đoái

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.