SQL में "शून्य से विभाजित" त्रुटि से कैसे बचें?


363

मेरे पास यह त्रुटि संदेश है:

Msg 8134, स्तर 16, राज्य 1, पंक्ति 1 शून्य त्रुटि से विभाजित का सामना करना पड़ा।

SQL कोड लिखने का सबसे अच्छा तरीका क्या है कि मैं इस त्रुटि संदेश को फिर कभी नहीं देख पाऊंगा?

मैं निम्नलिखित में से कोई भी कर सकता था:

  • एक खंड जोड़ें, ताकि मेरा भाजक कभी शून्य न हो

या

  • मैं एक केस स्टेटमेंट जोड़ सकता था, ताकि शून्य के लिए एक विशेष उपचार हो।

NULLIFक्लॉज का उपयोग करने का सबसे अच्छा तरीका है ?

क्या बेहतर तरीका है, या इसे कैसे लागू किया जा सकता है?


7
शायद कुछ डेटा सत्यापन क्रम में है।
एंथनी

जवाबों:


644

"शून्य बाय डिवीजन" त्रुटि से बचने के लिए हमने इसे इस तरह से प्रोग्राम किया है:

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

लेकिन यहाँ यह करने का एक अच्छा तरीका है:

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

अब एकमात्र समस्या NullIf बिट को याद रखना है, अगर मैं "/" कुंजी का उपयोग करता हूं।


13
इसे करने का एक बहुत अच्छा तरीका है "लाभांश / nullif (भाजक, 0) ..." का चयन करें यदि विभाजक NULL है।
एंडरसन

8
@ एंडरसन यह सच नहीं है। क्या आप वाकई IsNullइसके बजाय गलती से उपयोग नहीं कर रहे हैं NullIf? इसे स्वयं आज़माएं! SELECT Value,1/NullIf(Value,0)FROM(VALUES(0),(5.0),(NULL))x(Value);जब तक "विराम" का अर्थ है कि आप एक पूर्ण रिटर्न नहीं देते हैं? आप जो चाहें उसके साथ परिवर्तित कर सकते हैं IsNullया कर सकते हैं Coalesce
एरिके

1
@EricE, यह सच है ... चलाने का प्रयास करें ... 1 / nullif (शून्य, 0) का चयन करें ... आपको "NULLIF के पहले तर्क का प्रकार NULL स्थिर नहीं हो सकता है क्योंकि पहले तर्क का प्रकार है पहचाने जाने के लिए।" "Coalesce (FieldName, 0)" का उपयोग करके इसे संभालें ... उदाहरण के लिए 1 / nullif का चयन करें (coalesce (null, 0), 0)
John Joseph

1
@JohnJoseph मैं नहीं बता सकता कि आप मुझसे सहमत हैं या मेरे साथ बहस कर रहे हैं।
एरिक

1
@JohnJoseph आपको मिली त्रुटि के करीब देखें। हां, SELECT 1 / NULLIF(NULL, 0)विफल रहता है, लेकिन यह इसलिए है क्योंकि NULLIF()पहले तर्क के डेटाटाइप को जानने की जरूरत है। यह परिवर्तित उदाहरण ठीक काम करता है SELECT 1 / NULLIF(CAST(NULL AS INT), 0):। वास्तविक जीवन में, आप NULLIF()एक NULLनिरंतर के बजाय एक तालिका स्तंभ की आपूर्ति करने जा रहे हैं । चूंकि टेबल कॉलम में डेटाटाइप्स ज्ञात हैं, इसलिए यह ठीक भी काम करता है SELECT 1 / NULLIF(SomeNullableColumn, 0) FROM SomeTable:।
मार्रेडेसेज़

180

यदि आप शून्य लौटाना चाहते हैं, तो शून्य विचलन होने पर, आप इसका उपयोग कर सकते हैं:

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

प्रत्येक भाजक के लिए जो शून्य है, आपको परिणाम सेट में शून्य मिलेगा।


9
कुछ बेंचमार्क बताते हैं कि COALESCE ISNULL की तुलना में थोड़ा धीमा है। हालांकि, मानकों मानकों में है इसलिए अधिक पोर्टेबल है।
पॉल चेरोच

37
अगर किसी और को तुरंत यह नहीं मिलता है कि यह क्यों काम करता है, तो NULLIF (d, 0) NULL वापस आ जाएगा यदि d 0. है। SQL में, NULL रिटर्न NULL से विभाजित होता है।
कोलेस

16
@SQLGeorge जबकि मैं आपके तर्क से सहमत हूं, कृपया ध्यान दें कि ऐसे मामले हैं जो गणितीय रूप से सही होने की तुलना में सांख्यिकीय रूप से अधिक सही हैं। कुछ मामलों में जब सांख्यिकी फ़ंक्शन का उपयोग करते हैं, तो 0 या 1 भी स्वीकार्य परिणाम होता है जब विभाजक शून्य होता है।
अथफौड

10
क्या कोई मुझे समझा सकता है कि यह बुरा क्यों है? यदि मैं एक प्रतिशत का पता लगाने की कोशिश कर रहा हूं और विभाजक शून्य है तो मैं निश्चित रूप से परिणाम शून्य प्रतिशत होना चाहता हूं।
टोड शार्प

10
मुझे लगता है कि @George और @ James / Wilson मूल रूप से पूछे जा रहे प्रश्न को गलत समझते हैं। निश्चित रूप से व्यावसायिक अनुप्रयोग हैं जहां "0" वापस करना उचित है, भले ही यह गणितीय दृष्टिकोण से तकनीकी रूप से सच न हो।
सीन ब्रान्चव

66

यह मेरी स्थिति के लिए सबसे अच्छा तय लग रहा था जब शून्य से विभाजित करने की कोशिश कर रहा था, जो मेरे डेटा में होता है।

मान लीजिए कि आप विभिन्न स्कूल क्लबों के लिए पुरुष-महिला अनुपातों की गणना करना चाहते हैं, लेकिन आपको पता चलता है कि निम्न क्वेरी विफल हो जाती है और डिवाइड-बाय-ज़ीरो त्रुटि जारी करती है, जब वह लॉर्ड ऑफ द रिंग्स क्लब के लिए अनुपात की गणना करने की कोशिश करती है, जिसमें कोई महिला नहीं होती है :

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

आप NULLIFशून्य से विभाजन से बचने के लिए फ़ंक्शन का उपयोग कर सकते हैं । NULLIFदो अभिव्यक्तियों की तुलना करता है और यदि वे समान हैं या पहली अभिव्यक्ति अन्यथा शून्य हैं।

क्वेरी को इस रूप में फिर से लिखें:

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

कोई भी संख्या NULLदेता है NULL, और कोई त्रुटि उत्पन्न नहीं होती है।


6
हां वास्तव में, यह उस अन्य उत्तर की तुलना में अधिक बेहतर है , जिसे बहुत सारे उत्थान मिले हैं। आपके समाधान में, आपके पास कम से कम एक NULL है, जो इंगित करता है कि आप एक सही परिणाम प्रदान नहीं कर सकते हैं। लेकिन अगर आप परिणाम को NULL से शून्य में बदलते हैं, तो आपको बस गलत और भ्रामक परिणाम मिलते हैं।
SQL पुलिस

8
वैसे, यदि आप पुरुष / महिला अनुपात की गणना करना चाहते हैं, तो मैं इसे इस तरह कुल की तुलना में बेहतर बनाने का सुझाव देता हूं select males/(males+females), females/(males+females):। यह आपको एक क्लब में पुरुषों और महिलाओं का प्रतिशत वितरण देगा, जैसे कि 31% पुरुष, 69% महिलाएं।
SQL पुलिस

44

आप इसे क्वेरी की शुरुआत में भी कर सकते हैं:

SET ARITHABORT OFF 
SET ANSI_WARNINGS OFF

तो अगर आपके पास कुछ ऐसा है 100/0तो वह NULL को लौटा देगा। मैंने इसे केवल सरल प्रश्नों के लिए किया है, इसलिए मुझे नहीं पता कि यह कैसे लंबे / जटिल लोगों को प्रभावित करेगा।


1
मेरे लिये कार्य करता है। मेरे मामले में मुझे WHERE क्लॉज में डिवाइड ऑपरेशन का उपयोग करना होगा। मुझे यकीन है कि कोई शून्य विभक्त नहीं है, क्योंकि जब मैं बाहर टिप्पणी करता हूं, तो परिणामों पर कोई शून्य मान नहीं होता है। लेकिन किसी तरह क्वेरी ऑप्टिमाइज़र फ़िल्टर करते समय शून्य से विभाजित करते हैं। SET ARITHABORT OFF SET और ANSI_WARNINGS इसे बंद कर दें - 2 दिनों के बाद लड़ाई में शून्य से विभाजित होने के बाद WHERE क्लॉज पर काम करें। धन्यवाद!
हुहु7878

2
यह "लगता है" इतना गंदा है लेकिन मैं इसे प्यार करता हूँ! इसे एक ऐसे प्रश्न की आवश्यकता थी जो एकत्रीकरण करता है और CASE कथन का उपयोग नहीं करता है क्योंकि तब मुझे उस कॉलम को GROUP BY में जोड़ना था, जिससे परिणाम पूरी तरह से बदल गए। प्रारंभिक क्वेरी को एक सबसेलेक्ट बनाना और फिर बाहरी क्वेरी पर एक ग्रुप बीवाई करने से भी परिणाम बदलते हैं क्योंकि इसमें विभाजन शामिल है।
एंड्रयू स्टीट्ज

1
ठीक है, इसलिए मैं अभी भी इस "समाधान" को पसंद करता हूं, लेकिन आप में से कई लोग शायद महसूस करते हैं, मुझे लगा कि "क्लीनर" तरीका होना चाहिए। क्या होगा अगर मैं चेतावनियों को फिर से सक्षम करना भूल गया? या किसी ने मेरे कोड को बंद कर दिया (जो कभी नहीं होता है, ठीक है?) और चेतावनियों के बारे में नहीं सोचा? वैसे भी, NULLIF () के बारे में अन्य उत्तर देखे गए। मुझे NULLIF () के बारे में पता था लेकिन NULL रिटर्न NULL द्वारा विभाजित करने का एहसास नहीं हुआ (मुझे लगा कि यह एक त्रुटि होगी)। इसलिए ... मैं निम्नलिखित के साथ गया: ISNULL ((SUM (foo) / NULLIF (SUM (बार), 0)), 0) AS औसत
एंड्रयू स्टिट्ज

2
मुझे इसका समाधान नहीं पता था। मुझे यकीन नहीं है कि मुझे यह पसंद है, लेकिन किसी दिन यह जानना उपयोगी हो सकता है। आपका बहुत बहुत धन्यवाद।
हेनरिक स्टॉउन पॉल्सेन

1
यह सबसे आसान समाधान है, लेकिन ध्यान दें कि यह प्रदर्शन को नुकसान पहुंचाएगा। से docs.microsoft.com/en-us/sql/t-sql/statements/... : "बंद करने के लिए ARITHABORT स्थापना नकारात्मक क्वेरी अनुकूलन प्रदर्शन के मुद्दों के लिए अग्रणी प्रभावित कर सकता है।"
मोनो ब्लाइंड

36

आप कम से कम क्वेरी को त्रुटि से तोड़ने से रोक सकते हैं और NULLयदि शून्य से कोई विभाजन है तो वापस लौटें :

SELECT a / NULLIF(b, 0) FROM t 

हालाँकि, मैं इसे शून्य में परिवर्तित नहीं करूंगा क्योंकि coalesceयह उस अन्य उत्तर में दिखाया गया है, जिसमें बहुत सारे बदलाव हुए। यह गणितीय अर्थों में पूरी तरह से गलत है, और यह और भी खतरनाक है क्योंकि आपका आवेदन गलत और भ्रामक परिणाम देगा।


32

संपादित करें: मुझे इस पर हाल ही में बहुत सारे डाउनवोट मिल रहे हैं ... तो मैंने सोचा कि मैं सिर्फ एक नोट जोड़ूंगा कि यह उत्तर प्रश्न के पहले लिखा गया था, यह सबसे हाल ही में संपादित किया गया है, जहां वापस लौटने को विकल्प के रूप में उजागर किया गया था। जो बहुत स्वीकार्य लगता है। मेरे कुछ जवाब, एडवर्डो की तरह की चिंताओं को संबोधित करते थे, टिप्पणियों में, जो एक 0. लौटाने की वकालत करते दिख रहे थे। यह वह मामला है जिसके खिलाफ मैं रेलिंग कर रहा था।

उत्तर: मुझे लगता है कि यहाँ एक अंतर्निहित मुद्दा है, जो कि 0 से विभाजन वैध नहीं है। यह एक संकेत है कि कुछ fundementally गलत है। यदि आप शून्य से विभाजित कर रहे हैं, तो आप कुछ ऐसा करने की कोशिश कर रहे हैं जो गणितीय रूप से समझ में नहीं आता है, इसलिए कोई भी संख्यात्मक उत्तर जो आप प्राप्त कर सकते हैं वह मान्य नहीं होगा। (इस मामले में अशक्त का उपयोग उचित है, क्योंकि यह ऐसा मूल्य नहीं है जिसे बाद की गणितीय गणना में उपयोग किया जाएगा)।

तो एडवर्डो टिप्पणियों में पूछता है "अगर उपयोगकर्ता 0 में डालता है तो क्या होगा?", और वह वकालत करता है कि बदले में 0 प्राप्त करना ठीक होना चाहिए। यदि उपयोगकर्ता राशि में शून्य डालता है, और आप 0 चाहते हैं जब वे ऐसा करते हैं, तो आपको उस मूल्य को पकड़ने के लिए व्यावसायिक नियमों के स्तर पर कोड डालना चाहिए और 0 वापस करना चाहिए ... कुछ विशेष मामला नहीं है जहां 0 = द्वारा विभाजन होता है 0।

यह एक सूक्ष्म अंतर है, लेकिन यह महत्वपूर्ण है ... क्योंकि अगली बार जब कोई आपके फ़ंक्शन को कॉल करता है और यह अपेक्षा करता है कि वह सही काम करेगा, और यह कुछ ऐसा कायरता करता है जो गणितीय रूप से सही नहीं है, लेकिन बस उस विशेष किनारे के मामले को संभालता है जो इसे मिल गया है बाद में किसी को काटने का अच्छा मौका। आप वास्तव में 0 से विभाजित नहीं कर रहे हैं ... आप एक बुरे प्रश्न का एक बुरा उत्तर दे रहे हैं।

कल्पना कीजिए कि मैं कुछ कोड कर रहा हूं, और मैं इसे खराब कर रहा हूं। मुझे एक विकिरण माप स्केलिंग मान में पढ़ना चाहिए, लेकिन एक अजीब धार वाले मामले में जिसका मैंने अनुमान नहीं किया था, मैंने 0. में पढ़ा था। फिर मैंने अपने मूल्य को आपके फ़ंक्शन में छोड़ दिया ... आप मुझे 0 पर लौटाएं! हुर्रे, कोई विकिरण नहीं! सिवाय इसके कि वास्तव में वहाँ है और यह सिर्फ इतना है कि मैं एक बुरे मूल्य में गुजर रहा था ... लेकिन मुझे पता नहीं है। मैं चाहता हूं कि विभाजन त्रुटि को फेंक दे क्योंकि यह झंडा है कि कुछ गलत है।


15
मैं असहमत हूं। आपके व्यवसाय के नियमों को कभी भी अवैध गणित को समाप्त नहीं करना चाहिए। यदि आप ऐसा कुछ करते हैं तो आपके डेटा मॉडल के गलत होने की संभावना है। जब भी आप 0 से विभाजित करते हैं तो आपको विचार करना चाहिए कि क्या डेटा 0. के बजाय NULL होना चाहिए था
Remus Rusanu

32
मुझे विश्वास नहीं हो रहा है कि मुझे किसी ऐसे व्यक्ति ने उकसाया था जो पूछता है कि क्या मैंने कभी "कोई वास्तविक प्रोग्रामिंग की है?" क्योंकि मैं इसे सही करने के लिए कह रहा हूं, बजाय आलसी होने के। sigh
बेसका

11
मुझे क्षमा करें, मेरा मतलब आपको अपमानित करना नहीं था। लेकिन यह सवाल बहुत सारे सामान्य एलओबी अनुप्रयोगों में पूरी तरह से मान्य है, और "0 से विभाजन नहीं है" के साथ इसका जवाब देना मूल्य आईएमएचओ को नहीं जोड़ता है।
एडुआर्डो मोल्टनी

2
@JackDouglas राइट। यह एक ऐसा मामला है जहां आप चाहते हैं कि व्यावसायिक नियम एक विशेष मामले को एक विशेष तरीके से संभालें ... लेकिन यह अंतर्निहित गणित नहीं होना चाहिए जो एक खाली रिटर्न देता है। यह व्यापार नियम होना चाहिए। स्वीकृत उत्तर एक शून्य देता है, जो इसे संभालने का एक अच्छा तरीका है। अपवाद फेंकना भी ठीक होगा। एसक्यूएल में जाने से पहले इसे खोलना और संभालना यकीनन आदर्श होगा। कुछ प्रकार के फ़ंक्शन प्रदान करना जो अन्य चीजों को कॉल कर सकते हैं जो गणितीय रूप से गलत मान लौटाते हैं वे जाने का तरीका नहीं है, क्योंकि यह विशेष मामला उन अन्य कॉलर्स के लिए लागू नहीं हो सकता है।
बेसका

4
@JackDouglas हां, यह एक अच्छा सारांश है, जिससे मैं सहमत हूं। मूल रूप से सवाल यह था कि "मैं इस त्रुटि को छिपाने के लिए क्या कर सकता हूं।" तब से, यह विकसित हुआ है। एक अशक्त लौटते हुए, वह जवाब जो वह अंततः आता है, एक उचित पुनरावृत्ति की तरह लगता है। (मैं दृढ़ता से 0, या किसी अन्य संख्या को वापस नहीं करने की वकालत कर रहा था।)
बेस्का

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

शून्य को nullif () के साथ पकड़कर, फिर isnull () के साथ परिणामी नल को आप शून्य त्रुटि द्वारा अपने विभाजन को दरकिनार कर सकते हैं।


3
इसकी लंबाई के कारण आपके उत्तर को हटाने के लिए सिफारिश की गई है। ध्यान दें कि जो भी आप सुझाव दे रहे हैं उसका एक छोटा सा विवरण जोड़ना हमेशा बेहतर होता है - भले ही यह बहुत सरल लगता है;)
त्रिनिमोन

10

शून्य से "डिवाइड बाय जीरो" को बदलना विवादास्पद है - लेकिन यह एकमात्र विकल्प भी नहीं है। कुछ मामलों में 1 के साथ प्रतिस्थापित करना (यथोचित) उचित है। मैं अक्सर खुद का इस्तेमाल कर पाता हूं

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

जब मैं स्कोर / काउंट में बदलाव देख रहा हूं, और यदि मेरे पास डेटा नहीं है तो 1 को डिफ़ॉल्ट करना चाहता हूं। उदाहरण के लिए

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

अधिक बार नहीं, मैंने वास्तव में इस अनुपात को कहीं और गणना की है (कम से कम नहीं है क्योंकि यह कम भाजक के लिए कुछ बहुत बड़े समायोजन कारक फेंक सकता है। इस मामले में मैं आमतौर पर ओल्डस्प्लोरकोर के लिए नियंत्रण एक सीमा से अधिक होगा; जो तब शून्य को रोकता है। .लेकिन कभी-कभी 'हैक' करना उचित होता है।


1
@ एन मेसन; हाँ, कभी-कभी 1 एक विकल्प है। लेकिन जब आप बैकस्लैश टाइप करते हैं, तो आपको ISNULL भाग कैसे याद है?
हेनरिक स्टॉउन पॉल्सन

1
सॉरी हेनरिक - मुझे यकीन नहीं है कि मैं सवाल समझ गया हूँ।
एन मेसन

6

मैंने अपनी संग्रहीत प्रक्रियाओं के लिए इसे संभालने के लिए कुछ समय पहले एक फ़ंक्शन लिखा था :

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
हाय रॉन, अच्छा समाधान, सिवाय इसके कि एक सीमित डेटा प्रकार (4 दशमलव स्थान) हैं और हमारे @divisers नकारात्मक भी हो सकते हैं। और आप इसे कैसे लागू करते हैं? टीआईए हेनरिक स्टॉउन पॉल्सेन
हेनरिक स्टॉन पॉल्सन

1
मैं समय पर एक विशेष समस्या परिदृश्य को संभालने के लिए इसे बहुत जल्दी बंद कर दिया। एकल डेवलपर ऐप, इसलिए मेरी स्मृति को छोड़कर इतना मुश्किल नहीं प्रवर्तन। :-)
रॉन सैवेज

5
प्रिंट स्टेटमेंट के बावजूद, यह एक संग्रहित खरीद नहीं है, यह एक स्केल यूडीएफ है। यदि यह किसी क्वेरी का हिस्सा है तो यह आपको MS-SQL में मार देगा।
मार्क सोउल

4
मैं मार्क सोउल की इस बात से सहमत था कि अदिश क्रिया से दर्द होगा। यह टी-एसक्यूएल में एक भयानक सुझाव है, यह मत करो! स्केलर फ़ंक्शंस प्रदर्शन विध्वंसक हैं! इन-लाइन टेबल वैल्यू फ़ंक्शन SQL सर्वर में केवल अच्छे उपयोगकर्ता फ़ंक्शन हैं (संभवतः सीएलआर फ़ंक्शन के अपवाद के साथ जो अच्छा प्रदर्शन कर सकते हैं)।
दावोस

4
  1. एक CHECK बाधा जोड़ें जो Divisorगैर-शून्य होने के लिए मजबूर करता है
  2. प्रपत्र में एक सत्यापनकर्ता जोड़ें ताकि उपयोगकर्ता इस क्षेत्र में शून्य मान दर्ज न कर सके।

1
मुझे अच्छा लगने लगा है कि CHECK अधिक से अधिक बाधाओं का सामना करता है।
हेनरिक स्टॉउन पोल्सेन

4

अद्यतन एसक्यूएल के लिए:

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

3
हाय विजय, हाँ, यह काम करेगा, लेकिन ... मैं ISNULL भाग के बारे में सावधान रहूँगा, जहाँ आप NULL द्वारा विभाजन समाप्त करते हैं। मैं उपयोगकर्ता को संकेत दूंगा कि परिणाम अज्ञात है क्योंकि भाजक शून्य है।
हेनरिक स्टॉउल पॉल्सेन

2
यह मुझे जटिल उप-व्यापार में सहेजा गया है, धन्यवाद।
QMaster

3

कोई जादू वैश्विक सेटिंग नहीं है 'टर्न डिवीजन बाय 0 अपवाद बंद'। ऑपरेशन को फेंकना होगा, क्योंकि x / 0 का गणितीय अर्थ NULL अर्थ से अलग है, इसलिए यह NULL को वापस नहीं कर सकता है। मुझे लगता है कि आप स्पष्ट का ख्याल रख रहे हैं और आपके प्रश्नों में ऐसी स्थितियां हैं जो 0 विभाजक के साथ रिकॉर्ड को खत्म कर देना चाहिए और विभाजन का मूल्यांकन कभी नहीं करना चाहिए। सामान्य 'गेटचा' अधिकांश डेवलपर्स की अपेक्षा है कि एसक्यूएल प्रक्रियात्मक भाषाओं की तरह व्यवहार करे और तार्किक ऑपरेटर शॉर्ट-सर्किट की पेशकश करे, लेकिन यह नहीं है । मैं आपको इस लेख को पढ़ने की सलाह देता हूं: http://www.sqlmag.com/Articles/ArticleID/9148/pg/in/in.html


4
इस तरह की "मैजिक ग्लोबल सेटिंग" है; सेट ARITHABORT OFF।
डेविड मैनहेम

3

यहां एक ऐसी स्थिति है जहां आप शून्य से विभाजित कर सकते हैं। व्यापार नियम यह है कि इन्वेंट्री टर्न की गणना करने के लिए, आप एक अवधि के लिए बेचे गए सामानों की लागत लेते हैं, इसे वार्षिक करते हैं। आपके पास वार्षिक संख्या होने के बाद, आप अवधि के लिए औसत इन्वेंट्री द्वारा विभाजित करते हैं।

मैं तीन महीने की अवधि में होने वाले इन्वेंट्री टर्न की संख्या की गणना कर रहा हूं। मैंने गणना की है कि मेरे पास 1,000 डॉलर के तीन महीने की अवधि के दौरान बिकने वाले सामान की लागत है। बिक्री की वार्षिक दर $ 4,000 ($ 1,000 / 3) * 12 है। शुरुआती इन्वेंट्री है। एंडिंग इन्वेंट्री है। 0. मेरी औसत इन्वेंट्री अब 0. है। मेरे पास प्रति वर्ष $ 4000 की बिक्री है, और कोई इन्वेंट्री नहीं है। यह कई अनंत बार पैदावार देता है। इसका मतलब है कि मेरी सभी इन्वेंट्री को ग्राहकों द्वारा परिवर्तित और खरीदा जा रहा है।

यह एक व्यापारिक नियम है कि इन्वेंट्री टर्न की गणना कैसे करें।


3
हां, फिर आपके पास अनंत संख्या में मोड़ हैं। तो इस मामले में, यदि आपके पास शून्य से एक विभाजन है, तो आपको '#INF' जैसा कुछ दिखाना चाहिए।
एसक्यूएल पुलिस

1
"शुरुआती इन्वेंटरी 0. है। एंडिंग इनवेंटरी 0. है। मेरी औसत इन्वेंट्री अब 0. है।" आपकी गणना एक अनुमान है। कुछ समय में इन्वेंट्री पॉजिटिव है या आप कुछ भी शिप / बेच नहीं सकते हैं। यदि आप परिणामस्वरूप + ppy से नाखुश हैं, तो औसत इन्वेंट्री के बेहतर अनुमान का उपयोग करें।
टॉम ब्लोडेट

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

मुझे आपका समाधान पसंद नहीं है, क्योंकि UDF का उपयोग करने से क्वेरी को एकल थ्रेडेड मोड में चलाने के लिए बाध्य किया जाता है। मुझे आपका टेस्ट सेटअप पसंद है। मैं चाहूंगा कि हमारे सभी यू.डी.एफ.
हेनरिक स्टॉउन पॉल्सेन

मेरे लिए यह समाधान एकदम सही और सुरुचिपूर्ण है
पेएडिमांट

@Payedimaunt; हाँ, UDFs बहुत ही सुंदर कोड का नेतृत्व करते हैं। लेकिन यह अच्छा प्रदर्शन नहीं करता है। यह "नींद की गोलियों पर अभिशाप" है। :-) एक साधारण के बजाय dbo.Divide लिखना याद रखना भी मुश्किल है "/"
हेनरिक स्टॉन पोल्सन

1

जहां क्लॉज का उपयोग कर डेटा को फ़िल्टर करें ताकि आपको 0 मान न मिले।


1

कभी-कभी, 0 उपयुक्त नहीं हो सकता है, लेकिन कभी-कभी 1 भी उपयुक्त नहीं होता है। कभी-कभी 1 या 100 प्रतिशत परिवर्तन के रूप में वर्णित 0 से 100,000,000 की छलांग भी भ्रामक हो सकती है। उस परिदृश्य में 100,000,000 प्रतिशत उपयुक्त हो सकते हैं। यह इस बात पर निर्भर करता है कि आप प्रतिशत या अनुपात के आधार पर किस तरह के निष्कर्ष निकालना चाहते हैं।

उदाहरण के लिए, 2-4 से बिकने वाली एक बहुत छोटी-बिक्री वाली वस्तु और 1,000,000 से 2,000,000 में बिकने वाली एक बहुत बड़ी बिक्री वाली वस्तु का मतलब एक विश्लेषक या प्रबंधन के लिए बहुत अलग चीजें हो सकती हैं, लेकिन दोनों 100% या 1 के रूप में आएंगे। परिवर्तन।

वैध डेटा के साथ मिश्रित 0% या 100% पंक्तियों के एक समूह पर परिमार्जन करने की तुलना में NULL मूल्यों को अलग करना आसान हो सकता है। अक्सर, हर में 0 एक त्रुटि या लापता मूल्य का संकेत दे सकता है, और आप सिर्फ अपने डेटासेट को सुव्यवस्थित बनाने के लिए सिर्फ एक मनमाना मूल्य नहीं भरना चाहते हैं।

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

1
मुझे लगता है कि समस्या यह है कि जब भी आप एक विभाजन करना चाहते हैं तो कुछ करने के लिए याद रखें। यदि आप CASE या NULLIF जोड़ने को याद रखने में विफल रहते हैं, तो आपको सोमवार की सुबह, एक्स हफ्तों में एक समर्थन मामला मिलता है। मुझे उससे नफरत है।
हेनरिक स्टॉउन पॉल्सेन

1

मैंने इसे कैसे तय किया:

IIF (ValueA! = 0, कुल / मान, 0)

इसे अपडेट में लपेटा जा सकता है:

सेट Pct = IIF (ValueA! = 0, कुल / मान, 0)

या एक चयन में:

सेलेक्ट आईआईएफ (ValueA! = 0, कुल / मान, 0) AS Pct फ्रॉम तबलेनमे;

विचार?


मैं और अन्य लोग पाते हैं कि "अज्ञात" को शून्य से बदलना एक खतरनाक फिक्स है। मैं NULL को बहुत पसंद करता हूं। लेकिन मुश्किल यह है कि सभी डिवीजनों पर iif या nullif जोड़ना याद रखें!
हेनरिक स्टॉउन पोल्सेन

0

जब आप कॉलिंग प्रोग्राम में वापस प्रचारित करते हैं (या यदि आप चाहते हैं तो इसे अनदेखा कर सकते हैं) आप उचित रूप से त्रुटि को संभाल सकते हैं। C # में SQL में होने वाली कोई भी त्रुटि एक अपवाद को फेंक देगी जिसे मैं पकड़ सकता हूं और फिर किसी अन्य त्रुटि की तरह अपने कोड में संभाल सकता हूं।

मैं बस्का से सहमत हूं कि आप त्रुटि को छिपाना नहीं चाहते हैं। आप एक परमाणु रिएक्टर के साथ काम नहीं कर सकते हैं, लेकिन सामान्य रूप से त्रुटियों को छिपाना खराब प्रोग्रामिंग अभ्यास है। यह सबसे आधुनिक प्रोग्रामिंग भाषाओं में से एक है जो एक त्रुटि / स्थिति कोड के साथ वास्तविक रिटर्न मूल्य को कम करने के लिए संरचित अपवाद हैंडलिंग को लागू करता है। यह विशेष रूप से सच है जब आप गणित कर रहे हैं। सबसे बड़ी समस्या यह है कि आप किसी त्रुटि के परिणाम के रूप में एक गणना की गई 0 या एक 0 के बीच अंतर नहीं कर सकते हैं। बदले में लौटाए गए किसी भी मूल्य की गणना मूल्य है और अगर कुछ गलत होता है तो एक अपवाद फेंक दिया जाता है। यह निश्चित रूप से इस बात पर निर्भर करता है कि आप डेटाबेस का उपयोग कैसे कर रहे हैं और आप किस भाषा का उपयोग कर रहे हैं, लेकिन आपको हमेशा एक त्रुटि संदेश प्राप्त करने में सक्षम होना चाहिए।

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
मुझे लगता है कि हम सभी सहमत हैं कि त्रुटि को 0 के साथ छुपाना एक समाधान नहीं है। मेरा प्रस्ताव है कि हमारे कोड को ऐसे लिखें कि हर "/" के बाद एक "NULLIF" हो। इस तरह से मेरी रिपोर्ट / परमाणु रिएक्टर अकेला नहीं बचा है, लेकिन उस pesky त्रुटि Msg 8134 के बजाय एक "NULL" दिखा रहा है, कारण, अगर मुझे एक अलग प्रक्रिया की आवश्यकता होती है जब विभाजक 0 होता है, तो Beska और मैं सहमत होते हैं। हमें यह कोड करने की आवश्यकता है। हर बार जब आप "/" लिखते हैं, तो ऐसा करना मुश्किल होता है। "" NULLIF "हर बार करना असंभव नहीं है।
हेनरिक स्टॉउन पोल्सेन

0

NULLIF(exp,0)इस तरह से उपयोग करें -NULLIF(ISNULL(exp,0),0)

NULLIF(exp,0)टूटता है अगर ऍक्स्प है, nullलेकिन NULLIF(ISNULL(exp,0),0)नहीं तोड़ेगा


1
मुझे NULLIF नहीं मिल सकता है (exp, 0), अगर 0 एक शून्य है, तो ओ नहीं। प्रयत्न; DECLARE @i INT SELECT 1 / NULLIF (@i, 0) यह देखने के लिए कि क्या आप इसे तोड़ने के लिए प्राप्त कर सकते हैं।
हेनरिक स्टॉउन पॉल्सेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.