Haruskah Anda memilih tipe data UANG atau DECIMAL (x, y) di SQL Server?

442

Saya ingin tahu apakah ada perbedaan nyata antara moneytipe data dan sesuatu seperti decimal(19,4)(yang menggunakan uang secara internal, saya percaya).

Saya sadar itu moneykhusus untuk SQL Server. Saya ingin tahu apakah ada alasan kuat untuk memilih satu dari yang lain; kebanyakan sampel SQL Server (mis. database AdventureWorks) digunakan moneydan bukan decimaluntuk hal-hal seperti informasi harga.

Haruskah saya terus menggunakan datatype uang, atau adakah manfaat menggunakan desimal? Uang lebih sedikit untuk diketik, tetapi itu bukan alasan yang sah :)

Wayne Molina
sumber
12
DECIMAL(19, 4) adalah pilihan yang populer periksa ini juga periksa di sini Format Mata Uang Dunia untuk memutuskan berapa banyak tempat desimal yang digunakan, semoga membantu.
shaijut
Saya bertanya-tanya mengapa tipe data uang memiliki 4 desimal .. dan bukan 2. yaitu 100 sen dalam dolar sehingga hanya 2 tempat desimal yang diperlukan? Untuk menyimpan catatan jumlah uang kurang dari $ 9999,99, saya akan menggunakan tipe data desimal (6,2). Saya tidak khawatir tentang membagi atau mengalikan perhitungan, hanya menyimpan dan menjumlahkan ..
Allan F

Jawaban:

326

Jangan pernah Anda menggunakan uang. Itu tidak tepat, dan itu adalah sampah murni; selalu gunakan desimal / numerik.

Jalankan ini untuk melihat apa yang saya maksud:

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

Output: 2949.0000 2949.8525

Kepada sebagian orang yang mengatakan bahwa Anda tidak membagi uang dengan uang:

Ini adalah salah satu pertanyaan saya untuk menghitung korelasi, dan mengubahnya menjadi uang memberikan hasil yang salah.

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
SQLMenace
sumber
61
"Tidak pernah" adalah kata yang kuat. "Uang" berguna untuk menampilkan hasil ke jenis itu untuk ditampilkan kepada pengguna dengan cara yang peka budaya, tetapi Anda benar bahwa sangat buruk digunakan untuk perhitungan itu sendiri.
Joel Coehoorn
36
Contoh Anda tidak berarti, karena tidak seorang pun akan pernah melipatgandakan dua objek uang tip. Jika Anda ingin membuktikan poin Anda, Anda perlu membandingkan mengalikan uang dengan desimal ke mengalikan desimal dengan desimal.
Brian
27
.. tetapi masih membingungkan mengapa uang * uang tidak akan memiliki ketepatan uang.
Belajar
4
@Pelajaran: ia memiliki ketepatan uang. Namun, Anda masih berakhir dengan kesalahan pembulatan yang dapat menumpuk dari waktu ke waktu. Tipe desimal tidak menggunakan aritmatika biner: ini menjamin bahwa ia mendapatkan hasil basis 10 yang sama dengan yang Anda lakukan dari kertas.
Joel Coehoorn
55
Penggandaan dan pembagian yang moneyberlebihan money, 'ilustrasi' ini manipulatif. Ini adalah fakta yang terdokumentasi yang moneymemiliki ketepatan tetap dan sangat terbatas. Dalam kasus seperti itu, yang pertama harus dikalikan, dan kemudian dibagi. Ubah urutan operator dalam contoh ini dan Anda akan mendapatkan hasil yang identik. Sebuah moneydasarnya adalah int 64-bit, dan jika Anda berurusan dengan int, Anda akan kalikan sebelum membaginya.
Andriy M
272

SQLMenace mengatakan uang tidak tepat. Tetapi Anda tidak mengalikan / membagi uang dengan uang! Berapa 3 dolar kali 50 sen? 150 dolar? Anda mengalikan / membagi uang dengan skalar, yang seharusnya menjadi desimal.

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

Hasil dalam hasil yang benar:

hasil penghitungan uang
--------------------- ----------------------------- ----------
2949.8525 2949.8525

moneybagus selama Anda tidak membutuhkan lebih dari 4 digit desimal, dan Anda memastikan skalar Anda - yang tidak mewakili uang - bernilai decimals.

konfigurator
sumber
57
berapa banyak koin 1 sen yang dapat Anda terima dengan satu dolar? jawaban untuk ini membutuhkan uang / uang.
Belajar
48
@Pelajaran dalam hal ini hasilnya bukan uang, tetapi pelampung. (Analisis dimensi dasar.)
Richard
11
@Pelajaran: Apakah Anda bertanya pada database berapa banyak sen dalam satu dolar banyak? Bagaimanapun, itu akan mengembalikan hasil yang tepat. Masalahnya adalah bahwa uang / uang itu hanya tepat untuk empat digit (itu adalah 0,2949), kemudian ketika dikalikan dengan 10.000 itu menjadi 2949,0000.
konfigurator
26
@son Dia benar dan tidak membuat kritik pribadi seperti yang Anda lakukan berdasarkan komentar satu baris, itu tidak membantu. Jika dia tidak membagi dengan $ 0,01 tetapi sebaliknya 0,01, maka hasilnya adalah $ 100 bukannya 100. Ada 100 sen dalam dolar, bukan $ 100 sen. Unit itu penting! Pasti ada tempat besar untuk menyelam, dan mungkin mengalikan, uang dengan uang.
andrewb
19
Jika saya ingin menghabiskan $ 1000 untuk membeli saham dengan harga $ 36, bukankah itu penggunaan yang sah money / money? Jawabannya adalah seluruh unit tanpa tanda dolar terpasang, yang benar! Ini adalah skenario yang sangat masuk akal, menunjukkan bahwa karena kasus tepi aneh seperti ini, moneybukan tipe data yang baik untuk digunakan, karena hasilnya selalu terpotong kembali agar sesuai moneydaripada mengikuti aturan normal untuk presisi dan skala. Bagaimana jika Anda ingin menghitung standar deviasi dari satu set moneynilai? Ya, Sqrt(Sum(money * money))(disederhanakan) sebenarnya masuk akal.
ErikE
59

Semuanya berbahaya jika Anda tidak tahu apa yang Anda lakukan

Bahkan tipe desimal presisi tinggi tidak dapat menyelamatkan hari:

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

1,000000 <- Seharusnya 0,6000000


Itu money jenis adalah bilangan bulat

Representasi teks dari smallmoney dan decimal(10,4)mungkin mirip, tetapi itu tidak membuatnya dipertukarkan. Apakah Anda merasa ngeri ketika melihat tanggal disimpan varchar(10)? Ini adalah hal yang sama.

Di belakang layar, money/ smallmoneyhanyabigint / int Titik desimal dalam representasi teks moneyadalah bulu visual, seperti tanda hubung pada tanggal tttt-hh-bb-hh. SQL sebenarnya tidak menyimpannya secara internal.

Mengenai decimalvs money, pilih apa pun yang sesuai dengan kebutuhan Anda. The moneyjenis ada karena menyimpan nilai-nilai akuntansi sebagai kelipatan bilangan bulat dari 1/10000 unit sangat umum. Juga, jika Anda berurusan dengan uang aktual dan perhitungan di luar penjumlahan dan pengurangan sederhana, Anda seharusnya tidak melakukan itu di tingkat basis data! Lakukan di tingkat aplikasi dengan perpustakaan yang mendukung Pembulatan Bankir (IEEE 754)

Segera
sumber
1
Bisakah Anda jelaskan apa yang terjadi dalam contoh ini?
Sergey Popov
4
Skala meluap. Pada skala kecil, numerik (a, b) * numerik (c, d) menghasilkan numerik (a-b + c-d + 1, maks (b, d)). Namun, jika (a + b + c + d)> 38, SQL membatasi skala, merampok presisi dari sisi fraksi untuk mengisi sisi integer, menyebabkan kesalahan pembulatan.
Anon
Semua perhitungan numerik rentan terhadap kehilangan presisi karena penskalaan: alih-alih hitung pilih 1000000 * @ num1 * @ num2
Mitch Wheat
Contoh anon adalah versi dan basis data khusus. tapi intinya hati-hati itu valid. di sqlanywhere versi 1.1, contohnya memberikan 0.600000 dengan benar. (Saya tahu kita berbicara tentang ms sql di sini). titik lain tentang jenis uang yang hilang dari database lain, ada cara memanggil desimal atau numerik sebagai uang, seperti membuat domain.
gg89
3
Saya pikir ini adalah jawaban yang paling mencerahkan karena Anda telah menjelaskan bukan hanya kesalahan yang disebarkan, tetapi apa yang sebenarnya terjadi di balik layar, dan mengapa MONEY ada di tempat pertama. Saya tidak yakin mengapa butuh 4 tahun untuk mendapatkan jawaban ini, tapi mungkin itu karena terlalu banyak fokus pada "masalah" perhitungan, dan tidak begitu banyak pada mengapa dan bagaimana uang vs desimal.
Steve Sether
44

Saya menyadari bahwa WayneM telah menyatakan dia tahu bahwa uang itu khusus untuk SQL Server. Namun, ia bertanya apakah ada alasan untuk menggunakan uang lebih dari desimal atau sebaliknya dan saya pikir satu alasan yang jelas masih harus dinyatakan dan menggunakan desimal berarti satu hal yang tidak perlu dikhawatirkan jika Anda harus mengubah DBMS Anda - yang bisa terjadi.

Jadikan sistem Anda sefleksibel mungkin!

Dekan
sumber
1
Mungkin, tetapi secara teori Anda bisa mendeklarasikan domain bernama Uang di DBMS lain (yang mendukung deklarasi domain).
debat
Sebagai seseorang yang saat ini mengonversi basis data SQL Server ke Amazon Redshift, saya dapat menjamin bahwa ini adalah masalah asli. Cobalah untuk menghindari tipe data yang dipesan khusus untuk platform database tertentu kecuali ada alasan bisnis yang sangat baik untuk menggunakannya.
Nathan Griffiths
@Nathn diberi sistem tipe Redshift yang lemah dibandingkan dengan PostgreSQL atau SQL Server, misalnya tanpa datetipe, saya akan mengatakan Anda akan selalu memiliki masalah seperti itu. Anda harus mengatakan "Jangan menggunakan tipe yang sudah tidak digunakan lagi ketika database sudah menyediakan tipe yang lebih baik, lebih sesuai standar dan memperingatkan terhadap yang sudah usang".
Panagiotis Kanavos
@PanagiotisKanavos - uang tidak ditinggalkan
Martin Smith
@MartinSmith terkejut melihat ini, karena tidak dapat benar-benar menangani nilai uang seperti BTC pada tahun 2017. Atau membedakan antara jumlah GBP dan EUR - meskipun mereka bergerak menuju paritas: P. Pokoknya, pindah ke Redshift menimbulkan banyak rasa sakit
Panagiotis Kanavos
32

Ya saya suka MONEY! Ini satu byte lebih murah daripada DECIMAL, dan komputasi berkinerja lebih cepat karena (di bawah penutup) operasi penambahan dan pengurangan pada dasarnya operasi integer. Contoh @ SQLMenace — yang merupakan peringatan besar bagi yang tidak sadar — bisa juga diterapkan pada INTegers, di mana hasilnya akan nol. Tapi itu bukan alasan untuk tidak menggunakan bilangan bulat— jika perlu .

Jadi, sangat 'aman' dan tepat untuk digunakan MONEYketika apa yang Anda hadapi adalah MONEYdan menggunakannya sesuai dengan aturan matematika yang diikuti (sama sepertiINT eger).

Apakah lebih baik jika SQL Server mempromosikan pembagian dan perkalian dari MONEYmenjadi DECIMALs (atau FLOATs?) - mungkin, tetapi mereka tidak memilih untuk melakukan ini; mereka juga tidak memilih untuk mempromosikan INTeger FLOATketika membaginya.

MONEYtidak memiliki masalah presisi; bahwaDECIMAL dapat memiliki tipe perantara yang lebih besar yang digunakan selama perhitungan hanyalah 'fitur' dari penggunaan tipe itu (dan saya tidak benar-benar yakin seberapa jauh 'fitur' itu meluas).

Untuk menjawab pertanyaan spesifik, "alasan kuat"? Nah, jika Anda ingin kinerja maksimum absolut di suatu SUM(x)tempat xbisa jadi DECIMALatau MONEY, makaMONEY akan memiliki keunggulan.

Juga, jangan lupa itu sepupu yang lebih kecil, SMALLMONEY—hanya 4 byte, tapi maks214,748.3647 — yang cukup kecil untuk uangnya — dan karenanya sering kali tidak cocok.

Untuk membuktikan titik sekitar menggunakan tipe perantara yang lebih besar, jika Anda menetapkan perantara secara eksplisit ke variabel, DECIMALmenderita masalah yang sama:

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

Menghasilkan 2950.0000(oke, jadi setidaknya DECIMALbulat daripada MONEYterpotong — sama seperti integer.)

dsz
sumber
21
MONEYadalah salah satu byte kurang dari yang besar DECIMAL , dengan sampai 19 digit presisi. Namun, sebagian besar perhitungan moneter dunia nyata (hingga $ 9,99 M) dapat ditampung dalam a DECIMAL(9, 2), yang hanya membutuhkan lima byte. Anda dapat menghemat ukuran, lebih sedikit khawatir tentang kesalahan pembulatan, dan membuat kode Anda lebih portabel.
Meskipun @JonofAllTrades benar, Anda juga bisa mendapatkan kinerja integer kembali hanya dengan menggunakan integer yang mengandung uang atau sen, dan menyimpan byte tambahan yang mengkodekan posisi titik desimal, dan yang harus diperiksa ketika menambahkan desimal bersama.
dsz
"Jadi, benar-benar 'aman' dan tepat untuk menggunakan MONEY ketika apa yang Anda hadapi adalah MONEY dan menggunakannya sesuai dengan aturan matematika yang mengikutinya" -> Namun, lihat juga jawaban Anon: "Semuanya berbahaya jika Anda tidak tahu apa yang kamu lakukan ". Anda tidak pernah dapat memprediksi bagaimana orang pada akhirnya akan menanyakan sistem yang Anda buat, yang terbaik untuk menghindari kemungkinan penyalahgunaan ketika Anda bisa. Keuntungan sangat kecil dalam penyimpanan tidak sebanding dengan IMHO.
Nathan Griffiths
1
Cobalah menyimpan nilai Bitcoin. Ini memiliki 8 desimal
Panagiotis Kanavos
13

Kami baru saja menemukan masalah yang sangat mirip dan saya sekarang sangat +1 untuk tidak pernah menggunakan Uang kecuali dalam presentasi tingkat atas. Kami memiliki beberapa tabel (efektifnya voucher penjualan dan faktur penjualan) yang masing-masing berisi satu atau lebih bidang Uang karena alasan historis, dan kami perlu melakukan perhitungan pro-rata untuk menentukan berapa banyak dari total faktur Pajak yang relevan untuk masing-masing baris pada voucher penjualan. Perhitungan kami adalah

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

Ini menghasilkan perhitungan uang dunia nyata / uang yang menyebabkan kesalahan skala pada bagian divisi, yang kemudian dikalikan menjadi proporsi tong yang salah. Ketika nilai-nilai ini selanjutnya ditambahkan, kita berakhir dengan jumlah proporsi tong yang tidak menambahkan hingga nilai total faktur. Jika salah satu dari nilai dalam tanda kurung adalah desimal (saya akan memberikan salah satu dari mereka) proporsi tong akan benar.

Ketika kurung tidak ada di sana ini awalnya bekerja, saya kira karena nilai-nilai yang lebih besar yang terlibat, secara efektif mensimulasikan skala yang lebih tinggi. Kami menambahkan tanda kurung karena melakukan perkalian terlebih dahulu, yang dalam beberapa kasus jarang meniup presisi yang tersedia untuk perhitungan, tetapi ini sekarang telah menyebabkan kesalahan yang jauh lebih umum ini.

Kaideejee
sumber
8
Tetapi itu hanya terjadi karena pengembang yang tidak peduli mengabaikan aturan untuk perhitungan PPN dan batasan ketepatan uang yang didokumentasikan.
TomTom
1
@ TomTom tetapi poin yang Anda buat tentang kemungkinan penyalahgunaan tipe data ini adalah argumen yang mendukung untuk menghindari menggunakannya sama sekali.
Nathan Griffiths
@Nathan No. Saya menunjukkan bahwa argumen yang diberikan sebagai alasan untuk tidak pernah menggunakannya pada dasarnya adalah pengembang yang tidak kompeten, jadi argumennya adalah palsu.
TomTom
1
@TomTom sayangnya ada banyak pengembang yang tidak kompeten (dan juga banyak yang luar biasa) dan bagi saya, kecuali saya bisa menjamin bagaimana data ini akan ditanyakan di masa depan dan tidak ada yang akan membuat kesalahan seperti yang dijelaskan di sini , lebih baik berbuat salah di sisi hati-hati dan menggunakan tipe desimal. Yang mengatakan, setelah membaca semua jawaban ini saya bisa melihat ada beberapa kasus penggunaan khusus di mana uang akan menjadi jenis yang optimal untuk digunakan, saya tidak akan menggunakannya kecuali ada kasus penggunaan yang sangat baik untuk itu (misalnya kolom hanya akan pernah diagregasi oleh SUM, pemuatan data keuangan dalam jumlah besar).
Nathan Griffiths
@ TomTom bukan hanya batasan presisi. Representasi internal juga dapat menyebabkan masalah. Uang adalah jenis kenyamanan untuk menangkap pengembang yang bodoh, bukan jenis yang hebat yang disalahgunakan pengembang. Contoh tong, terlepas dari aturan untuk menghitungnya, jelas harus menakut-nakuti pengembang non-jahil ketika mereka menerapkan spesifik ke umum.
Gerard ONeill
12

Sebagai titik tandingan untuk dorongan umum dari jawaban lain. Lihat Banyak Manfaat Uang ... Jenis Data! dalam Panduan SQLCAT untuk Mesin Relasional

Secara khusus saya akan tunjukkan berikut ini

Bekerja pada implementasi pelanggan, kami menemukan beberapa angka kinerja yang menarik mengenai tipe data uang. Misalnya, ketika Layanan Analisis diatur ke tipe data mata uang (dari dua kali lipat) agar sesuai dengan tipe data uang SQL Server, ada peningkatan 13% dalam kecepatan pemrosesan (baris / detik). Untuk mendapatkan kinerja yang lebih cepat dalam SQL Server Integration Services (SSIS) untuk memuat 1,18 TB dalam waktu kurang dari tiga puluh menit, seperti dicatat dalam SSIS 2008 - rekor dunia kinerja ETL, diamati bahwa mengubah empat desimal (9,2) kolom dengan ukuran 5 byte dalam tabel TPC-H LINEITEM ke uang (8 byte) meningkatkan kecepatan memasukkan massal sebesar 20% ... Alasan peningkatan kinerja adalah karena protokol Tabular Data Stream (TDS) SQL Server, yang memiliki prinsip desain utama untuk mentransfer data dalam bentuk biner yang ringkas dan sedekat mungkin dengan format penyimpanan internal SQL Server. Secara empiris, ini diamati selama SSIS 2008 - tes kinerja ETL rekor dunia menggunakan Kernrate; protokol turun secara signifikan ketika tipe data dialihkan ke uang dari desimal. Ini membuat transfer data seefisien mungkin. Tipe data yang kompleks membutuhkan siklus penguraian dan CPU tambahan untuk menangani daripada tipe dengan lebar tetap.

Jadi jawaban untuk pertanyaan itu adalah "itu tergantung". Anda harus lebih berhati-hati dengan operasi aritmatika tertentu untuk menjaga presisi tetapi Anda mungkin menemukan bahwa pertimbangan kinerja membuat ini bermanfaat.

Martin Smith
sumber
Bagaimana Anda menyimpan bitcoin ?
Panagiotis Kanavos
@PanagiotisKanavos - Saya tidak tahu. Saya tidak pernah melihat bitcoin dan praktis tidak tahu apa-apa tentang itu!
Martin Smith
6

Saya ingin memberikan pandangan yang berbeda tentang MONEY vs NUMERICAL, sebagian besar berdasarkan keahlian dan pengalaman saya sendiri ... Pandangan saya di sini adalah MONEY, karena saya telah bekerja dengannya untuk waktu yang cukup lama dan tidak pernah benar-benar menggunakan NUMERICAL .. .

MONEY Pro:

  • Tipe Data Asli . Ini menggunakan tipe data asli ( integer ) sama seperti register CPU (32 atau 64 bit), sehingga perhitungan tidak perlu overhead yang tidak perlu sehingga lebih kecil dan lebih cepat ... UANG membutuhkan 8 byte dan NUMERIK (19, 4 ) membutuhkan 9 byte (12,5% lebih besar) ...

    UANG lebih cepat asalkan digunakan untuk itu dimaksudkan untuk menjadi (sebagai uang). Seberapa cepat? SUMTes sederhana saya pada 1 juta data menunjukkan bahwa MONEY adalah 275 ms dan NUMERIC 517 ms ... Itu hampir dua kali lebih cepat ... Mengapa uji SUM? Lihat poin Pro berikutnya

  • Terbaik untuk uang . MONEY adalah yang terbaik untuk menyimpan uang dan melakukan operasi, misalnya dalam akuntansi. Satu laporan dapat menjalankan jutaan penambahan (SUM) dan beberapa perkalian setelah operasi SUM dilakukan. Untuk aplikasi akuntansi yang sangat besar hampir dua kali lebih cepat , dan ini sangat signifikan ...
  • Presisi Uang Rendah . Uang dalam kehidupan nyata tidak harus sangat tepat. Maksud saya, banyak orang mungkin peduli sekitar 1 sen USD, tetapi bagaimana dengan 0,01 sen USD? Bahkan, di negara saya, bank tidak lagi peduli dengan sen (digit setelah koma desimal); Saya tidak tahu tentang bank AS atau negara lain ...

Con MONEY:

  • Ketepatan Terbatas . MONEY hanya memiliki empat digit (setelah koma) presisi, sehingga harus dikonversi sebelum melakukan operasi seperti divisi ... Tapi sekali lagi moneytidak perlu begitu tepat dan dimaksudkan untuk digunakan sebagai uang, bukan hanya jumlah...

Tapi ... Besar, tetapi di sini bahkan aplikasi Anda melibatkan uang sungguhan, tetapi jangan menggunakannya dalam banyak operasi SUM, seperti dalam akuntansi. Jika Anda menggunakan banyak divisi dan perkalian sebagai gantinya maka Anda seharusnya tidak menggunakan UANG ...

Susilo
sumber
1
Jika Anda akan mengatakan bahwa uang lebih cepat daripada desimal, Anda perlu memberi tahu kami hal-hal seperti apa rdbms, pada perangkat keras apa, menjalankan OS apa, dengan data spesifik apa yang menjalankan kueri spesifik apa yang Anda bicarakan. Selain itu, jika itu TIDAK sepenuhnya akurat, saya TIDAK melakukan operasi keuangan dengannya, karena petugas pajak akan agak tidak senang mendapatkan angka buruk kembali. Anda peduli dengan seperseribu sen jika Anda berurusan dengan mata uang AS misalnya. Jika uang tidak melakukan itu, itu tidak dapat digunakan.
Haakon Løtveit
3
@ HaakonLøtveit seluruh utas T&J ini tentang tipe data SQL Server "uang", jadi saya tidak berpikir mereka perlu menentukan ini dalam jawabannya. Uang dapat lebih cepat digunakan daripada desimal dalam beberapa keadaan (misalnya memuat data), lihat jawabannya oleh Martin Smith untuk lebih jelasnya. Saya setuju dengan sebagian besar jawaban ini, karena ada kasus penggunaan tertentu yang dapat membuat Uang menjadi pilihan yang lebih efisien daripada desimal, namun kecuali ada kasus yang sangat menarik untuk menggunakannya saya pikir itu harus dihindari.
Nathan Griffiths
1
Bitcoin memiliki 8 desimal. Anda bahkan tidak dapat menyimpannya di moneykolom
Panagiotis Kanavos
4

Semua posting sebelumnya membawa poin yang valid, tetapi beberapa tidak menjawab pertanyaan dengan tepat.

Pertanyaannya adalah: Mengapa seseorang lebih suka uang ketika kita sudah tahu itu adalah tipe data yang kurang tepat dan dapat menyebabkan kesalahan jika digunakan dalam perhitungan yang rumit?

Anda menggunakan uang ketika Anda tidak akan membuat perhitungan yang rumit dan dapat memperdagangkan ketepatan ini untuk kebutuhan lain.

Misalnya, ketika Anda tidak harus membuat perhitungan tersebut, dan perlu mengimpor data dari string teks mata uang yang valid. Konversi otomatis ini hanya berfungsi dengan tipe data MONEY:

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

Saya tahu Anda dapat membuat rutin impor sendiri. Namun terkadang Anda tidak ingin membuat ulang rutin impor dengan format lokal khusus di seluruh dunia.

Contoh lain, ketika Anda tidak harus membuat perhitungan tersebut (Anda hanya perlu menyimpan nilai) dan perlu menyimpan 1 byte (uang membutuhkan 8 byte dan desimal (19,4) membutuhkan 9 byte). Dalam beberapa aplikasi (CPU cepat, RAM besar, IO lambat), seperti hanya membaca data dalam jumlah besar, ini juga bisa lebih cepat.

Weber K.
sumber
2

Anda tidak harus menggunakan uang ketika Anda perlu melakukan perkalian / pembagian nilai. Uang disimpan dengan cara yang sama dengan bilangan bulat disimpan, sedangkan desimal disimpan sebagai titik desimal dan digit desimal. Ini berarti bahwa uang akan menurunkan akurasi dalam kebanyakan kasus, sementara desimal hanya akan melakukannya ketika dikonversi kembali ke skala aslinya. Uang adalah titik tetap, sehingga skalanya tidak berubah selama perhitungan. Namun karena itu adalah titik tetap ketika dicetak sebagai string desimal (berlawanan dengan posisi tetap dalam string basis 2), nilai hingga skala 4 direpresentasikan secara tepat. Jadi untuk penambahan dan pengurangan, uang baik-baik saja.

Desimal diwakili dalam basis 10 secara internal, dan dengan demikian posisi titik desimal juga didasarkan pada angka dasar 10. Yang membuat bagian fraksinya mewakili nilainya dengan tepat, seperti halnya dengan uang. Perbedaannya adalah bahwa nilai tengah desimal dapat mempertahankan presisi hingga 38 digit.

Dengan angka floating point, nilainya disimpan dalam biner seolah-olah bilangan bulat, dan posisi titik desimal (atau biner, ahem) relatif terhadap bit yang mewakili angka tersebut. Karena ini adalah titik desimal biner, angka dasar 10 kehilangan presisi tepat setelah titik desimal. 1 / 5th, atau 0.2, tidak dapat direpresentasikan secara tepat dengan cara ini. Baik uang maupun desimal tidak mengalami keterbatasan ini.

Cukup mudah untuk mengkonversi uang menjadi desimal, melakukan perhitungan, dan kemudian menyimpan nilai yang dihasilkan kembali ke bidang uang atau variabel.

Dari POV saya, saya ingin hal-hal yang terjadi pada angka terjadi begitu saja tanpa harus terlalu memikirkannya. Jika semua perhitungan akan dikonversi menjadi desimal, maka bagi saya saya hanya ingin menggunakan desimal. Saya akan menyimpan bidang uang untuk keperluan tampilan.

Dari segi ukuran, saya tidak melihat cukup banyak perbedaan untuk mengubah pikiran saya. Uang membutuhkan 4 - 8 byte, sedangkan desimal dapat 5, 9, 13, dan 17. 9 byte dapat mencakup seluruh rentang yang dapat dicapai oleh 8 byte uang. Dari segi indeks (membandingkan dan mencari harus sebanding).

Gerard ONeill
sumber
Terima kasih atas Upvote. Saya melihat ini dan sementara saya mendapatkan apa yang saya coba katakan, saya juga bisa melihatnya sangat membingungkan. Mungkin saya akan menulis ulang nanti dengan beberapa contoh bit vs desimal.
Gerard ONeill
2

Saya menemukan alasan tentang menggunakan desimal atas uang dalam subjek akurasi.

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

Cukup uji dan buat keputusan Anda.

QMaster
sumber
2
Kami sangat ingin mendengar (baca, itulah) kesimpulan Anda .
Peter Mortensen
@PeterMortensen Saya pikir jika saya ingin memiliki kelengkapan dan akurasi antara Uang dan jenis Desimal, keputusan saya harus Desimal.
QMaster
1
Pertimbangkan untuk memperbarui jawaban Anda dengan hasil aktual di atas. Maka kesimpulan Anda akan segera jelas bagi siapa pun yang membaca :-)
Agreax
1
@Ageax Hasilnya ditambahkan ke jawaban.
QMaster
1

Saya baru saja melihat entri blog ini: Uang vs. Desimal di SQL Server .

Yang pada dasarnya mengatakan bahwa uang memiliki masalah presisi ...

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

set @m = 19.34
set @d = 19.34

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

Untuk moneyjenisnya, Anda akan mendapatkan 19,30 bukannya 19,34. Saya tidak yakin apakah ada skenario aplikasi yang membagi uang menjadi 1000 bagian untuk perhitungan, tetapi contoh ini memang memaparkan beberapa batasan.

Harsha
sumber
15
Ini bukan "masalah", ini "sesuai spesifikasi": «Jenis data moneydan smallmoneyakurat hingga seperseribu unit moneter yang mereka wakili.» seperti yang dikatakan di msdn.microsoft.com/en-us/library/ms179882.aspx sehingga siapa pun yang mengatakan "ini sampah" tidak tahu apa yang dia bicarakan.
Albireo