क्या एनम डेटा प्रकार का उपयोग करने के बजाय एक नया डेटाबेस तालिका बनाना बेकार है?


38

मान लीजिए कि मेरे पास 4 प्रकार की सेवाएं हैं जो मैं प्रदान करता हूं (वे अक्सर बदलने की संभावना नहीं हैं):

  • परिक्षण
  • डिज़ाइन
  • प्रोग्रामिंग
  • अन्य

मान लीजिए कि मेरे पास 60-80 वास्तविक सेवाएँ हैं, जिनमें से प्रत्येक उपरोक्त श्रेणियों में से एक में आती है। उदाहरण के लिए, 'ए सर्विस' तकनीक ए का उपयोग करके "टेस्ट प्रोग्राम" हो सकता है और यह "परीक्षण" प्रकार का है।

मैं उन्हें एक डेटाबेस में बदलना चाहता हूं। मैं कुछ विकल्पों के साथ आया:

विकल्प 0:

VARCHARसीधे सेवा प्रकार को एक स्ट्रिंग के रूप में एन्कोड करने के लिए सीधे उपयोग करें

विकल्प 1:

डेटाबेस का उपयोग करें enum। लेकिन, एनम बुराई है

विकल्प 2:

दो तालिकाओं का उपयोग करें:

service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);

मैं भी संदर्भात्मक अखंडता का आनंद ले सकते हैं:

ALTER service_line_item 
    ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);

अच्छा लगता है, हाँ?

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

विकल्प 3:

उपयोग न करें enum, दो तालिकाओं का उपयोग न करें, लेकिन सिर्फ एक पूर्णांक स्तंभ का उपयोग करें

service_line_item (
    id,
    service_type INT,        -- use 0, 1, 2, 3 (for service types)
    description VARCHAR
);

यह एक um फर्जी एनम ’की तरह है, जिसे चीजों के कोड साइड पर अधिक ओवरहेड की आवश्यकता होती है, जैसे कि यह जानना {2 == 'Programming'}और उससे उचित तरीके से निपटना।

सवाल:

वर्तमान में मैंने इसे विकल्प 2 का उपयोग करके लागू किया है , अवधारणाओं के तहत निर्देशित

  1. एनम का उपयोग न करें (विकल्प 1)
  2. स्प्रेडशीट के रूप में डेटाबेस का उपयोग करने से बचें (विकल्प 0)

लेकिन मैं यह महसूस करने में मदद नहीं कर सकता कि प्रोग्रामिंग और संज्ञानात्मक ओवरहेड के संदर्भ में मुझे बेकार लगता है - मुझे दो तालिकाओं के बारे में पता होना चाहिए, और दो तालिकाओं, बनाम एक के साथ व्यवहार करना होगा।

'कम बेकार' तरीके के लिए, मैं देख रहा हूं Option 3। आईटी हल्का होता है और इसे अनिवार्य रूप से एक ही कोड को संचालित करने की आवश्यकता होती है (मामूली संशोधनों के साथ लेकिन जटिलता और संरचना मूल रूप से एक ही है लेकिन एक एकल तालिका के साथ)

मुझे लगता है कि आदर्श रूप में यह हमेशा बेकार नहीं होता है, और दोनों में से किसी एक विकल्प के लिए अच्छे मामले हैं, लेकिन क्या एक अच्छा दिशानिर्देश है जब किसी को विकल्प 2 और कब विकल्प 3 का उपयोग करना चाहिए?

जब केवल दो प्रकार होते हैं (बाइनरी)

इस प्रश्न को थोड़ा और जोड़ने के लिए ... उसी स्थान पर, मेरे पास "मानक" या "अपवाद" सेवा का एक द्विआधारी विकल्प है, जो सेवा लाइन आइटम पर लागू हो सकता है। मैंने विकल्प 3 का उपयोग करते हुए एनकोड किया है ।

मैंने मान {{मानक ”,“ अपवाद ”} रखने के लिए नई तालिका नहीं बनाने का निर्णय लिया। इसलिए मेरा कॉलम सिर्फ {0, 1} रखता है और मेरे कॉलम का नाम कहा जाता है exception, और मेरा कोड एक अनुवाद कर {0, 1} => {STANDARD, EXCEPTION}रहा है (जिसे मैंने प्रोग्रामिंग भाषा में स्थिरांक के रूप में एन्कोड किया है)

अब तक उस तरह से या तो ..... पसंद नहीं है (विकल्प 2 पसंद नहीं है और न ही विकल्प 3)। मैं विकल्प 2 को 3 से बेहतर पाता हूं, लेकिन अधिक ओवरहेड के साथ, और फिर भी मैं एन्कोडिंग चीजों से बच नहीं सकता क्योंकि पूर्णांक से कोई फर्क नहीं पड़ता कि मैं 2 और 3 में से किस विकल्प का उपयोग करता हूं।

ORM

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

मैंने पहली बार service_types, और फिर service_line_items को आबाद किया , क्योंकि एक वास्तविक स्प्रेडशीट से मौजूदा सूची थी। इसलिए 'मानक / अपवाद' और 'परीक्षण' जैसी चीजें स्प्रेडशीट पर सभी तार हैं, और उन्हें डीबी में संग्रहीत करने से पहले उचित प्रकारों में एन्कोड किया जाना है।

मुझे यह SO उत्तर मिला: doctrine2 में ENUM के बजाय आप क्या उपयोग करते हैं? , जिसने डीबी के एनम निर्माण का उपयोग नहीं करने का सुझाव दिया, लेकिन एक INTक्षेत्र का उपयोग करने के लिए और प्रोग्रामिंग भाषा के 'कास्ट' निर्माण का उपयोग करके प्रकारों को एन्कोड करने के लिए।

लेकिन जैसा कि ऊपर एसओ प्रश्न में कहा गया है, मैं सीधे पूर्णांक का उपयोग करने से बच सकता हूं और भाषा निर्माण - स्थिरांक का उपयोग कर सकता हूं - एक बार जब वे परिभाषित होते हैं ...।

लेकिन फिर भी .... कोई फर्क नहीं पड़ता कि आप इसे कैसे चालू करते हैं, अगर मैं stringएक प्रकार के रूप में शुरू कर रहा हूं, तो मुझे पहले इसे एक उचित प्रकार में बदलना होगा, यहां तक ​​कि एक ओआरएम का उपयोग करते समय भी।

तो अगर कहते हैं $str = 'Testing';, मुझे अभी भी कहीं एक ब्लॉक की आवश्यकता है जो कुछ ऐसा करता है:

switch($str):
{ 
    case 'Testing':  $type = MyEntity::TESTING; break;
    case 'Other':    $type = MyEntity::OTHER; break;
}

अच्छी बात यह है कि आप पूर्णांक / मैजिक नंबरों के साथ काम नहीं कर रहे हैं [इसके बजाय, एन्कोडेड निरंतर मात्रा के साथ काम कर रहे हैं], लेकिन बुरी बात यह है कि आप इस रूपांतरण चरण के बिना डेटाबेस में चीजों को ऑटो-जादुई रूप से खींच नहीं सकते, मेरे लिए ज्ञान।

और इसका मतलब है कि, मेरे हिस्से में, "अभी भी चीजों को सांकेतिक शब्दों में बदलना और पूर्णांक से निपटने के लिए" जैसी चीजें हैं। (दी गई, अब, Ocramius की टिप्पणी के बाद, मुझे सीधे पूर्णांक के साथ सौदा नहीं करना होगा, लेकिन नामांकित स्थिरांक और स्थिरांक से / के रूप में कुछ रूपांतरण करने की आवश्यकता है)।


9
आप जो भी करते हैं, वह # 3 न करें। इसे बनाए रखने वाले मनोरोगी को लगातार यह पता लगाना होगा कि उन जादुई संख्याओं का क्या मतलब है। यदि आप ऐसा करते हैं, तो आपको बेहतर आशा है कि वे नहीं जानते कि आप कहाँ रहते हैं। blog.codinghorror.com/coding-for-violent-psychopaths
RubberDuck

7
मुझे विकल्प 2 पसंद है। यदि आपको लुकअप टेबल का प्रसार पसंद नहीं है, तो एक तालिका का उपयोग करें और "लुकअप प्रकार" कॉलम जोड़ें। लेकिन हाँ, लुकअप टेबल बनाना ऐसा करने का "मानक" तरीका है, क्योंकि यह आपको मज़ेदार चीजें करने की अनुमति देता है जैसे कि यूआई में आसानी से गिरावट आती है।
रॉबर्ट हार्वे

यहां अपनी पोस्ट में "EDIT" का उपयोग न करें; हम एक मंच नहीं हैं। प्रत्येक स्टैक एक्सचेंज पोस्ट में पहले से ही एक विस्तृत संपादन इतिहास होता है जिसे कोई भी देख सकता है।
रॉबर्ट हार्वे

अगर मैं EDIT का उपयोग नहीं कर सकता, तो मुझे क्या उपयोग करना चाहिए?
डेनिस

बस पोस्ट को संपादित करें और इसे स्वाभाविक दिखें, जैसे मैंने पहले ही किया है। परिवर्तनों की समीक्षा करने के लिए संपादन इतिहास देखें ।
रॉबर्ट हार्वे

जवाबों:


35

विकल्प # 2, संदर्भ तालिकाओं का उपयोग करते हुए, इसे करने का मानक तरीका है। यह लाखों प्रोग्रामर द्वारा उपयोग किया गया है, और काम करने के लिए जाना जाता है। यह एक पैटर्न है , इसलिए आपके सामान को देखने वाले किसी अन्य व्यक्ति को तुरंत पता चल जाएगा कि क्या चल रहा है। पुस्तकालयों और उपकरण मौजूद हैं जो डेटाबेस पर काम करते हैं, आपको बहुत सारे और बहुत सारे काम से बचाते हैं, जो इसे सही तरीके से संभालेंगे। इसके उपयोग के लाभ असंख्य हैं।

क्या यह बेकार है? हाँ, लेकिन केवल थोड़ा। कोई भी आधा-अधूरा डेटाबेस हमेशा ऐसी छोटी-छोटी तालिकाओं के साथ जुड़ता रहेगा, जो कि बेकार होती हैं।

आपके द्वारा वर्णित सभी अन्य विकल्प MySQL's सहित तदर्थ और हैकी हैं enum, क्योंकि यह SQL मानक का हिस्सा नहीं है। (इसके अलावा, क्या enumMySQL के कार्यान्वयन के साथ बेकार है, विचार ही नहीं। मैं इसे मानक के हिस्से के रूप में एक दिन देखने में बुरा नहीं मानूंगा।)

एक सादे पूर्णांक का उपयोग करने के साथ आपका अंतिम विकल्प # 3 विशेष रूप से हैकी है। आपको सभी दुनिया के सबसे खराब मिलते हैं: कोई संदर्भात्मक अखंडता, कोई नामित मूल्य, डेटाबेस में कोई निश्चित ज्ञान नहीं है कि मूल्य क्या है, बस मनमाने ढंग से पूर्णांक सभी जगह फेंक दिए जाते हैं। इस टोकन के द्वारा, आप अपने कोड में स्थिरांक का उपयोग करना छोड़ सकते हैं, और इसके बजाय हार्ड-कोडित मूल्यों का उपयोग करना शुरू कर सकते हैं। circumference = radius * 6.28318530718;। उस के बारे में कैसा है?

मुझे लगता है कि आपको फिर से जांच करनी चाहिए कि आप संदर्भ तालिका को क्यों पाते हैं। जहाँ तक मुझे पता है, उन्हें कोई और नहीं मिला। क्या ऐसा हो सकता है कि यह इसलिए है क्योंकि आप नौकरी के लिए सही उपकरणों का उपयोग नहीं कर रहे हैं?

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

अंत में, यदि आप डेटाबेस के साथ सीधे काम करते हुए अपने जीवन को आसान बनाना चाहते हैं, तो कम से कम दो चीजें हैं जो आप कर सकते हैं, कि मैं अभी सोच सकता हूं:

  1. जो भी संदर्भ तालिकाएँ वे संदर्भ के साथ अपनी मुख्य तालिकाओं में शामिल करते हैं, उन्हें बनाएं, ताकि प्रत्येक पंक्ति में केवल संदर्भ आईडी न हों, बल्कि संबंधित नाम भी हों।

  2. संदर्भ तालिका के लिए पूर्णांक आईडी का उपयोग करने के बजाय, 4-अक्षर संक्षिप्तिकरण के साथ एक CHAR (4) कॉलम का उपयोग करें। तो, आपकी श्रेणियों के आईडी "टेस्ट", "DSGN", "PROG", "OTHR" बन जाएंगे। (उनका वर्णन उचित अंग्रेजी शब्द रहेगा, निश्चित रूप से।) यह थोड़ा धीमा होगा, लेकिन मुझ पर भरोसा करें, किसी को भी ध्यान नहीं होगा।

अंत में, जब केवल दो प्रकार होते हैं, तो ज्यादातर लोग सिर्फ बूलियन कॉलम का उपयोग करते हैं। तो, उस "मानक / अपवाद" कॉलम को बूलियन के रूप में लागू किया जाएगा और इसे "IsException" कहा जाएगा।


3
एक तरफ के रूप में, Postgres भी enum प्रकार , भी है। वे सरल और कुछ खास नहीं हैं, जिससे आपको मूल्य के रूप में पठनीय स्ट्रिंग का उपयोग करने की अनुमति मिलती है, लेकिन हुड के नीचे एक अधिक कुशल पूर्णांक का उपयोग किया जाता है।
कैट

मामले के बारे में क्या है जब डेटा परिणामी दोहराया जाता है, लेकिन निरर्थक नहीं है (उदाहरण के लिए अद्यतन / प्रविष्टि / विलोपन विसंगतियों में परिणाम नहीं होगा)? उदाहरण के लिए, किसी व्यक्ति का लिंग (नए डेटा प्रकारों को पेश करने की संभावना नहीं है, कभी भी लिंग का नाम बदलने की आवश्यकता नहीं होगी, आदि)
एडम थॉम्पसन

यह: क्योंकि अंततः आपको पता चलेगा कि आपको एक "स्वीकृति वातावरण" की आवश्यकता है और आपके बदलते हुए वातावरण को बदलने की आवश्यकता नहीं है।
बी पर Pieter B

3

विकल्प 2 प्रोग्रामिंग अंत पर स्थिरांक या एनम के साथ।
यद्यपि यह ज्ञान को दोहराता है, सत्य स्रोत के एकल स्रोत का उल्लंघन करते हुए, आप फेल-फास्ट तकनीक का उपयोग करके इससे निपट सकते हैं । जब आपका सिस्टम लोड करता है तो यह जाँच करेगा कि डेटाबेस में एनम या कास्ट वैल्यू मौजूद हैं। यदि नहीं, तो सिस्टम को एक त्रुटि फेंकनी चाहिए और लोड करने से इनकार करना चाहिए। आम तौर पर इस बग को इस समय पर ठीक करना सस्ता होगा जब बाद में कुछ और गंभीर हो सकता है।


0

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

अपने उपयोगकर्ताओं में अपने चार श्रेणियों देख सकते हैं अपने खुद के भाषा है, लेकिन अपने डेटाबेस तालिकाओं अभी भी मानों शामिल आप पढ़ सकते हैं - और यह से कोई भी किसी भी डेटाबेस संरचना या कोड परिवर्तन की आवश्यकता है!

table service_type 
( id VARCHAR 
, name VARCHAR 
  primary key ( id ) 
);
table service_line_item 
( id 
, service_type VARCHAR 
, description VARCHAR
  foreign key ( service_type ) references service_type ( id )
);

select * from service_type ; 

+-------------+----------------+
| id          | name           |
+-------------+----------------+
| Testing     | Testen         |
| Design      | Design         | 
| Programming | Programmierung |
| Other       | Andere         |
+-------------+----------------+

या, अपने फ्रांसीसी ग्राहकों के लिए ...

update services_types set name = 'Essai'         where id = 'Testing'; 
update services_types set name = 'Conception'    where id = 'Design'; 
update services_types set name = 'Programmation' where id = 'Programming'; 
update services_types set name = 'Autre'         where id = 'Other'; 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.