NUMERIC
/ DECIMAL
Như Joachim Isaksson đã nói
, bạn muốn sử dụng NUMERIC
/ DECIMAL
loại, như một loại chính xác tùy ý.
Hai điểm quan trọng về NUMERIC
/ DECIMAL
:
- Đọc tài liệu cẩn thận để biết rằng bạn nên chỉ định tỷ lệ để tránh tỷ lệ mặc định là 0, nghĩa là các giá trị số nguyên trong đó phân số thập phân bị thiếu. Mặc dù đây là một trong những nơi Postgres đi lạc khỏi SQL tiêu chuẩn (cung cấp cho bạn bất kỳ quy mô nào lên đến giới hạn triển khai). Vì vậy, không xác định được thang đo là một lựa chọn tồi.
- Các loại SQL
NUMERIC
&DECIMAL
gần gũi nhưng không giống hệt nhau theo Tiêu chuẩn SQL. Trong SQL:92 , độ chính xác đã chỉ định của bạn choNUMERIC
được tôn trọng, trong khi đối vớiDECIMAL
máy chủ cơ sở dữ liệu được phép thêm độ chính xác bổ sung ngoài những gì bạn đã chỉ định. Ở đây một lần nữa Postgres lại đi lạc một chút so với tiêu chuẩn, với cảNUMERIC
&DECIMAL
được lập tài liệu tương đương.
Điều khoản:
- Độ chính xác là tổng số chữ số trong một số.
- Tỷ lệ là số chữ số ở bên phải của dấu thập phân (phần thập phân).
- (Độ chính xác - Tỷ lệ) =Số chữ số ở bên trái dấu thập phân (phần số nguyên).
Hãy rõ ràng về thông số kỹ thuật của dự án của bạn để biết độ chính xác và quy mô:
- Lớn
Độ chính xác phải đủ lớn để xử lý các số lớn hơn có thể cần thiết trong tương lai. Có nghĩa là… Có lẽ ứng dụng của bạn ngày nay hoạt động với số tiền hàng nghìn USD nhưng trong tương lai phải thực hiện các báo cáo tổng hợp lên đến hàng triệu. - Nhỏ Đối với một số mục đích kế toán, bạn có thể cần phải lưu trữ một phần nhỏ của số tiền tệ nhỏ nhất. Có nghĩa là… Cần nhiều hơn 3 hoặc 4 chữ số thập phân thay vì 2 chữ số cho một xu trong USD .
Tránh MONEY
gõ
Postgres cung cấp MONEY
cả loại nữa. Điều đó nghe có vẻ đúng, nhưng có lẽ không phải là tốt nhất cho hầu hết các mục đích. Một nhược điểm là với MONEY
thang đo được đặt bởi cài đặt cấu hình trên toàn cơ sở dữ liệu dựa trên ngôn ngữ
. Vì vậy, cài đặt đó có thể thay đổi một cách dễ dàng nguy hiểm khi bạn chuyển đổi máy chủ hoặc thực hiện các thay đổi khác. Hơn nữa, bạn không thể kiểm soát cài đặt đó cho các cột cụ thể, trong khi bạn có thể đặt tỷ lệ trên mỗi cột của NUMERIC
loại hình. Cuối cùng, MONEY
không phải là SQL chuẩn như được hiển thị trong danh sách dữ liệu SQL chuẩn này các loại
. Postgres bao gồm MONEY
để thuận tiện cho mọi người chuyển dữ liệu từ các hệ thống cơ sở dữ liệu khác.
Di chuyển dấu thập phân
Một phương pháp thay thế khác được một số người sử dụng là di chuyển dấu thập phân và chỉ lưu trữ trong kiểu dữ liệu số nguyên lớn.
Ví dụ:Nếu lưu trữ USD đô la thành xu, bội bất kỳ số phân số đã cho nào với 100, được chuyển thành kiểu số nguyên và tiếp tục. Ví dụ:$ 123,45 trở thành số nguyên 12,345.
Lợi ích của cách tiếp cận này là thời gian thực hiện nhanh hơn. Các phép toán như sum
rất nhanh khi được thực hiện trên số nguyên. Một lợi ích khác đối với số nguyên là sử dụng ít bộ nhớ hơn.
Tôi thấy cách tiếp cận này khó chịu, khó hiểu và rủi ro. Khó chịu vì máy tính phải hoạt động cho chúng tôi, không chống lại chúng tôi. Rủi ro vì một số lập trình viên hoặc người dùng có thể bỏ qua việc nhân / chia để chuyển đổi trở lại số phân số, cho kết quả không chính xác. Nếu làm việc trong một hệ thống mà không có sự hỗ trợ tốt cho các số phân số chính xác, thì phương pháp này có thể là một cách giải quyết có thể chấp nhận được.
Tôi không thấy bất kỳ lợi ích nào khi di chuyển dấu thập phân khi chúng ta có DECIMAL
/ NUMERIC
trong SQL và BigDecimal
trong Java.
Làm tròn &NaN
Trong lập trình ứng dụng của bạn, cũng như bất kỳ phép tính nào được thực hiện ở phía máy chủ Postgres, hãy rất cẩn thận và lưu ý về việc làm tròn và cắt bớt trong phần thập phân. Và kiểm tra NaN vô tình bật lên.
Ở cả hai phía, ứng dụng và Postgres, luôn tránh dấu chấm động các kiểu dữ liệu cho hoạt động kiếm tiền. Dấu chấm động được thiết kế cho tốc độ hiệu suất , nhưng với chi phí chính xác . Các phép tính có thể dẫn đến các chữ số thừa dường như điên rồ trong phân số thập phân. Không tốt cho tài chính / tiền bạc hoặc các mục đích khác khi tính chính xác quan trọng.
BigDecimal
Có, trong Java, bạn muốn BigDecimal
như kiểu chính xác tùy ý của bạn. BigDecimal
chậm hơn và sử dụng nhiều bộ nhớ hơn, nhưng sẽ lưu trữ chính xác số tiền của bạn. SQL NUMERIC
/ DECIMAL
nên ánh xạ tới BigDecimal
như đã thảo luận tại đây
và trên StackOverflow
.
BigDecimal
là một trong những điều tốt nhất về Java. Tôi không biết có nền tảng nào khác có lớp tương tự, đặc biệt là nền tảng được triển khai tốt và được mài dũa tốt với các cải tiến và sửa chữa lớn được thực hiện trong nhiều năm.
Sử dụng BigDecimal
chắc chắn chậm hơn so với việc sử dụng Các loại dấu phẩy động của Java
, float
&double
. Nhưng trong các ứng dụng trong thế giới thực, tôi nghi ngờ việc tính toán tiền bạc của bạn sẽ trở thành nút thắt cổ chai. Và ngoài ra, bạn hoặc khách hàng của bạn muốn cái nào: nhanh nhất tính toán tiền hoặc chính xác tính toán tiền bạc? 😉
Tôi luôn nghĩ về BigDecimal
là tính năng buồn ngủ lớn nhất trong Java, lợi thế quan trọng nhất để sử dụng nền tảng Java so với rất nhiều nền tảng khác thiếu hỗ trợ phức tạp như vậy cho các số phân số.
Câu hỏi tương tự: Loại dữ liệu tốt nhất cho đơn vị tiền tệ