SQL'de “sıfıra böl” hatasını nasıl önleyebilirim?


363

Bu hata iletisini aldım:

Msg 8134, Seviye 16, Durum 1, Hat 1 Sıfır hatayla bölün.

Bu hata iletisini bir daha asla görmeyeceğim şekilde SQL kodu yazmanın en iyi yolu nedir?

Aşağıdakilerden birini yapabilirim:

  • Bölücümün asla sıfır olmaması için where cümlesi ekle

Veya

  • Bir vaka ifadesi ekleyebilirim, böylece sıfır için özel bir tedavi var.

Bir NULLIFcümle kullanmanın en iyi yolu nedir?

Daha iyi bir yol var mı, yoksa bu nasıl uygulanabilir?


7
Belki de bazı veri doğrulamaları mümkündür.
Anthony

Yanıtlar:


644

"Sıfıra bölme" hatasını önlemek için, bunu şu şekilde programladık:

Select Case when divisor=0 then null
Else dividend / divisor
End ,,,

Ama işte bunu yapmanın çok daha güzel bir yolu var:

Select dividend / NULLIF(divisor, 0) ...

Şimdi tek sorun "/" tuşunu kullanırsam NullIf bitini hatırlamaktır.


13
Bunu yapmanın çok daha hoş bir yolu "Dividend / nullif (divisor, 0) ..." seç bölen NULL ise kırılır.
Anderson

8
@Anderson Bu hiç doğru değil. IsNullBunun yerine yanlışlıkla kullanmadığınızdan emin misiniz NullIf? Kendin dene! SELECT Value,1/NullIf(Value,0)FROM(VALUES(0),(5.0),(NULL))x(Value);"Mola" ile bir NULL döndürür mü demek? Bunu IsNullveya ile istediğiniz her şeye dönüştürebilirsiniz Coalesce.
ErikE

1
@ErikE, bu doğru ... çalıştırmayı dene ... 1 / nullif (null, 0) seçin ... "NULLIF için ilk bağımsız değişkenin türü NULL sabiti olamaz çünkü ilk bağımsız değişkenin türü bilinmek." Bunu "coalesce (FieldName, 0)" kullanarak halledin ... örneğin select 1 / nullif (coalesce (null, 0), 0) seçin
John Joseph

1
@JohnJoseph Benimle hemfikir olup olmadığınızı söyleyemem.
ErikE

1
@JohnJoseph Aldığınız hataya daha yakından bakın. Evet, SELECT 1 / NULLIF(NULL, 0)başarısız olur, ancak bunun nedeni NULLIF()ilk argümanın veri tipini bilmesidir. Bu değişmiş örnek çalışıyor: SELECT 1 / NULLIF(CAST(NULL AS INT), 0). Gerçek hayatta, NULLIF()bir NULLsabit yerine bir tablo sütunu tedarik edeceksiniz . Tablo sütunları bilinen veri türlerini sahip olduğundan, bu da para cezası çalışır: SELECT 1 / NULLIF(SomeNullableColumn, 0) FROM SomeTable.
MarredCheese

180

Sıfır döndürmek istiyorsanız, sıfır sapma olması durumunda şunları kullanabilirsiniz:

SELECT COALESCE(dividend / NULLIF(divisor,0), 0) FROM sometable

Sıfır olan her bölen için, sonuç kümesinde bir sıfır elde edersiniz.


9
Bazı kriterler COALESCE'in ISNULL'dan biraz daha yavaş olduğunu ortaya koyuyor. Ancak, COALESCE standartlarda olduğundan daha portatiftir.
Paul Chernoch

37
Birisi bunun neden işe yaradığını hemen anlamadıysa, d 0 ise NULLIF (d, 0) NULL döndürür. SQL'de NULL ile bölme NULL döndürür.
Coalesce

16
@SQLGeorge Argümanınıza katılırken, birisinin istatistiksel olarak doğru olanın matematiksel olarak doğru olandan daha fazla önem verdiği durumlar olduğunu lütfen unutmayın. Bazı durumlarda istatistik işlevlerini kullanırken, bölen sıfır olduğunda 0 veya hatta 1 kabul edilebilir bir sonuçtur.
Athafoud

10
Birisi bana bunun neden kötü olduğunu açıklayabilir mi? Bir yüzde bulmaya çalışıyorsam ve bölen sıfırsa, kesinlikle sonucun yüzde sıfır olmasını istiyorum.
Todd Sharp

10
@George ve @ James / Wilson'un sorulan soruyu temelde yanlış anladığını düşünüyorum. Teknik açıdan doğru olmasa bile, bir "0" döndürmenin uygun olduğu iş uygulamaları kesinlikle vardır.
Sean Branchaw

66

Verilerimde gerçekleşen sıfıra bölünmeyi ele almaya çalışırken durumum için en iyi düzeltme gibi görünüyordu.

Çeşitli okul kulüpleri için erkek-kadın oranlarını hesaplamak istediğinizi varsayalım, ancak aşağıdaki sorgunun başarısız olduğunu ve kadınları olmayan Yüzüklerin Efendisi Kulübü için oran hesaplamaya çalıştığında sıfıra bölünen bir hata verdiğini varsayın. :

SELECT club_id, males, females, males/females AS ratio
  FROM school_clubs;

NULLIFSıfıra bölmeyi önlemek için işlevi kullanabilirsiniz . NULLIFiki ifadeyi karşılaştırır ve eşitse ilk ifadeyi, aksi takdirde ilk ifadeyi döndürür.

Sorguyu şu şekilde yeniden yazın:

SELECT club_id, males, females, males/NULLIF(females, 0) AS ratio
  FROM school_clubs;

Herhangi bir sayı bölünerek NULLverir NULLve hata üretilmez.


6
Evet gerçekten de, yani YOL DAHA İYİ kadar çok upvotes var ki diğer cevaptan daha. Çözümünüzde, doğru sonuç veremeyeceğinizi gösteren en az NULL var. Ancak sonucu NULL'dan Zero'ya dönüştürürseniz, yanlış ve yanıltıcı sonuçlar elde edersiniz.
SQL Police

8
Eğer bir erkek / kadın oranı hesaplamak istiyorsanız bu arada, o zaman daha iyi böyle, toplamda karşılaştırmak için öneriyoruz: select males/(males+females), females/(males+females). Bu size bir kulüpteki erkek ve kadınların yüzde dağılımını verecektir, örneğin% 31 erkek,% 69 kadın.
SQL Polisi

44

Bunu, sorgunun başında da yapabilirsiniz:

SET ARITHABORT OFF 
SET ANSI_WARNINGS OFF

Yani böyle bir şey varsa 100/0NULL dönecektir. Bunu sadece basit sorgular için yaptım, bu yüzden daha uzun / karmaşık olanları nasıl etkileyeceğini bilmiyorum.


1
Benim için çalışıyor. Benim durumumda WHERE yan tümcesinde bölme işlemini kullanmak zorundayım. Sıfır bölücü olmadığından eminim, çünkü NEREDE dışarı yorum yaptığımda sonuçlarda sıfır değer yok. Ancak bir şekilde sorgu optimize edici filtreleme sırasında sıfıra bölünür. SET ARITHABORT OFF SET ve ANSI_WARNINGS OFF çalışır - 2 gün WHERE yan tümcesinde sıfıra bölünerek kavga ettikten sonra. Teşekkür!
huhu78

2
Bu "kirli" hissettiriyor ama onu seviyorum! Toplama ve CASE deyimi kullanan bir sorguda gerekli bir seçenek değildi, çünkü daha sonra sonuçları tamamen değiştirdi GROUP BY bu sütun eklemek zorunda kaldı. İlk sorguyu bir alt seçim yapmak ve sonra dış sorgu üzerinde bir GROUP BY yapmak da bölümü olduğu için sonuçları da değiştirir.
Andrew Steitz

1
Tamam, bu yüzden hala bu "çözümü" sevdim ama birçoğunuz muhtemelen hissettiği gibi, "daha temiz" bir yol olması gerektiğini hissettim. Uyarıları yeniden etkinleştirmeyi unutursam ne olur? Veya birisi kodumu kopyaladı (bu asla olmaz, değil mi?) Ve uyarıları düşünmedi mi? Her neyse, NULLIF () hakkında başka cevaplar gördüm. NULLIF () hakkında biliyordum ama NULL ile bölme NULL döndürme fark etmedi (bir hata olacağını düşündüm). Yani ... Şunlarla gittim: ISNULL ((SUM (foo) / NULLIF (SUM (bar), 0)), 0) AS Avg
Andrew Steitz

2
Bu çözümü bilmiyordum. Sevdiğimden emin değilim, ama bir gün bilmek yararlı olabilir. Çok teşekkür ederim.
Henrik Staun Poulsen

1
Bu en kolay çözümdür, ancak performansa zarar vereceğini unutmayın. Gönderen docs.microsoft.com/en-us/sql/t-sql/statements/... : "OFF ARITHABORT ayarlanması olumsuz performans sorunları giden sorgu optimizasyonu etkileyebilir."
mono blaine

36

Sorgunun bir hatayla kesilmesini durdurabilir ve NULLsıfıra bölme varsa geri dönebilirsiniz :

SELECT a / NULLIF(b, 0) FROM t 

Ancak, ben ederim ASLA ile Sıfır bu dönüştürmek coalescebirçok upvotes var bu diğer cevap gösterilmektedir gibi. Bu matematiksel anlamda tamamen yanlıştır ve uygulamanız muhtemelen yanlış ve yanıltıcı sonuçlar vereceğinden tehlikelidir.


32

DÜZENLEME: Bu son zamanlarda bir sürü downvotes alıyorum ... bu yüzden bu cevabın, en son düzenleme yapılmadan önce yazıldığını ve bir seçenek olarak null döndürülmesinin vurgulandığı bir not eklediğimi düşündüm. .Bu çok kabul edilebilir görünüyor. Cevabımın bir kısmı, 0 döndürmeyi savunuyor gibi görünen yorumlarda Edwardo'nunki gibi endişelere yönelmişti.

YANIT: Sanırım burada temel bir sorun var, yani 0'a bölünmesi yasal değil. Bir şeyin temelden yanlış olduğunun bir göstergesi. Sıfıra bölüyorsanız, matematiksel olarak anlamlı olmayan bir şey yapmaya çalışıyorsunuz, böylece alabileceğiniz sayısal bir cevap geçerli olmayacaktır. (Bu durumda null değeri kullanılması, daha sonraki matematiksel hesaplamalarda kullanılacak bir değer olmadığından makul olur).

Bu nedenle Edwardo, "kullanıcı 0 girerse ne olur?" Kullanıcı tutarı sıfır koyarsa ve bunu yaparken 0 döndürülmesini istiyorsanız, o değeri yakalamak ve 0 değerini döndürmek için iş kuralları düzeyinde kod girmelisiniz ... 0 ile bölmenin bazı özel durumları yoktur. 0.

Bu ince bir fark, ama önemli ... çünkü bir dahaki sefere bir kişi fonksiyonunuzu çağırdığında ve doğru şeyi yapmasını beklediğinde ve matematiksel olarak doğru olmayan korkak bir şey yapar, ancak sadece daha sonra birini ısırma şansı. Gerçekten 0'a bölmüyorsunuz ... sadece kötü bir soruya kötü bir cevap veriyorsunuz.

Bir şey kodladığımı ve berbat ettiğimi düşünün. Bir radyasyon ölçümü ölçekleme değerinde okumalıydım, ama garip bir uç durumda tahmin etmedim, 0'da okudum. Sonra değerimi işlevinize bırakıyorum ... bana 0 döndürdün! Yaşasın, radyasyon yok! Gerçekten orada ve sadece kötü bir değerden geçiyordum ... ama hiçbir fikrim yok. Bölmenin hatayı atmasını istiyorum çünkü bir şeylerin yanlış olduğu bayrağı.


15
Katılmıyorum. İş kurallarınız asla yasadışı matematik yapmamalıdır. Sonunda böyle bir şey yaparsanız, büyük olasılıkla veri modeliniz yanlıştır. 0 ile bir bölünme ile karşılaştığınızda, verilerin 0 yerine NULL olması gerekip gerekmediğini düşünmelisiniz.
Remus Rusanu

32
Hiç "gerçek bir programlama yaptım mı?" Diye soran biri tarafından reddedildiğime inanamıyorum. çünkü tembel olmak yerine doğru yapmayı söylüyorum.
çeker

11
Üzgünüm, seni gücendirmek istemedim. Ancak soru, birçok yaygın LOB uygulamasında mükemmel bir şekilde geçerlidir ve bunu "0'a bölmek yasal değildir" ile cevaplamak IMHO'ya değer katmaz.
Eduardo Molteni

2
@JackDouglas Doğru. Bu, iş kurallarının özel bir durumu özel bir şekilde ele almasını istediğiniz bir durumdur ... ancak boş bir alan döndüren temel matematik olmamalıdır. Bu iş kuralı olmalı. Kabul edilen cevap null değerini döndürür, bu da bunun üstesinden gelmenin iyi bir yoludur. Bir istisna atmak da iyi olur. SQL'e gitmeden önce onu tespit etmek ve işlemek tartışmalı olarak ideal olacaktır. Matematiksel olarak yanlış bir değer döndüren başka şeylerin çağırabileceği bir tür işlev sağlamak , gitmek için bir yol değildir , çünkü bu özel durum diğer arayanlar için geçerli olmayabilir.
Beska

4
@JackDouglas Evet, bu iyi bir özet, hemfikirim. Aslında soru "bu hatayı gizlemek için ne yapabilirim" şeklinde ifade edilmiş gibi görünüyordu. O zamandan beri gelişti. Bir null döndürmek, sonunda geldiği cevap, makul bir cevap gibi görünüyor. (0 ya da başka bir sayı döndürmemenizi şiddetle savunuyordum.)
Beska

28
SELECT Dividend / ISNULL(NULLIF(Divisor,0), 1) AS Result from table

Sıfırı bir nullif () ile yakaladıktan sonra, bir isnull () ile sonuçlanan null değerini bölmek, sıfır hata ile bölünmeyi atlatabilirsiniz.


3
Uzunluğu nedeniyle cevabınızın silinmesi önerildi. Her ne kadar önerdiğinize ilişkin küçük bir açıklama eklemek her zaman daha iyidir - çok basit görünse bile;)
Trinimon

10

"Sıfıra böl" ü sıfır ile değiştirmek tartışmalıdır - ancak tek seçenek de bu değildir. Bazı durumlarda 1 ile değiştirmek (makul) uygundur. Kendimi sık sık

 ISNULL(Numerator/NULLIF(Divisor,0),1)

Puanlara / sayılara kaymalara baktığımda ve verilerim yoksa varsayılan olarak 1'e ayarlamak istediğimde Örneğin

NewScore = OldScore *  ISNULL(NewSampleScore/NULLIF(OldSampleScore,0),1) 

Daha sık olmamakla birlikte, aslında bu oranı başka bir yerde hesapladım (en azından düşük paydalar için çok büyük ayarlama faktörleri atabildiği için.Bu durumda OldSampleScore için normal olarak kontrol edeceğim bir eşikten daha büyüktür; Ancak bazen 'hack' uygundur.


1
@N Mason; evet, bazen 1 bir seçenektir. Ancak ters eğik çizgiyi yazdığınızda ISNULL bölümünü nasıl hatırlarsınız?
Henrik Staun Poulsen

1
Üzgünüm Henrik - Soruyu anladığımdan emin değilim.
N Mason

6

Saklı yordamlar için işlemek için bir süre bir işlev yazdım :

print 'Creating safeDivide Stored Proc ...'
go

if exists (select * from dbo.sysobjects where  name = 'safeDivide') drop function safeDivide;
go

create function dbo.safeDivide( @Numerator decimal(38,19), @divisor decimal(39,19))
   returns decimal(38,19)
begin
 -- **************************************************************************
 --  Procedure: safeDivide()
 --     Author: Ron Savage, Central, ex: 1282
 --       Date: 06/22/2004
 --
 --  Description:
 --  This function divides the first argument by the second argument after
 --  checking for NULL or 0 divisors to avoid "divide by zero" errors.
 -- Change History:
 --
 -- Date        Init. Description
 -- 05/14/2009  RS    Updated to handle really freaking big numbers, just in
 --                   case. :-)
 -- 05/14/2009  RS    Updated to handle negative divisors.
 -- **************************************************************************
   declare @p_product    decimal(38,19);

   select @p_product = null;

   if ( @divisor is not null and @divisor <> 0 and @Numerator is not null )
      select @p_product = @Numerator / @divisor;

   return(@p_product)
end
go

2
Merhaba Ron, Güzel bir çözüm, ancak sınırlı bir veri tipi (4 ondalık basamak) vardır ve @ danışmanlarımız da negatif olabilir. Ve kullanımını nasıl zorlarsınız? TIA Henrik Staun Poulsen
Henrik Staun Poulsen

1
O sırada belirli bir sorun senaryosunu halletmeyi çok çabuk kestim. Tek geliştirici uygulaması, bu yüzden zorlama benim hafıza dışında çok zor değil. :-)
Ron Savage

5
Yazdırma ifadesine rağmen, saklı bir proc değil, skaler bir UDF. Sorgunun bir parçasıysa, MS-SQL'de sizi öldürür.
Mark Sowul

4
Mark Sowul'un skaler fonksiyonun ağrıya neden olacağı iddiasıyla anlaştım. Bu T-SQL'de korkunç bir öneri, yapma! Skaler Fonksiyonlar performans avcılarıdır! Satır içi tablo değerli işlev, SQL Server'daki tek iyi kullanıcı işlevleridir (muhtemelen iyi performans gösterebilen CLR işlevleri hariç).
Davos

4
  1. DivisorSıfırdan çıkmaya zorlayan bir CHECK kısıtlaması ekleyin
  2. Kullanıcının bu alana sıfır değer girememesi için forma bir doğrulayıcı ekleyin.

1
CHECK kısıtlamalarını gittikçe daha fazla sevmeye başladım.
Henrik Staun Poulsen

4

Güncelleme SQL'leri için:

update Table1 set Col1 = Col2 / ISNULL(NULLIF(Col3,0),1)

3
merhaba Vijay, Evet, bu işe yarayacak, ama ... NULL ile bölündüğünüz ISNULL kısmına dikkat edeceğim. Kullanıcıya bölen sıfır olduğu için sonucun bilinmediğini bildirmeyi tercih ederim.
Henrik Staun Poulsen

2
Beni karmaşık subQuery'de kurtardı, teşekkürler.
QMaster

3

'0 istisna ile bölünmeyi kapat' sihirli küresel ayarı yoktur. İşlem atmak zorundadır, çünkü x / 0'ın matematiksel anlamı NULL anlamından farklıdır, bu yüzden NULL döndüremez. Açık olanlarla ilgilentiğinizi ve sorgularınızın 0 bölen ile kayıtları ortadan kaldıracak ve bölünmeyi asla değerlendirmeyecek koşulları olduğunu varsayıyorum. Her zamanki 'gotcha', çoğu geliştiricinin SQL'in yordamsal diller gibi davranmasını ve mantıksal operatör kısa devresi sunmasını beklemesinden daha fazladır, ancak DEĞİLDİR . Bu makaleyi okumanızı tavsiye ederim: http://www.sqlmag.com/Articles/ArticleID/9148/pg/2/2.html


4
Böyle bir "Büyü küresel ayarı" var; ARITHABORT'u KAPATIN.
David Manheim

3

İşte sıfıra bölebileceğiniz bir durum. İş kuralı, envanter dönüşlerini hesaplamak için, bir dönem için satılan malların maliyetini almanız, yıllıklaştırmanızdır. Yıllık numarayı aldıktan sonra, o dönemin ortalama envanterine bölersiniz.

Üç aylık bir sürede meydana gelen stok dönüş sayısını hesaplamaya bakıyorum. 1.000 dolarlık üç aylık dönemde Mal Maliyeti'nin satıldığını hesapladım. Yıllık satış oranı 4.000 $ (1.000 $ / 3) * 12'dir. Başlangıç ​​envanteri 0'dır. Bitiş envanteri 0'dır. Ortalama envanterim şu an 0'dır. Yıllık 4000 $ satışım var ve stok yok. Bu sonsuz sayıda dönüş verir. Bu, tüm envanterimin müşteriler tarafından dönüştürülüp satın alındığı anlamına gelir.

Bu, envanter dönüşlerinin nasıl hesaplanacağına ilişkin bir iş kuralıdır.


3
Evet, sonsuz sayıda dönüşünüz olur. Bu durumda, sıfıra bölme işleminiz varsa, '#INF' gibi bir şey göstermelisiniz.
SQL Police

1
"Başlangıç ​​envanteri 0. Bitiş envanteri 0. Ortalama envanterim şimdi 0." Hesaplamanız bir tahmindir. Bir zamanlar envanter pozitiftir veya hiçbir şey gönderemez / satamazsınız. Sonuç olarak + ∞ ile memnun değilseniz, ortalama envanter için daha iyi bir tahmin kullanın.
Tom Blodget

2
CREATE FUNCTION dbo.Divide(@Numerator Real, @Denominator Real)
RETURNS Real AS
/*
Purpose:      Handle Division by Zero errors
Description:  User Defined Scalar Function
Parameter(s): @Numerator and @Denominator

Test it:

SELECT 'Numerator = 0' Division, dbo.fn_CORP_Divide(0,16) Results
UNION ALL
SELECT 'Denominator = 0', dbo.fn_CORP_Divide(16,0)
UNION ALL
SELECT 'Numerator is NULL', dbo.fn_CORP_Divide(NULL,16)
UNION ALL
SELECT 'Denominator is NULL', dbo.fn_CORP_Divide(16,NULL)
UNION ALL
SELECT 'Numerator & Denominator is NULL', dbo.fn_CORP_Divide(NULL,NULL)
UNION ALL
SELECT 'Numerator & Denominator = 0', dbo.fn_CORP_Divide(0,0)
UNION ALL
SELECT '16 / 4', dbo.fn_CORP_Divide(16,4)
UNION ALL
SELECT '16 / 3', dbo.fn_CORP_Divide(16,3)

*/
BEGIN
    RETURN
        CASE WHEN @Denominator = 0 THEN
            NULL
        ELSE
            @Numerator / @Denominator
        END
END
GO

Çözümünüzü sevmiyorum, çünkü bir UDF kullanmak sorguyu tek bir iş parçacığı modunda çalışmaya zorlar. Test kurulumunu beğendim. Bunu tüm UDF'lerde görmek istiyorum.
Henrik Staun Poulsen

Benim için bu çözüm mükemmel ve zarif
Payedimaunt

@Payedimaunt; evet, UDF'ler çok zarif bir koda yol açar. Ancak iyi performans göstermiyor. Bu "uyku hapları üzerinde imleçler" dir. :-) Ayrıca sıradan bir "/" yerine dbo.Divide yazmayı hatırlamak zor
Henrik Staun Poulsen

1

0 değeri almamak için where cümlesi kullanarak verileri filtreleyin.


1

Bazen 0 uygun olmayabilir, ancak bazen 1 de uygun olmayabilir. Bazen yüzde 1 veya yüzde 100 değişiklik olarak tanımlanan 0 ile 100.000.000 arasındaki bir sıçrama da yanıltıcı olabilir. Bu senaryoda yüzde 100.000.000 uygun olabilir. Bu, yüzdelere veya oranlara dayanarak ne tür sonuçlar çıkarmak istediğinize bağlıdır.

Örneğin, satılan 2-4'ten çok küçük satış yapan bir ürün ve 1.000.000'dan 2.000.000 satılan çok büyük bir satış ürünü bir analiste veya yönetime çok farklı şeyler ifade edebilir, ancak her ikisi de% 100 veya 1 olarak ortaya çıkabilir. değişiklik.

NULL değerlerini izole etmek, meşru verilerle karıştırılmış% 0 veya% 100 satırlık bir grup üzerinden ovmaktan daha kolay olabilir. Genellikle, paydadaki bir 0 bir hatayı veya eksik bir değeri gösterebilir ve sadece veri kümenizin düzenli görünmesini sağlamak için rastgele bir değer doldurmak istemeyebilirsiniz.

CASE
     WHEN [Denominator] = 0
     THEN NULL --or any value or sub case
     ELSE [Numerator]/[Denominator]
END as DivisionProblem

1
Sorunun, bir bölünme yapmak istediğinizde bir şeyler yapmayı hatırlamak olduğunu görüyorum. CASE veya NULLIF eklemeyi hatırlayamazsanız, Pazartesi sabahı x hafta içinde bir destek vakası alırsınız. Bundan nefret ediyorum.
Henrik Staun Poulsen

1

Ben böyle giderdim:

IIF (DeğerA! = 0, Toplam / DeğerA, 0)

Bir güncellemeye sarılabilir:

SET Pct = IIF (DeğerA! = 0, Toplam / DeğerA, 0)

Veya bir seçimde:

SELECT IIF (ValueA! = 0, Toplam / ValueA, 0) AS Tablename'den Pct;

Düşünceler?


Ben ve diğerleri "bilinmeyen" i sıfırla değiştirmenin tehlikeli bir çözüm olduğunu görüyoruz. NULL'u çok tercih ederim. Ama zor olan, tüm bölümlere iif veya nullif eklemeyi hatırlamaktır!
Henrik Staun Poulsen

0

Hata, çağıran programa geri yayıldığında uygun şekilde işleyebilir (veya istediğiniz şeyse yoksayabilirsiniz). C # SQL'de oluşan herhangi bir hata, diğer tüm hatalar gibi, kodumu işleyip yakalayabileceğim bir istisna atar.

Hatayı gizlemek istemediğiniz için Beska'ya katılıyorum. Bir nükleer reaktörle uğraşmıyor olabilirsiniz ancak genel olarak hataları gizlemek kötü programlama uygulamasıdır. Bu, çoğu modern programlama dilinin, gerçek dönüş değerini bir hata / durum koduyla ayırmak için yapılandırılmış istisna işleme uygulamasının nedenlerinden biridir. Bu özellikle matematik yaparken geçerlidir. En büyük sorun, döndürülen doğru hesaplanmış 0 veya bir hata sonucunda 0'ı ayırt edememenizdir. Bunun yerine, döndürülen herhangi bir değer hesaplanan değerdir ve bir şey ters giderse bir istisna atılır. Bu elbette veritabanına nasıl eriştiğinize ve hangi dili kullandığınıza bağlı olarak değişecektir, ancak her zaman başa çıkabileceğiniz bir hata mesajı alabilmeniz gerekir.

try
{
    Database.ComputePercentage();
}
catch (SqlException e)
{
    // now you can handle the exception or at least log that the exception was thrown if you choose not to handle it
    // Exception Details: System.Data.SqlClient.SqlException: Divide by zero error encountered.
}

1
Sanırım hepimiz hatayı 0 ile gizlemenin bir çözüm olmadığını kabul ediyoruz. Ne teklif her "/" bir "NULLIF" izler, böylece bizim kod yazmaktır. Bu şekilde raporum / nükleer reaktör yalnız bırakılmıyor, ama bu sinir bozucu hata Msg 8134 yerine bir "NULL" gösteriyor. Bu nedenle, bölen 0 olduğunda farklı bir işleme ihtiyacım olursa Beska ve katılıyorum. Bunu kodlamamız gerekiyor. Her "/" yazışınızda bunu yapmak zordur. "/ NULLIF" her seferinde yapmak imkansız değildir.
Henrik Staun Poulsen

0

Kullanın NULLIF(exp,0)ama bu şekilde -NULLIF(ISNULL(exp,0),0)

NULLIF(exp,0)exp ise nullama NULLIF(ISNULL(exp,0),0)kırılmazsa kırılır


1
NULLIF (exp, 0) elde edemiyorum, 0 sıfırsa, o değil. Deneyin; DECLARE @i INT SELECT 1 / NULLIF (@i, 0) 'ı kırıp kırmayacağınızı görmek için.
Henrik Staun Poulsen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.