क्या एक डेटाबेस कॉलम में सीमांकित सूची को वास्तव में खराब माना जाता है?


363

चेक बॉक्स के सेट के साथ एक वेब फ़ॉर्म की कल्पना करें (किसी भी या सभी को चुना जा सकता है)। मैंने उन्हें डेटाबेस तालिका के एक कॉलम में संग्रहीत मानों की अल्पविराम से अलग सूची में सहेजने के लिए चुना।

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

मुझे लगा कि बचाया समय और सरल कोड मेरी स्थिति में इसके लायक था, क्या यह एक दोषपूर्ण डिजाइन विकल्प है, या क्या मुझे इसे शुरू से सामान्य करना चाहिए?

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


21
उस स्थिति में, क्यों डेटाबेस को परेशान कर रहा है ?, एक फ़ाइल में बचत करेगा।
थावन

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

1
Postgres में, एक अल्पविराम से अलग सूची में एक सरणी स्तंभ को प्राथमिकता दी जानी चाहिए। यह कम से कम उचित डेटा प्रकार सुनिश्चित करता है, वास्तविक डेटा से सीमांकक को अलग करने में कोई समस्या नहीं है और इसे कुशलता से अनुक्रमित किया जा सकता है।
a_horse_with_no_name

जवाबों:


567

पहले सामान्य रूप का उल्लंघन करने के अलावा , एक एकल स्तंभ में संग्रहीत मानों के दोहराव समूह के कारण, अल्पविराम से अलग की गई सूचियों में बहुत अधिक अन्य व्यावहारिक समस्याएं हैं:

  • यह सुनिश्चित नहीं कर सकता कि प्रत्येक मान सही डेटा प्रकार है: 1,2,3, केला, 5 को रोकने का कोई तरीका नहीं
  • मानों को लुकअप टेबल से लिंक करने के लिए विदेशी कुंजी बाधाओं का उपयोग नहीं कर सकते; संदर्भात्मक अखंडता को लागू करने का कोई तरीका नहीं।
  • विशिष्टता को लागू नहीं कर सकते: 1,2,3,3,3,5 को रोकने के लिए कोई रास्ता नहीं
  • पूरी सूची लाए बिना सूची से कोई मान नहीं हटा सकते।
  • स्ट्रिंग कॉलम में जो फिट बैठता है, उससे अधिक लंबी सूची संग्रहीत नहीं कर सकता।
  • सूची में दिए गए मान के साथ सभी संस्थाओं की खोज करना मुश्किल है; आपको एक अक्षम तालिका-स्कैन का उपयोग करना होगा। उदाहरण के लिए, MySQL में नियमित अभिव्यक्तियों का सहारा लेना पड़ सकता है:
    idlist REGEXP '[[:<:]]2[[:>:]]'*
  • सूची में तत्वों की गणना करना कठिन है, या अन्य समग्र प्रश्न करें।
  • वे संदर्भ तालिका में मानों में शामिल होने के लिए कड़ी मेहनत करते हैं।
  • सूची को क्रमबद्ध क्रम में लाना मुश्किल है।

इन समस्याओं को हल करने के लिए, आपको एप्लिकेशन कोड के टन को लिखना होगा, कार्यक्षमता को सुदृढ़ करना जो RDBMS पहले से ही बहुत अधिक कुशलतापूर्वक प्रदान करता है

कोमा से अलग की गई सूचियाँ काफी गलत हैं कि मैंने इसे अपनी पुस्तक में पहला अध्याय बनाया: SQL Antipatterns: डेटाबेस प्रोग्रामिंग के नुकसान से बचना

ऐसे समय होते हैं जब आपको वंचितता को नियोजित करने की आवश्यकता होती है, लेकिन @OMG पॉनीज़ के उल्लेख के अनुसार , ये अपवाद मामले हैं। किसी भी गैर-संबंधपरक "अनुकूलन" से डेटा के अन्य उपयोगों की कीमत पर एक प्रकार की क्वेरी का लाभ मिलता है, इसलिए सुनिश्चित करें कि आप जानते हैं कि आपके प्रश्नों में से कौन सा विशेष रूप से व्यवहार करने की आवश्यकता है, ताकि वे वियोग का पात्र बन सकें।


* MySQL 8.0 अब इस शब्द-सीमा अभिव्यक्ति सिंटैक्स का समर्थन नहीं करता है।


8
एक ARRAY (किसी भी डेटाटाइप का) अपवाद को ठीक कर सकता है, बस PostgreSQL की जाँच करें: postgresql.org/docs/current/static/arrays.html (@Bill: महान पुस्तक, किसी भी डेवलपर या dba के लिए पढ़ना चाहिए)
फ्रैंक हाइकेन

4
+1 बिल करविन महान जवाब! लवली ने बुलेट पॉइंट्स को संक्षिप्त किया। वह भी एक महान पुस्तक की तरह लग रहा है। कवर को भी प्यार करें +1 NullUserException। मैं एक फ्लैट फ़ाइल पाठ आधारित प्रणाली को बदलने के लिए MySQL डेटाबेस के लिए स्कीमा डिज़ाइन करने की प्रक्रिया में हूं। मैंने अब तक कई दुविधाओं का सामना किया है। तो यह किताब खरीदने लायक होगी।
उपचार 16

2
Pragprog.com साइट अच्छी दिखती है: अच्छी शैली, लेआउट, उपयोगकर्ता के अनुकूल स्वच्छ। यह काफी नया होना चाहिए, मैं अतीत में उनकी ईबुक नहीं खरीद पाया। पुनश्च। मैं उनके लिए काम नहीं करता लेखकों के साथ कोई संबंध है। मैं अच्छे उत्पादों, सेवाओं का जश्न मनाना पसंद करता हूं और जब मैं इसे देखता हूं तो मदद करता हूं।
उपराष्ट्रपति

2
गंभीर पक्ष पर, मैं आपकी सूची में जोड़ूंगा: खोज करना मुश्किल। कहते हैं कि आप सभी रिकॉर्ड चाहते हैं जिसमें "2" शामिल है। बेशक आप सिर्फ फ़ॉबर = '2' को नहीं खोज सकते हैं क्योंकि अगर अन्य मान होते हैं तो यह याद आएगा। आप '% 2%' की तरह फ़ॉबर नहीं खोज सकते क्योंकि इससे 12 और 28 को झूठी हिट मिल सकती है। आप '%, 2,%' जैसे फ़ॉबरों को नहीं खोज सकते क्योंकि 2 सूची का पहला या अंतिम तत्व हो सकता है और इसलिए उनमें से केवल एक अल्पविराम होता है।
जय

2
मुझे पता है कि इसकी अनुशंसा नहीं की गई है, लेकिन डेविल्स एडवोकेट की भूमिका निभा रहे हैं: इनमें से अधिकांश को हटा दिया जा सकता है यदि कोई ऐसा यूआई है जो विशिष्टता और डेटा प्रकारों को संभालता है (अन्यथा त्रुटि या दुर्व्यवहार होगा), यूआई ड्रॉप करता है और इसे वैसे भी बनाता है, एक ड्राइवर टेबल है जहां मान उन्हें विशिष्ट बनाने के लिए आते हैं, '% P%' जैसे फ़ील्ड का उपयोग किया जा सकता है, P, R, S, T, मानों को गिनना मायने नहीं रखता है, और छंटनी मायने नहीं रखती है। यूआई के आधार पर, मानों को विभाजित किया जा सकता है [जैसे कि उन्हें प्राप्त करने के लिए किसी अन्य तालिका में जाने के बिना ड्राइवर तालिका से कम से कम सामान्य परिदृश्य में एक सूची में चेकबॉक्स की जांच करना।
jmcclure

44

"एक कारण आलस्य था"।

यह खतरे की घंटी बजाता है। ऐसा कुछ करने का एकमात्र कारण यह है कि आप जानते हैं कि यह कैसे करना है "सही तरीका" लेकिन आप इस निष्कर्ष पर पहुंचे हैं कि इस तरह से ऐसा न करने का एक ठोस कारण है।

यह कहा जाने के बाद: यदि आप इस तरह से स्टोर करने के लिए जो डेटा चुन रहे हैं, वह डेटा है जिसे आपको कभी भी क्वेरी करने की आवश्यकता नहीं होगी, तो आपके द्वारा चुने गए तरीके से इसे संग्रहीत करने के लिए एक मामला हो सकता है।

(कुछ उपयोगकर्ता मेरे पिछले पैराग्राफ में कथन को विवादित करेंगे, यह कहते हुए कि "आप कभी नहीं जान सकते हैं कि भविष्य में क्या आवश्यकताएं जोड़ी जाएंगी"। ये उपयोगकर्ता या तो एक धार्मिक विश्वास को भ्रमित कर रहे हैं या कह रहे हैं। कभी-कभी यह उन आवश्यकताओं के लिए काम करना फायदेमंद होता है। आपके सामने है।)


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

41

एसओ से कई सवाल पूछे जाते हैं:

  • अल्पविराम से अलग सूची से विशिष्ट मानों की गिनती कैसे प्राप्त करें
  • उस अल्पविराम से अलग सूची में केवल 2/3 / आदि विशिष्ट मूल्य वाले रिकॉर्ड कैसे प्राप्त करें

अल्पविराम से अलग सूची के साथ एक और समस्या यह सुनिश्चित कर रही है कि मूल्य सुसंगत हैं - पाठ को संग्रहीत करने का मतलब है कि टाइपो की संभावना ...

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


19

सामान्य तौर पर किसी भी चीज़ की रक्षा की जा सकती है अगर वह आपकी परियोजना की आवश्यकताओं को पूरा करती है। इसका मतलब यह नहीं है कि लोग आपके फैसले का बचाव करेंगे या सहमत होना चाहेंगे ...

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


10

हां, मैं कहूंगा कि यह वास्तव में बहुत बुरा है। यह एक दोषपूर्ण विकल्प है, लेकिन यह इसे सही या अच्छा नहीं बनाता है।

यह पहले सामान्य रूप को तोड़ता है।

एक दूसरी आलोचना यह है कि कच्चे इनपुट परिणामों को सीधे डेटाबेस में डालना, बिना किसी सत्यापन या बंधन के, आपको SQL इंजेक्शन के हमलों के लिए खुला छोड़ देता है।

जिसे आप आलस्य कह रहे हैं और SQL ज्ञान की कमी है वह सामान है जो कि neophytes से बना है। मैं इसे ठीक से करने और सीखने के अवसर के रूप में देखने के लिए समय लेने की सलाह दूंगा।

या इसे वैसे ही छोड़ दें और SQL इंजेक्शन हमले के दर्दनाक सबक सीखें।


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

5
@Paul: और शायद उसी रवैये से उसे बस से टकराया जाएगा जब वह सड़क पार करने से पहले दोनों तरह से देखने में विफल रहता है, लेकिन आपने उसे इसके बारे में चेतावनी नहीं दी है। संपादित करें: मैंने सोचा था कि आप इस उत्तर के पोस्टर थे, मेरी गलती।
हेमराइट

1
@ Hammerite - बसों के लिए आपका एक्सट्रपलेशन हास्यास्पद है।
duffymo

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

1
हाँ मैं समझा। मुझे लगता है कि मेरे पास और भी कारण थे कि बसों के बारे में आपकी चेतावनी।
duffymo

7

वैसे मैं SQL सर्वर में NTEXT कॉलम में एक कुंजी / मान युग्म टैब अलग सूची का उपयोग 4 साल से अधिक समय से कर रहा हूं और यह काम करता है। आप प्रश्न बनाने की लचीलेपन को खो देते हैं, लेकिन दूसरी ओर, यदि आपके पास एक पुस्तकालय है जो कुंजी मूल्य जोड़ी को बनाए रखता / व्युत्पन्न करता है तो यह एक बुरा विचार नहीं है।


13
नहीं, यह एक भयानक विचार है। आप इसके साथ भाग निकलने में कामयाब रहे हैं, लेकिन आपके विकास के समय के कुछ मिनटों की लागत ने आपको घटिया क्वेरी प्रदर्शन, लचीलापन, और आपके कोड की स्थिरता को बनाए रखा है।
पॉल टॉम्बलिन

5
पॉल, मैं सहमत हूं। लेकिन जैसा कि मैंने कहा कि मैंने एक विशिष्ट उद्देश्य के लिए उपयोग किया है, और यह डेटा प्रविष्टि ऑपरेशन के लिए है जहां आपके पास कई प्रकार के फॉर्म हैं। मैं अब डिज़ाइन को संशोधित कर रहा हूं कि मैंने NHibernate सीख लिया है, लेकिन फिर मुझे ASP.NET में फ़ॉर्म को डिज़ाइन करने और कुंजी / मान जोड़ी में कुंजी के रूप में टेक्स्टबॉक्स आईडी का उपयोग करने के लिए लचीलेपन की आवश्यकता है।
राज

28
+1 केवल डाउनवोट्स का मुकाबला करने के लिए। किसी को बताना जिसने रखरखाव की चिंताओं के बारे में 4 साल तक ऐप बनाए रखा है, थोड़ा अनुमान है। स्व-विकास में बहुत कम "भयानक" विचार हैं - ज्यादातर वे बहुत सीमित प्रयोज्यता वाले विचार हैं। यह लोगों को सीमाओं पर चेतावनी देने के लिए उचित है, लेकिन उन लोगों का पीछा करना, जिन्होंने इसे किया है और इसके माध्यम से रहते हैं, मुझे एक होलियर-की तुलना में-तू-तू मैं मैं बिना कर सकते हैं।
मार्क ब्रैकेट

7

मुझे एक बहु-मूल्य स्तंभ की आवश्यकता थी, इसे xml फ़ील्ड के रूप में लागू किया जा सकता है

इसे आवश्यकतानुसार अल्पविराम में परिवर्तित किया जा सकता है

Xquery का उपयोग करके sql सर्वर में XML सूची को क्वेरी करना

एक xml क्षेत्र होने से, कुछ चिंताओं को संबोधित किया जा सकता है।

CSV के साथ: यह सुनिश्चित नहीं कर सकता कि प्रत्येक मान सही डेटा प्रकार है: 1,2,3, केला, 5 को रोकने का कोई तरीका नहीं

एक्सएमएल के साथ: एक टैग में मूल्यों को सही प्रकार होने के लिए मजबूर किया जा सकता है


CSV के साथ: मानों को लुकअप टेबल से जोड़ने के लिए विदेशी कुंजी बाधाओं का उपयोग नहीं कर सकते; संदर्भात्मक अखंडता को लागू करने का कोई तरीका नहीं।

XML के साथ: अभी भी एक समस्या है


CSV के साथ: विशिष्टता को लागू नहीं कर सकते: 1,2,3,3,3,5 को रोकने के लिए कोई रास्ता नहीं

XML के साथ: अभी भी एक समस्या है


CSV के साथ: पूरी सूची प्राप्त किए बिना सूची से कोई मान नहीं हटा सकते।

XML के साथ: एकल आइटम हटाया जा सकता है


CSV के साथ: सूची में दिए गए मान के साथ सभी संस्थाओं को खोजना मुश्किल; आपको एक अक्षम तालिका-स्कैन का उपयोग करना होगा।

XML के साथ: xml फ़ील्ड को अनुक्रमित किया जा सकता है


CSV के साथ: सूची में तत्वों को गिनने के लिए, या अन्य समग्र प्रश्न करना मुश्किल है। **

XML के साथ: विशेष रूप से कठिन नहीं है


CSV के साथ: वे संदर्भ तालिका में मानों में शामिल होने के लिए कठिन। **

XML के साथ: विशेष रूप से कठिन नहीं है


CSV के साथ: क्रमबद्ध क्रम में सूची लाने के लिए कठिन।

XML के साथ: विशेष रूप से कठिन नहीं है


CSV के साथ: स्टर्लिंग पूर्णांक द्विआधारी पूर्णांक के रूप में स्ट्रिंग्स के रूप में दो बार के रूप में ज्यादा जगह लेता है।

एक्सएमएल के साथ: स्टोरेज एक सीएसवी से भी बदतर है


CSV के साथ: प्लस बहुत सारे अल्पविराम वर्ण।

XML के साथ: टैग का उपयोग अल्पविराम के बजाय किया जाता है


संक्षेप में, XML का उपयोग सीमांकित सूची के कुछ मुद्दों के आसपास हो जाता है और आवश्यकतानुसार सीमांकित सूची में परिवर्तित किया जा सकता है


6

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


0

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


फ़ॉर्म में कुछ और फ़ील्ड हैं, यह फ़ॉर्म का केवल एक हिस्सा है (जिसे मैंने प्रश्न में अच्छी तरह से समझाया नहीं था)।
मैड साइंटिस्ट

0

यदि आपके पास बूलियन फ़ील्ड की एक निश्चित संख्या है, तो आप प्रत्येक के लिए INT(1) NOT NULL(या BIT NOT NULLयदि यह मौजूद है) या CHAR (0)(अशक्त) का उपयोग कर सकते हैं । तुम भी एक का उपयोग कर सकते हैं SET(मैं सटीक वाक्यविन्यास भूल जाते हैं)।


1
INT(1)4 बाइट्स लेता है; (1)अर्थहीन है।
रिक जेम्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.