Saya punya pesan kesalahan ini:
Msg 8134, Level 16, State 1, Line 1 Divide by zero error found.
Apa cara terbaik untuk menulis kode SQL sehingga saya tidak akan pernah melihat pesan kesalahan ini lagi?
Saya dapat melakukan salah satu dari yang berikut:
- Tambahkan klausa dimana sehingga pembagi saya tidak pernah nol
Atau
- Saya bisa menambahkan pernyataan kasus, sehingga ada perlakuan khusus untuk nol.
Apakah cara terbaik untuk menggunakan NULLIF
klausa?
Apakah ada cara yang lebih baik, atau bagaimana ini bisa ditegakkan?
sql
sql-server
sql-server-2005
sql-server-2008
Henrik Staun Poulsen
sumber
sumber
Jawaban:
Untuk menghindari kesalahan "Division by zero", kami telah memprogramnya seperti ini:
Tapi di sini ada cara yang lebih baik untuk melakukannya:
Sekarang satu-satunya masalah adalah untuk mengingat bit NullIf, jika saya menggunakan kunci "/".
sumber
IsNull
bukanNullIf
? Cobalah sendiri!SELECT Value,1/NullIf(Value,0)FROM(VALUES(0),(5.0),(NULL))x(Value);
Kecuali dengan "break" yang Anda maksud mengembalikan NULL? Anda dapat mengonversinya menjadi apa pun yang Anda inginkan denganIsNull
atauCoalesce
.SELECT 1 / NULLIF(NULL, 0)
gagal, tapi itu karenaNULLIF()
perlu tahu tipe data dari argumen pertama. Contoh diubah ini bekerja dengan baik:SELECT 1 / NULLIF(CAST(NULL AS INT), 0)
. Dalam kehidupan nyata, Anda akan memasok kolom tabelNULLIF()
daripadaNULL
konstanta. Sejak kolom tabel memiliki tipe data yang diketahui, ini juga berfungsi dengan baik:SELECT 1 / NULLIF(SomeNullableColumn, 0) FROM SomeTable
.Jika Anda ingin mengembalikan nol, jika terjadi devisi nol, Anda dapat menggunakan:
Untuk setiap pembagi yang nol, Anda akan mendapatkan nol di set hasil.
sumber
Ini tampaknya menjadi perbaikan terbaik untuk situasi saya ketika mencoba mengatasi pembagian dengan nol, yang memang terjadi pada data saya.
Misalkan Anda ingin menghitung rasio pria-wanita untuk berbagai klub sekolah, tetapi Anda menemukan bahwa kueri berikut gagal dan mengeluarkan kesalahan dibagi-oleh-nol ketika mencoba menghitung rasio untuk Klub Lord of the Rings, yang tidak memiliki wanita :
Anda dapat menggunakan fungsi ini
NULLIF
untuk menghindari pembagian dengan nol.NULLIF
membandingkan dua ekspresi dan mengembalikan nol jika sama atau ekspresi pertama sebaliknya.Tulis ulang kueri sebagai:
Setiap angka dibagi dengan
NULL
memberiNULL
, dan tidak ada kesalahan yang dihasilkan.sumber
select males/(males+females), females/(males+females)
. Ini akan memberi Anda distribusi persentase pria dan wanita di sebuah klub, seperti 31% pria, 69% wanita.Anda juga dapat melakukan ini di awal kueri:
Jadi jika Anda memiliki sesuatu seperti
100/0
itu akan mengembalikan NULL. Saya hanya melakukan ini untuk pertanyaan sederhana, jadi saya tidak tahu bagaimana itu akan mempengaruhi yang lebih lama / kompleks.sumber
Anda setidaknya dapat menghentikan permintaan agar tidak putus dengan kesalahan dan kembali
NULL
jika ada pembagian dengan nol:Namun, saya TIDAK AKAN PERNAH mengonversi ini menjadi Nol dengan
coalesce
seperti ditunjukkan dalam jawaban lain yang mendapat banyak upvotes. Ini benar-benar salah dalam arti matematis, dan bahkan berbahaya karena aplikasi Anda kemungkinan akan mengembalikan hasil yang salah dan menyesatkan.sumber
EDIT: Saya mendapatkan banyak downvotes tentang ini baru-baru ini ... jadi saya pikir saya hanya akan menambahkan catatan bahwa jawaban ini ditulis sebelum pertanyaan menjalani edit terakhir, di mana pengembalian null disorot sebagai pilihan .. .yang tampaknya sangat bisa diterima. Beberapa jawaban saya ditujukan kepada keprihatinan seperti itu dari Edwardo, dalam komentar, yang tampaknya menganjurkan pengembalian 0. Ini adalah kasus saya menentang.
JAWABAN: Saya pikir ada masalah mendasar di sini, yaitu pembagian dengan 0 tidak legal. Ini merupakan indikasi bahwa ada sesuatu yang secara fundamental salah. Jika Anda membaginya dengan nol, Anda mencoba melakukan sesuatu yang tidak masuk akal secara matematis, sehingga tidak ada jawaban numerik yang Anda dapatkan akan valid. (Penggunaan nol dalam kasus ini masuk akal, karena ini bukan nilai yang akan digunakan dalam perhitungan matematika nanti).
Jadi Edwardo bertanya di komentar "bagaimana jika pengguna memasukkan 0?", Dan dia menganjurkan bahwa tidak apa-apa untuk mendapatkan 0 sebagai balasan. Jika pengguna memasukkan nol dalam jumlah, dan Anda ingin 0 dikembalikan ketika mereka melakukan itu, maka Anda harus memasukkan kode pada tingkat aturan bisnis untuk menangkap nilai itu dan mengembalikan 0 ... tidak memiliki kasus khusus di mana pembagian dengan 0 = 0.
Itu perbedaan yang halus, tetapi ini penting ... karena ketika seseorang memanggil fungsi Anda dan mengharapkannya untuk melakukan hal yang benar, dan itu melakukan sesuatu yang funky yang tidak benar secara matematis, tetapi hanya menangani kasing tepi tertentu itu punya peluang bagus untuk menggigit seseorang nanti. Anda tidak benar-benar membaginya dengan 0 ... Anda hanya mengembalikan jawaban yang buruk ke pertanyaan yang buruk.
Bayangkan saya sedang mengkode sesuatu, dan saya mengacaukannya. Saya seharusnya membaca nilai skala pengukuran radiasi, tetapi dalam kasus tepi aneh yang tidak saya antisipasi, saya baca di 0. Saya kemudian menjatuhkan nilai saya ke dalam fungsi Anda ... Anda mengembalikan saya 0! Hore, tidak ada radiasi! Kecuali itu benar-benar ada dan hanya saja saya melewati nilai buruk ... tapi saya tidak tahu. Saya ingin divisi untuk melempar kesalahan karena itu adalah bendera bahwa ada sesuatu yang salah.
sumber
Dengan menangkap nol dengan nullif (), maka null yang dihasilkan dengan isnull () Anda dapat menghindari pembagian Anda dengan kesalahan nol.
sumber
Mengganti "bagi dengan nol" dengan nol adalah kontroversial - tetapi itu juga bukan satu-satunya pilihan. Dalam beberapa kasus, mengganti dengan 1 sesuai (wajar). Saya sering menemukan diri saya menggunakan
ketika saya melihat pergeseran dalam skor / jumlah, dan ingin default ke 1 jika saya tidak memiliki data. Sebagai contoh
Lebih sering daripada tidak, saya sudah benar-benar menghitung rasio ini di tempat lain (paling tidak karena dapat melempar beberapa faktor penyesuaian yang sangat besar untuk penyebut rendah. Dalam hal ini saya biasanya mengontrol OldSampleScore lebih besar dari ambang; yang kemudian menghalangi nol Tapi terkadang 'retasan' itu sesuai.
sumber
Saya menulis sebuah fungsi beberapa waktu lalu untuk mengatasinya untuk prosedur tersimpan saya :
sumber
Divisor
menjadi nolsumber
Untuk memperbarui SQL:
sumber
Tidak ada pengaturan global ajaib 'turn Division by 0 exception off'. Operasi harus melempar, karena arti matematis x / 0 berbeda dari makna NULL, sehingga tidak dapat mengembalikan NULL. Saya berasumsi Anda mengurus yang jelas dan pertanyaan Anda memiliki kondisi yang harus menghilangkan catatan dengan pembagi 0 dan tidak pernah mengevaluasi divisi. 'Gotcha' yang biasa adalah daripada kebanyakan pengembang mengharapkan SQL berperilaku seperti bahasa prosedural dan menawarkan hubungan pendek operator logis, tetapi TIDAK . Saya sarankan Anda membaca artikel ini: http://www.sqlmag.com/Articles/ArticleID/9148/pg/2/2.html
sumber
Berikut adalah situasi di mana Anda dapat membaginya dengan nol. Aturan bisnis adalah bahwa untuk menghitung perputaran persediaan, Anda mengambil harga pokok penjualan untuk suatu periode, menjadikannya tahunan. Setelah Anda memiliki angka tahunan, Anda membagi dengan persediaan rata-rata untuk periode tersebut.
Saya sedang menghitung jumlah perputaran persediaan yang terjadi dalam periode tiga bulan. Saya telah menghitung bahwa saya memiliki Harga Pokok Penjualan selama periode tiga bulan sebesar $ 1.000. Tingkat penjualan tahunan adalah $ 4.000 ($ 1.000 / 3) * 12. Persediaan awal adalah 0. Persediaan akhir adalah 0. Persediaan rata-rata saya sekarang adalah 0. Saya memiliki penjualan $ 4000 per tahun, dan tidak ada persediaan. Ini menghasilkan jumlah belokan yang tak terbatas. Ini berarti bahwa semua inventaris saya sedang dikonversi dan dibeli oleh pelanggan.
Ini adalah aturan bisnis tentang cara menghitung perputaran persediaan.
sumber
sumber
Memfilter data menggunakan klausa dimana sehingga Anda tidak mendapatkan nilai 0.
sumber
Terkadang, 0 mungkin tidak sesuai, tetapi terkadang 1 juga tidak tepat. Kadang-kadang lompatan dari 0 hingga 100.000.000 digambarkan sebagai perubahan 1 atau 100 persen juga bisa menyesatkan. 100.000.000 persen mungkin sesuai dalam skenario itu. Itu tergantung pada kesimpulan apa yang ingin Anda buat berdasarkan persentase atau rasio.
Misalnya, barang yang sangat kecil yang dijual dari 2-4 yang terjual dan barang yang sangat besar berubah dari 1.000.000 menjadi 2.000.000 yang terjual mungkin berarti hal yang sangat berbeda bagi seorang analis atau manajemen, tetapi keduanya akan menjadi 100% atau 1 perubahan.
Mungkin lebih mudah untuk mengisolasi nilai NULL daripada menjelajahi sekitar 0% atau 100% baris yang dicampur dengan data yang sah. Seringkali, 0 dalam penyebut dapat menunjukkan kesalahan atau nilai yang hilang, dan Anda mungkin tidak ingin hanya mengisi nilai arbitrer hanya untuk membuat dataset Anda terlihat rapi.
sumber
Inilah cara saya memperbaikinya:
IIF (ValueA! = 0, Total / ValueA, 0)
Itu dapat dibungkus dengan pembaruan:
SET Pct = IIF (ValueA! = 0, Total / ValueA, 0)
Atau di pilih:
SELECT IIF (ValueA! = 0, Total / ValueA, 0) SEBAGAI Pct DARI Tablename;
Pikiran?
sumber
Anda dapat menangani kesalahan dengan tepat ketika merambat kembali ke program panggilan (atau mengabaikannya jika itu yang Anda inginkan). Dalam C # setiap kesalahan yang terjadi di SQL akan melempar pengecualian yang bisa saya tangkap dan kemudian menangani kode saya, sama seperti kesalahan lainnya.
Saya setuju dengan Beska karena Anda tidak ingin menyembunyikan kesalahan. Anda mungkin tidak berurusan dengan reaktor nuklir tetapi menyembunyikan kesalahan secara umum adalah praktik pemrograman yang buruk. Ini adalah salah satu alasan kebanyakan bahasa pemrograman modern menerapkan penanganan pengecualian terstruktur untuk memisahkan nilai pengembalian aktual dengan kode kesalahan / status. Ini terutama benar ketika Anda melakukan matematika. Masalah terbesar adalah bahwa Anda tidak dapat membedakan antara 0 yang dikembalikan dengan benar atau 0 sebagai hasil dari kesalahan. Sebaliknya nilai yang dikembalikan adalah nilai yang dihitung dan jika terjadi kesalahan pengecualian dilemparkan. Ini tentu saja akan berbeda tergantung pada bagaimana Anda mengakses database dan bahasa apa yang Anda gunakan tetapi Anda harus selalu bisa mendapatkan pesan kesalahan yang bisa Anda tangani.
sumber
Gunakan
NULLIF(exp,0)
tetapi dengan cara ini -NULLIF(ISNULL(exp,0),0)
NULLIF(exp,0)
istirahat jika expnull
tetapiNULLIF(ISNULL(exp,0),0)
tidak akan rusaksumber