डेटाबेस से गलत नल प्रविष्टियों के खिलाफ गार्ड करने के लिए डिजाइन और अभ्यास


9

मेरे कार्यक्रम का एक हिस्सा प्रसंस्करण के लिए मेरे डेटाबेस में कई तालिकाओं और स्तंभों से डेटा प्राप्त करता है। कुछ कॉलम हो सकते हैं null, लेकिन वर्तमान प्रसंस्करण संदर्भ में जो एक त्रुटि है।

यह "सैद्धांतिक रूप से" नहीं होना चाहिए, इसलिए यदि यह खराब डेटा या कोड में एक बग को इंगित करता है। त्रुटियों की अलग-अलग गंभीरता होती है, यह निर्भर करता है कि कौन सा क्षेत्र है null; अर्थात कुछ क्षेत्रों के लिए प्रसंस्करण बंद कर दिया जाना चाहिए और किसी को अधिसूचित किया जाना चाहिए, दूसरों के लिए प्रसंस्करण जारी रखने की अनुमति दी जानी चाहिए और बस किसी को सूचित करना चाहिए।

क्या दुर्लभ लेकिन संभव nullप्रविष्टियों को संभालने के लिए कोई अच्छा आर्किटेक्चर या डिज़ाइन सिद्धांत हैं?

समाधान जावा के साथ लागू करना संभव होना चाहिए लेकिन मैंने टैग का उपयोग नहीं किया क्योंकि मुझे लगता है कि समस्या कुछ हद तक भाषा-अज्ञेयवादी है।


कुछ विचार जो मैंने स्वयं लिए थे:

नल का उपयोग नहीं

सबसे आसान डेटाबेस में एक पूर्ण नाल बाधा का उपयोग करना होगा।

लेकिन क्या होगा अगर डेटा की मूल प्रविष्टि अधिक महत्वपूर्ण है कि यह बाद में प्रसंस्करण कदम है? इसलिए यदि इंसर्ट nullटेबल में रखा जाता है (या तो बग्स के कारण या शायद कुछ वैध कारण भी), तो मैं नहीं चाहूंगा कि इन्सर्ट फेल हो जाए। मान लें कि प्रोग्राम के कई और हिस्से सम्मिलित डेटा पर निर्भर करते हैं, लेकिन इस विशेष कॉलम पर नहीं। इसलिए मैं डालने के चरण के बजाय वर्तमान प्रसंस्करण चरण में त्रुटि का जोखिम उठाऊंगा। यही कारण है कि मैं एक नहीं पूर्ण बाधा का उपयोग नहीं करना चाहता।

मूल रूप से NullPointerException पर निर्भर करता है

मैं सिर्फ डेटा का उपयोग कर सकता हूं जैसे कि मैं उम्मीद करता हूं कि यह हमेशा (और वास्तव में ऐसा होना चाहिए), और परिणामस्वरूप एनपीई को एक उचित स्तर पर पकड़ें (जैसे कि ताकि वर्तमान प्रविष्टि का प्रसंस्करण बंद हो जाए लेकिन पूरी प्रसंस्करण प्रगति न हो )। यह "विफल तेज़" सिद्धांत है और मैं अक्सर इसे पसंद करता हूं। अगर यह बग है तो कम से कम मुझे एक लॉग एनपीई मिलेगा।

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

nullप्रत्येक पहुंच से पहले की जाँच करना और कस्टम अपवादों को फेंकना

कस्टम अपवाद मुझे अपवाद के आधार पर सही कार्रवाई का निर्णय लेने देंगे, इसलिए यह जाने का तरीका लगता है।

लेकिन क्या होगा अगर मैं इसे कहीं जांचना भूल जाऊं? इसके अलावा, मैं अपने कोड को अशक्त चेक के साथ बंद कर देता हूं जो कभी भी या शायद ही कभी अपेक्षित नहीं होते हैं (और इसलिए निश्चित रूप से व्यापार तर्क प्रवाह का हिस्सा नहीं है)।

यदि मैं इस तरह जाना चाहता हूं, तो दृष्टिकोण के लिए कौन से पैटर्न सबसे उपयुक्त हैं?


मेरे दृष्टिकोण पर किसी भी विचार और टिप्पणी का स्वागत किया जाता है। किसी भी प्रकार के बेहतर समाधान (पैटर्न, सिद्धांत, मेरे कोड या मॉडल आदि की बेहतर वास्तुकला)।

संपादित करें:

एक और अड़चन है, इसमें मैं एक ORM का उपयोग कर रहा हूँ DB से मानचित्रण करने के लिए दृढ़ता वस्तु पर, इसलिए उस स्तर पर अशक्त जांच करने से काम नहीं चलेगा (क्योंकि समान वस्तुओं का उपयोग उन भागों में किया जाता है जहाँ नल कोई नुकसान नहीं करता है । मैंने इसे इसलिए जोड़ा क्योंकि अब तक दिए गए जवाबों में इस विकल्प का उल्लेख है।


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

@ किलियनफोथ, मेरी शिथिलता यह है कि सम्मिलित करते समय "वर्तमान प्रसंस्करण" संदर्भ में त्रुटि कम गंभीर है। इसलिए मैं दुर्लभ प्रसंस्करण त्रुटियों को स्वीकार करता हूं, लेकिन मैं उन्हें संभालने के लिए एक अच्छा मजबूत डिजाइन चाहता हूं। यही कारण है कि NULL, जो अन्यथा एक अच्छा समाधान होगा, यहां संभव नहीं है।
jhyot

1
यदि आप इतनी त्रुटियों को स्वीकार करने के बारे में जाते हैं, तो उस त्रुटियों के प्रवर्तक उन्हें कभी ठीक नहीं करेंगे। यदि उनका गन्दा इन्सर्ट स्टेटमेंट सफल हो जाता है, तो उन्हें क्या प्रोत्साहन देना होता है? क्या आप मजबूत को असफल नहीं मानते लेकिन खराब आंकड़ों को स्वीकार करते हैं?
ट्यूलेंस कोर्डोवा 14

@ user61852 मैं स्पष्ट रूप से त्रुटियों को स्वीकार नहीं कर रहा हूं, लेकिन उन्हें इनायत से संभालना चाहता हूं। शून्य बिंदु को निगलने से प्रश्न समाप्त हो जाता है। इसके अलावा, क्या होगा अगर मेरा हिस्सा वास्तव में उद्देश्यपूर्ण है (व्यवसाय द्वारा परिभाषित) कई अन्य हिस्सों की तुलना में कम महत्वपूर्ण है जो सम्मिलित करने के लिए सफल होने की आवश्यकता होती है लेकिन इस विशेष क्षेत्र को सेट करने की आवश्यकता नहीं है? आवेषण एक उपयोगकर्ता प्रविष्टि से उत्पन्न नहीं होता है जहां मैं उन्हें मूल्य जोड़ने के लिए मजबूर कर सकता हूं, लेकिन अन्य कोड से जहां चूक की संभावना एक बग है (लेकिन डालने को तोड़ने के लिए महत्वपूर्ण नहीं है)।
jhyot

1
डेटाबेस में NULL के रूप में उन्हें चिह्नित करना सबसे अच्छा समाधान होगा, यदि कोई कॉलम अशक्त है, तो कोड को केस को संभालने की आवश्यकता होगी, जब यह अपेक्षित नहीं है, क्योंकि भंडारण तंत्र इसे अनुमति देता है।
जॉन रेन्नोर

जवाबों:


9

मैं आपके मैपिंग कोड में नल चेक डालूंगा, जहां आप परिणाम सेट से अपनी वस्तु का निर्माण करेंगे। यह जाँच एक जगह करता है, और एक त्रुटि को रोकने से पहले आपके कोड को रिकॉर्ड को संसाधित करने के माध्यम से आधे रास्ते पर लाने की अनुमति नहीं देगा। आपके आवेदन का प्रवाह कैसे काम करता है, इस पर निर्भर करते हुए, आप एक बार में प्रत्येक रिकॉर्ड को मैप करने और संसाधित करने के बजाय पूर्व-प्रसंस्करण चरण के रूप में सभी परिणामों की मैपिंग करना चाहते हैं।

यदि आप एक ORM का उपयोग कर रहे हैं, तो आपको प्रत्येक रिकॉर्ड को संसाधित करने से पहले अपनी सभी अशक्त जांच करनी होगी। मैं एक recordIsValid(recordData)प्रकार की विधि की सिफारिश करूँगा , इस तरह से आप (फिर से) सभी अशक्त-जाँच और अन्य सत्यापन तर्क को एक स्थान पर रख सकते हैं। मैं निश्चित रूप से आपके बाकी प्रोसेसिंग लॉजिक के साथ अशक्त जांच को रोक नहीं पाऊंगा।


धन्यवाद, यह अच्छी जानकारी है! मैं वास्तव में एक ओआरएम का उपयोग कर रहा हूं, इसलिए उस स्तर पर जांच से काम नहीं चलेगा। लेकिन मैं भी हठ वस्तुओं से वास्तविक डोमेन वस्तुओं के लिए कुछ मानचित्रण है। मैं जाँच करूँगा कि मैपिंग करना और प्रीप्रोसेसिंग चरण में मान्य करना संभव होगा या नहीं।
15

और अगर आप अपना ORM स्विच करते हैं, तो फिर क्या है? स्रोत पर इसका बचाव करने के लिए बेहतर है (डॉक्टर ब्राउन का जवाब देखें)।
रॉबी डे

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

ईटीएल प्रवाह में यह और अधिक होना चाहिए। आप अभी भी इस तरह से डुप्लिकेट प्रयास को जोखिम में डालते हैं।
रॉबी डी

6

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

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


2
जवाब के लिए धन्यवाद। मैं सहमत हूं कि आपका समाधान इसे करने का सही तरीका है, और आपने इसे संक्षिप्त रूप से पूरा किया है। मेरे प्रभाव से बाहर की बाधाएँ इसे कठिन या असंभव बना सकती हैं (जैसे परीक्षण के लिए अनुपलब्ध संसाधन या मौजूदा कोड को स्वचालित रूप से परीक्षण योग्य बनाने के लिए), लेकिन मुझे निश्चित रूप से यह देखना चाहिए कि क्या यह समाधान अन्य तरीकों को आज़माने से पहले काम कर सकता है। अपनी मूल सोच में मैंने शायद बहुत जल्दी मान लिया कि मैं स्रोत पर समस्या को ठीक नहीं कर सकता।
ज्योत

@ जियोट ठीक। यह निराशाजनक है जब आप चीजों को साफ तरीके से नहीं कर सकते। उम्मीद है कि मेरा जवाब दूसरों के लिए कम से कम उपयोगी हो, जिनके पास समान समस्याएं हैं लेकिन जो इस तथ्य के बाद गंदगी को साफ करने के बजाय मूल कारण पर हमला करने में सक्षम हैं।
मोनिका

5

प्रश्न में इस वाक्य के संबंध में:

यह "सैद्धांतिक रूप से" नहीं होना चाहिए, इसलिए यदि यह खराब डेटा या कोड में एक बग को इंगित करता है।

मैंने हमेशा इस उद्धरण ( इस लेख के सौजन्य से ) की सराहना की है :

मुझे लगता है कि जब नौसिखिए प्रोग्रामर मानते हैं कि उनका मुख्य काम कार्यक्रमों को दुर्घटनाग्रस्त होने से रोक रहा है, तो मुझे यह बहुत अच्छा लगता है। मुझे लगता है कि इस शानदार विफलता तर्क इस तरह के एक प्रोग्रामर के लिए इतना आकर्षक नहीं होगा। अधिक अनुभवी प्रोग्रामर को एहसास होता है कि सही कोड महान है, कोड जो क्रैश का उपयोग कर सकता है, लेकिन गलत कोड जो क्रैश नहीं करता है वह एक भयानक दुःस्वप्न है।

मूल रूप से: ऐसा लगता है कि आप पोस्टल के नियम का समर्थन कर रहे हैं , "जो आप भेजते हैं उसमें रूढ़िवादी हो, जो आप स्वीकार करते हैं उसमें उदार रहें"। सिद्धांत रूप में महान, व्यवहार में यह "मजबूती सिद्धांत" सॉफ्टवेयर की ओर जाता है जो मजबूत नहीं है , कम से कम लंबे समय में - और कभी-कभी अल्पावधि में भी। (एरिक अल्लमैन के पेपर की तुलना रोबस्टनेस सिद्धांत पर पुनर्विचार किया गया , जो कि इस विषय का बहुत गहन उपचार है, यद्यपि ज्यादातर नेटवर्क प्रोटोकॉल के उपयोग के मामलों पर केंद्रित है।)

यदि आपके पास ऐसे प्रोग्राम हैं जो गलत तरीके से आपके डेटाबेस में डेटा डाल रहे हैं, तो वे प्रोग्राम टूट गए हैं और उन्हें ठीक करने की आवश्यकता है । समस्या पर पैपिंग केवल इसे खराब होने के लिए जारी रखने की अनुमति देता है; यह एक सॉफ्टवेयर इंजीनियरिंग है जो किसी नशेड़ी को उनकी लत को जारी रखने में सक्षम बनाने के बराबर है ।

व्यावहारिक रूप से, हालांकि, कभी-कभी आपको "टूटे हुए" व्यवहार को जारी रखने के लिए सक्षम करने की आवश्यकता होती है, कम से कम अस्थायी रूप से, विशेष रूप से एक ढीला, टूटी हुई अवस्था से एक सख्त, सही स्थिति में सहज संक्रमण के हिस्से के रूप में। उस स्थिति में, आप गलत प्रविष्टि को सफल होने की अनुमति देना चाहते हैं, लेकिन फिर भी "कैनोनिकल" डेटा स्टोर को हमेशा सही स्थिति में रखने की अनुमति देते हैं । ऐसा करने के विभिन्न तरीके हैं:

  • विकृत आवेषण के साथ अनुपलब्ध आवेषण को प्रतिस्थापित करके विकृत आवेषण को सही आवेषण में बदलने के लिए एक डेटाबेस ट्रिगर का उपयोग करें
  • गलत प्रोग्राम को एक अलग डेटाबेस तालिका में डालें, जिसे "गलत" होने की अनुमति है, और एक अलग अनुसूचित प्रक्रिया या अन्य तंत्र है जो उस तालिका से सही डेटा को कैनोनिकल डेटा स्टोर में स्थानांतरित करता है।
  • यह सुनिश्चित करने के लिए क्वेरी-साइड फ़िल्टरिंग (उदाहरण के लिए) का उपयोग करें कि डेटाबेस से प्राप्त डेटा हमेशा एक सही स्थिति में हो, भले ही बाकी का डेटा न हो।

इन सभी मुद्दों को दरकिनार करने का एक तरीका एपीआई परत डालना है जो आप उन कार्यक्रमों के बीच नियंत्रित करते हैं जो लिखते हैं और वास्तविक डेटाबेस को जारी करते हैं।

ऐसा लगता है कि आपकी समस्या का एक हिस्सा यह है कि आप उन सभी स्थानों को भी नहीं जानते हैं जो गलत तरीके से लिख रहे हैं - या यह कि उनमें से बहुत से आप अद्यतन करने के लिए हैं। यह एक डरावनी स्थिति है, लेकिन इसे कभी भी पहली जगह में उत्पन्न नहीं होने देना चाहिए।

जैसे ही आप एक मुट्ठी भर से अधिक सिस्टम प्राप्त करते हैं, जो एक कैनोनिकल प्रोडक्शन डेटा स्टोर में डेटा को संशोधित करने की अनुमति देता है, जो आपको परेशानी में डालने वाला है: उस डेटाबेस के बारे में कुछ भी केंद्रीय रूप से बनाए रखने का कोई तरीका नहीं है। बेहतर होगा कि कुछ प्रक्रियाओं को लिखने के लिए जारी करने की अनुमति दें, और "गेटकीपर" के रूप में उन का उपयोग करें जो आवश्यक रूप से डालने से पहले डेटा को प्रीप्रोसेस कर सकते हैं। इसके लिए सटीक तंत्र वास्तव में आपकी विशिष्ट वास्तुकला पर निर्भर करता है।


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

@JeffO: डेटाबेस में "NA", "कोई नहीं", NULL, या कुछ और संग्रहीत करने के लिए कोई समिति बहस नहीं करनी चाहिए । गैर-तकनीकी हितधारकों में एक हिस्सेदारी होती है कि डेटा डेटाबेस से बाहर कैसे आता है और इसका उपयोग कैसे किया जाता है, लेकिन आंतरिक प्रतिनिधित्व में नहीं।
डैनियल प्राइडेन

@DanielPryden: मेरी पिछली नौकरी में, हमारे पास एक आर्किटेक्चर रिव्यू बोर्ड (DBA उप-समिति के साथ) था जो क्रॉस-डोमेन तकनीकी परिवर्तनों की समीक्षा करेगा। बहुत तकनीकी है, लेकिन वे केवल हर दो सप्ताह में मिलते हैं और यदि आपने उनके लिए पर्याप्त विवरण नहीं दिया है तो वे एक निर्णय को स्थगित कर देंगे, जब तक कि आप बाद में नहीं करते। अधिकांश गैर-तुच्छ प्रणाली परिवर्तन जो नए कोड के माध्यम से कार्यक्षमता जोड़ने में शामिल नहीं थे, वे नियमित रूप से एक या एक महीने का समय लेंगे।
TMN

@DanielPryden - मैं टेक्स्ट बॉक्स लेबल पर ऊपरी प्रबंधन की बहस के साथ बैठकों में बैठा हूं। आप तर्क दे सकते हैं कि इससे कोई लेना-देना नहीं है कि आप इसे एप्लिकेशन या डेटाबेस में नाम देने जा रहे हैं, लेकिन यह करता है।
जेएफओ

इस प्रकार के परिवर्तनों के लिए अतिरिक्त स्वीकृतियां प्राप्त करने के बारे में टिप्पणियों के जवाब में: "गलत" होने वाले मूल्यों के बारे में मेरी बात यह मानती है कि स्वीकार्य मूल्य पहले से ही कहीं दस्तावेज हैं - इसलिए ओपी का कहना है कि इन मूल्यों को बग माना जाना चाहिए। यदि डेटाबेस का स्कीमा किसी मान की अनुमति देने के लिए निर्दिष्ट किया जाता है, तो वह मान बग नहीं है। मुद्दा यह है कि यदि आपके पास डेटा है जो आपके स्कीमा से मेल नहीं खाता है, तो कुछ टूट गया है: आपकी प्राथमिकता डेटा और स्कीमा मैच बनाने के लिए होनी चाहिए। टीम के आधार पर, जिसमें डेटा, स्कीमा या दोनों को बदलना शामिल हो सकता है।
डैनियल प्रेडेन

2

" दुर्लभ लेकिन संभव अशक्त प्रविष्टियों को संभालने के लिए कोई अच्छा आर्किटेक्चर या डिज़ाइन सिद्धांत हैं? "

सरल उत्तर - हाँ।

ईटीएल

डेटा को डेटाबेस में जाने के लिए पर्याप्त गुणवत्ता का होना सुनिश्चित करने के लिए कुछ अप प्रोसेसिंग को पूरा करें। ड्रॉप फ़ाइल में कुछ भी वापस रिपोर्ट किया जाना चाहिए और किसी भी स्वच्छ डेटा को डेटाबेस में लोड किया जा सकता है।

जैसा कि कोई है जो दोनों शिकार (देव) और गेम कीपर (डीबीए) है, मैं कड़वा अनुभव से जानता हूं कि 3 पार्टियां केवल अपने डेटा मुद्दों को हल नहीं करेंगी जब तक कि वे मजबूर न हों। लगातार पीछे की ओर झुकना और डेटा के माध्यम से मालिश करना एक खतरनाक मिसाल कायम करता है।

मार्ट / भंडार

इस परिदृश्य में, कच्चे डेटा को रिपॉजिटरी डीबी में धकेल दिया जाता है और फिर एक सैनिटाइज्ड वर्जन को मार्ट डीबी में धकेल दिया जाता है, जिसके बाद एप्लिकेशन उस तक पहुंच बनाते हैं।

डिफ़ॉल्ट मान

यदि आप स्तंभों के लिए समझदार डिफ़ॉल्ट मानों को लागू कर सकते हैं, तो आपको हालांकि यह एक मौजूदा डेटाबेस होने पर कुछ काम शामिल कर सकता है।

जल्दी असफल हो गए

यह गेटवे पर डेटा के मुद्दों को केवल एप्लिकेशन, रिपोर्ट सूट, इंटरफ़ेस आदि के लिए लुभाना है। मैं आपको पूरी तरह से इस पर भरोसा नहीं करने की सलाह दूंगा। यदि आप DB के किसी अन्य विजेट में हुक करते हैं, तो आपको संभावित रूप से फिर से उसी समस्याओं का सामना करना पड़ेगा। डेटा गुणवत्ता समस्याओं को संबोधित करें।


+1 यह वही है जो मैं करता हूं, सभी डेटा एकत्र करें और अपने आवेदन को संसाधित करने के लिए एक वैध डेटा सेट बनाएं।
13

1

जब भी आपका उपयोग मामला NULL को एक अच्छे डिफ़ॉल्ट मान द्वारा सुरक्षित रूप से प्रतिस्थापित करने की अनुमति देता है, आप SELECTSql कथनों का उपयोग करके ISNULLया में रूपांतरण कर सकते हैं COALESCE। इसलिए इसके बजाय

 SELECT MyColumn FROM MyTable

कोई लिख सकता है

 SELECT ISNULL(MyColumn,DefaultValueForMyColumn) FROM MyTable

बेशक, यह तभी काम करेगा जब ओआरएम सीधे चयनित बयानों में हेरफेर करने की अनुमति देता है, या पीढ़ी के लिए अस्थिर टेम्पलेट प्रदान करता है। किसी को यह सुनिश्चित करना चाहिए कि कोई "वास्तविक" त्रुटियां इस तरह से नकाबपोश न हों, इसलिए इसे केवल तभी लागू करें जब कोई डिफ़ॉल्ट मान द्वारा प्रतिस्थापित करना वास्तव में आप NULL के मामले में चाहते हैं।

यदि आप डेटाबेस और स्कीमा को बदलने में सक्षम हैं, और आपका डीबी सिस्टम इस का समर्थन करता है, तो आप @RobbieDee द्वारा सुझाए गए अनुसार विशिष्ट कॉलम में एक डिफ़ॉल्ट मान खंड जोड़ने पर विचार कर सकते हैं। हालाँकि, इसके लिए पहले से डाले गए NULL मानों को हटाने के लिए डेटाबेस में मौजूदा डेटा को संशोधित करना होगा, और यह बाद में सही और अधूरे आयात डेटा के बीच अंतर करने की क्षमता को हटा देगा।

अपने स्वयं के अनुभव से, मुझे पता है कि ISNULL का उपयोग आश्चर्यजनक रूप से अच्छी तरह से काम कर सकता है - अतीत में मुझे एक विरासत एप्लिकेशन को बनाए रखना था जहां मूल देवता बहुत सारे कॉलमों में NOT NULL बाधाओं को जोड़ना भूल गए थे, और हम बाद में उन बाधाओं को आसानी से नहीं जोड़ पाए। कुछ कारणों से। लेकिन सभी मामलों में 99% में, नंबर कॉलम के लिए डिफ़ॉल्ट और टेक्स्ट कॉलम के लिए डिफ़ॉल्ट के रूप में खाली स्ट्रिंग पूरी तरह से स्वीकार्य थी।


जब भी यह काम करता है, तो आप प्रत्येक SELECT के लिए रक्षात्मक कोड को डुप्लिकेट कर सकते हैं। एक बेहतर तरीका एक NULL डाला जाता है जब एक कॉलम के लिए एक डिफ़ॉल्ट मान को परिभाषित करना है, हालांकि यह कई कारणों से संभव / वांछनीय नहीं हो सकता है।
रॉबी डी

@ रॉबीडी: उस टिप्पणी के लिए धन्यवाद, मैंने अपने उत्तर को उसी के अनुसार बदल दिया। हालांकि, अगर यह "कहीं बेहतर" बहस योग्य है। जब CRUD कोड एक स्थान पर होता है, तो डुप्लिकेट रक्षात्मक कोड एक समस्या का ज्यादा हिस्सा नहीं हो सकता है। और अगर ऐसा नहीं है, तो पहले से ही कुछ कोड डुप्लिकेट है।
डॉक्टर ब्राउन

साधारण CRUD ऑपरेशन निश्चित रूप से आदर्श हैं। लेकिन वास्तविक दुनिया में, सिस्टम में अक्सर जटिल यूआई दृश्य होते हैं, उपयोगकर्ता डेटा वाइज़र, रिपोर्ट आदि उत्पन्न करते हैं, लेकिन जैसा कि आपने बताया है, डिफ़ॉल्ट मानों को जमीन से ऊपर या कम से कम कुछ प्रारंभिक रूपांतरण प्रयास की आवश्यकता होती है। आपने जो वर्णन किया है वह ब्राउनफील्ड विकास में बेहतर हो सकता है।
रोबी डे

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

1

ओपी एक उत्तर दे रहा है कि युगल डेटाबेस तकनीकी विवरण के साथ व्यापार नियम बनाते हैं।

यह "सैद्धांतिक रूप से" नहीं होना चाहिए, इसलिए यदि यह खराब डेटा या कोड में एक बग को इंगित करता है। त्रुटियों में अलग-अलग गंभीरता होती है, जो इस बात पर निर्भर करता है कि कौन सा क्षेत्र अशक्त है; अर्थात कुछ क्षेत्रों के लिए प्रसंस्करण बंद कर दिया जाना चाहिए और किसी को अधिसूचित किया जाना चाहिए, दूसरों के लिए प्रसंस्करण जारी रखने की अनुमति दी जानी चाहिए और बस किसी को सूचित करना चाहिए।

यह सभी व्यावसायिक नियम हैं। व्यावसायिक नियम शून्य प्रति-से की परवाह नहीं करते हैं। सभी के लिए यह जानता है कि डेटाबेस शून्य, 9999 हो सकता है, "BOO!" ... यह सिर्फ एक और मूल्य है। RDBMS में, null के पास दिलचस्प गुण हैं और अद्वितीय उपयोग moot है।

केवल एक चीज जो मायने रखती है वह है "null-ness" का अर्थ दी गई व्यावसायिक वस्तु (ओं) के लिए है ...

क्या दुर्लभ लेकिन संभव अशक्त प्रविष्टियों को संभालने के लिए कोई अच्छा आर्किटेक्चर या डिज़ाइन सिद्धांत हैं?

हाँ।

  • व्यावसायिक नियमों को कक्षाओं में रखें।
  • लिप्यंतरण व्यावसायिक वर्गों और डेटा स्टोर को डिकूप करने वाली एक उपयुक्त कोड परत में होना चाहिए। यदि आप इसे ORM कोड में नहीं डाल सकते हैं तो कम से कम डेटाबेस में न डालें।
  • डेटाबेस को संभव के रूप में गूंगा बनाओ, यहां कोई व्यावसायिक नियम नहीं हैं। यहां तक ​​कि एक मूल्य को डिफॉल्ट करने जैसी सहज बातें भी आपको चुभेंगी । वहाँ गया।
  • डेटाबेस से जाने और आने वाले डेटा को मान्य करें। और निश्चित रूप से यह व्यापार वस्तुओं के संदर्भ में w / किया जाता है।

डेटा पुनर्प्राप्ति पर एक अपवाद फेंकने का कोई मतलब नहीं है।

सवाल यह है कि "क्या मुझे 'खराब' डेटा स्टोर करना चाहिए?" निर्भर करता है:

  • खराब डेटा का उपयोग किया जा सकता है - कभी भी अमान्य ऑब्जेक्ट, या ऑब्जेक्ट कंपोजिट को न सहेजें। सभी जगह जटिल डेटा / व्यावसायिक संबंध। उपयोगकर्ता किसी भी समय किसी भी कार्य को कर सकते हैं, संभवतः कई संदर्भों में उस व्यवसाय इकाई का उपयोग कर रहे हैं। खराब डेटा का प्रभाव (यदि कोई है), उस समय जो बचा है, वह ज्ञात नहीं है क्योंकि यह भविष्य के उपयोग पर अत्यधिक निर्भर है। उस डेटा की कोई एकीकृत / एकल प्रक्रिया नहीं है।
  • खराब डेटा होने पर प्रगति नहीं कर सकता - खराब डेटा को सहेजने की अनुमति दें। हालाँकि, प्रक्रिया में अगला चरण तब तक जारी नहीं रह सकता जब तक कि सब कुछ वैध न हो। उदाहरण के लिए किसी का आयकर करना। जब डेटाबेस से पुनर्प्राप्त किया जाता है तो सॉफ़्टवेयर त्रुटियों को बताता है और इसे वैधता जाँच के बिना आईआरएस को प्रस्तुत नहीं किया जा सकता है।

0

नल को संभालने के कई तरीके हैं, इसलिए हम डेटाबेस लेयर से एप्लिकेशन लेयर तक आगे बढ़ेंगे।


डेटाबेस लेयर

आप नल को मना कर सकते हैं ; हालांकि यहां यह अव्यावहारिक है।

आप प्रति कॉलम आधार पर एक डिफ़ॉल्ट कॉन्फ़िगर कर सकते हैं:

  • इसके लिए आवश्यक है कि कॉलम अनुपस्थित हो insert, इसलिए स्पष्ट अशक्तता को शामिल नहीं करता है
  • यह उन पंक्तियों से पता लगाने से रोकता है जहां insertगलत तरीके से यह कॉलम छूट गया है

आप एक ट्रिगर कॉन्फ़िगर कर सकते हैं , ताकि सम्मिलन पर लापता मान स्वचालित रूप से गणना कर रहे हैं:

  • इसके लिए आवश्यक है कि इस गणना को करने के लिए आवश्यक जानकारी मौजूद हो
  • यह धीमा हो जाएगा insert

क्वेरी परत

आप उन पंक्तियों को छोड़ सकते हैं जहाँ एक असुविधा nullमौजूद है:

  • यह मुख्य तर्क को सरल करता है
  • यह "खराब पंक्तियों" का पता लगाने से रोकता है, इसलिए उन पर जांच के लिए एक और प्रक्रिया की आवश्यकता होगी
  • इसके लिए आवश्यक है कि प्रत्येक क्वेरी को इंस्ट्रूमेंट किया जाए

आप क्वेरी में एक डिफ़ॉल्ट मान प्रदान कर सकते हैं :

  • यह मुख्य तर्क को सरल करता है
  • यह "खराब पंक्तियों" का पता लगाने से रोकता है, इसलिए उन पर जांच के लिए एक और प्रक्रिया की आवश्यकता होगी
  • इसके लिए आवश्यक है कि प्रत्येक क्वेरी को इंस्ट्रूमेंट किया जाए

नोट: प्रत्येक क्वेरी को इंस्ट्रूमेंट करना कोई समस्या नहीं है यदि आपके पास उन्हें उत्पन्न करने का कुछ स्वचालित तरीका है।


अनुप्रयोग परत

आप निषिद्ध के लिए तालिका की पूर्व जांच कर सकते हैं null:

  • यह मुख्य तर्क को सरल करता है
  • यह समय-समय पर विफलता में सुधार करता है
  • इसके लिए प्री-चेक और एप्लिकेशन लॉजिक को लगातार बनाए रखने की आवश्यकता होती है

निषिद्ध का सामना करते समय आप प्रसंस्करण को बाधित कर सकते हैं null:

  • यह कौन सा कॉलम हो सकता है nullऔर कौनसा नहीं हो सकता है के ज्ञान की नकल करने से बचता है
  • यह अभी भी अपेक्षाकृत सरल है (सिर्फ एक चेक + रिटर्न / थ्रो)
  • यह आवश्यक है कि आपकी प्रक्रिया फिर से शुरू हो (यदि आपने पहले से ही ई-मेल भेजा है, तो इसे दो बार, या सौ बार नहीं भेजना चाहते हैं)!

मना करने पर आप पंक्ति छोड़ सकते हैं null:

  • यह कौन सा कॉलम हो सकता है nullऔर कौनसा नहीं हो सकता है के ज्ञान की नकल करने से बचता है
  • यह अभी भी अपेक्षाकृत सरल है (सिर्फ एक चेक + रिटर्न / थ्रो)
  • इसकी आवश्यकता नहीं है कि आपकी प्रक्रिया फिर से शुरू हो

निषिद्ध का सामना करते समय आप एक सूचना भेज सकते हैं null, या तो एक बार या बैच द्वारा, जो कि ऊपर प्रस्तुत अन्य तरीकों के लिए प्रशंसा योग्य है। सबसे महत्वपूर्ण बात यह है कि "क्या तब?" फिर से संसाधित किया जा रहा है।


आपकी स्थिति को देखते हुए, मैं आवेदन पर स्थिति को संभालूंगा और या तो संयोजित करूंगा:

  • बीच में आना और सूचित करना
  • छोड़ें और सूचित करें

यदि संभव हो तो मैं किसी भी तरह की प्रगति की गारंटी देने के लिए सिर्फ लंघन की ओर रुख करूंगा , खासकर अगर प्रसंस्करण में समय लग सकता है।

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

अन्यथा, मैं पंक्तियों को ठीक करने के लिए एक साइड-टेबल (और फिर से संसाधित) का उपयोग करूंगा। यह साइड-टेबल या तो एक साधारण संदर्भ (विदेशी कुंजी के बिना) या पूर्ण-विकसित प्रतिलिपि हो सकती है: बाद वाला, भले ही अधिक महंगा हो, यदि आपके पास nullमुख्य डेटा को साफ करने से पहले पता करने का समय नहीं है, तो यह आवश्यक है ।


-1

Nulls को भाषा प्रकारों के डेटाबेस प्रकारों के अनुवाद या मानचित्रण में संभाला जा सकता है। C # में उदाहरण के लिए, यहाँ एक सामान्य विधि है जो किसी भी प्रकार के लिए आपके लिए उपयुक्त है:

public static T Convert<T>(object obj)
        {
            if (obj == DBNull.Value)
            {
                return default(T);
            }

            return (T) obj;
        }

public static T Convert<T>(object obj, T defaultValue)
        {
            if (obj == DBNull.Value)
            {
                T t = defaultValue;
                return t;
            }

            return (T) obj;
        }

या, यदि आप कार्रवाई करना चाहते हैं ...

 public static T Convert<T>(object obj, T defaultValue)
        {
            if (obj == DBNull.Value)
            {
                //Send an Alert, we might want pass in the name
                //of column or other details as well
                SendNullAlert();
                //Set it to default so we can keep processing
                T t = defaultValue;
                return t;
            }

            return (T) obj;
        }

और फिर मैपिंग में, "नमूना" प्रकार की वस्तु के मामले में, हम किसी भी कॉलम के लिए नल को संभाल लेंगे:

public class SampleMapper : MapperBase<Sample>
    {
        private const string Id = "Id";
        private const string Name = "Name";
        private const string DataValue = "DataValue";
        private const string Created = "Created";

        protected override Sample Map(IDataRecord record)
        {
            return new Sample(
                Utility.Convert<Int64>(record[Id]),
                Utility.Convert<String>(record[Name]),
                Utility.Convert<Int32>(record[DataValue]),
                Utility.Convert<DateTime>(record[Created])
                );
        }
    }

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


अगर कोई बराबर जावा संस्करण पोस्ट करना चाहता है जो बहुत अच्छा होगा ...
जॉन रेन्नोर

मुझे लगता है कि उदाहरण कोड जावा डेवलपर्स के लिए भी पूरी तरह से समझने योग्य है। मेरी स्थिति में मेरे पास पहले से ही एक ORM है, इसलिए किसी को लागू करने की आवश्यकता नहीं है। लेकिन आपका जवाब केवल नल के लिए डिफ़ॉल्ट मानों को संबोधित करता है, जबकि मेरे मामले में वास्तव में बहुत अधिक महत्वपूर्ण मामला एक अशक्त का पता लगा रहा है और एक कार्रवाई को ट्रिगर कर रहा है (उदाहरण के लिए गलत डेटा के बारे में एक व्यवस्थापक को सूचित करें)।
ज्योत

आह, मैं इसके आधार पर अपने उत्तर को अपडेट करूंगा।
जॉन रेनोर

आपके संपादित कोड में अब किसी भी शून्य मान के लिए एक डिफ़ॉल्ट कार्रवाई है (यानी यह पूरी तरह से सामान्य है)। यह मूल प्रश्न में मेरे 2 विकल्प के समान है, अर्थात केवल शून्य पर फेंक दें और इसे कहीं पकड़ लें। लेकिन जैसा कि वहां कहा गया है कि मुझे उन कार्यों को अंतर करने की आवश्यकता है जिनके आधार पर मूल्य गायब है।
ज्योत
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.