2008-11-27 14 views
122

मान लें कि मेरे पास डेटाबेस में एक रिकॉर्ड है और दोनों व्यवस्थापक और सामान्य उपयोगकर्ता अपडेट कर सकते हैं।डेटाबेस में रिकॉर्ड को कैसे नियंत्रित करें

क्या कोई भी इस तालिका में प्रत्येक बदलाव को संस्करण को नियंत्रित करने के लिए एक अच्छा दृष्टिकोण/वास्तुकला का सुझाव दे सकता है, इसलिए पिछले संशोधन में रिकॉर्ड को रोल करना संभव है।

उत्तर

123

मान लें कि आपके पास FOO तालिका है जो व्यवस्थापक और उपयोगकर्ता अपडेट कर सकते हैं। अधिकांश समय आप खाद्य तालिका के खिलाफ प्रश्न लिख सकते हैं। खुशी के दिन।

फिर, मैं FOO_HISTORY तालिका बनाउंगा। इसमें FOO तालिका के सभी कॉलम हैं। प्राथमिक कुंजी फूड प्लस एक रेविजन नम्बर कॉलम जैसा ही है। FOO_HISTORY से FOO पर एक विदेशी कुंजी है। आप संशोधन आईडी से संबंधित कॉलम भी जोड़ सकते हैं जैसे कि UserId और RevisionDate। सभी *_HISTORY तालिकाओं (यानी ओरेकल अनुक्रम या समकक्ष से) में लगातार बढ़ते फैशन में RevisionNumbers को पॉप्युलेट करें। एक दूसरे में केवल एक बदलाव होने पर भरोसा मत करो। अर्थात। प्राथमिक कुंजी में RevisionDate डालें।

अब, जब भी आप FOO अपडेट करते हैं, तो आप अपडेट करने से ठीक पहले FOO_HISTORY में पुराने मान डालते हैं। आप इसे अपने डिजाइन में कुछ मौलिक स्तर पर करते हैं ताकि प्रोग्रामर इस चरण को गलती से याद न कर सकें।

यदि आप FOO से कोई पंक्ति हटाना चाहते हैं तो आपके पास कुछ विकल्प हैं। या तो सभी इतिहास को कैस्केड करें और हटाएं, या हटाए गए FOO को फ़्लैग करके लॉजिकल डिलीट करें।

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

+0

यदि आप डेटा एक्सेस लेयर सीधे इसका समर्थन नहीं करते हैं तो आप डेटाबेस ट्रिगर्स के साथ अद्यतन ऑडिट तालिका कर सकते हैं। साथ ही, सिस्टम डेटा डिक्शनरी से आत्मनिरीक्षण का उपयोग करने वाले ट्रिगर बनाने के लिए कोड जेनरेटर बनाना मुश्किल नहीं है। – ConcernedOfTunbridgeWells

+25

मैं woyuld अनुशंसा करता हूं कि आप वास्तव में _new_ डेटा डालें, न कि पिछले, इसलिए इतिहास तालिका में सभी डेटा हैं। यद्यपि यह अनावश्यक डेटा संग्रहीत करता है, फिर भी ऐतिहासिक डेटा की आवश्यकता होने पर दोनों तालिकाओं में खोज से निपटने के लिए आवश्यक विशेष मामलों को समाप्त कर दिया जाता है। – Nerdfest

+0

@Nerdfest - मेरा मतलब इतिहास तालिका में सभी मौजूदा मानों को सम्मिलित करना था, और उसके बाद मुख्य मान को नए मानों के साथ अद्यतन करें। –

35

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

दिमाग में आने वाला सबसे अच्छा उदाहरण मीडियाविकि, विकिपीडिया इंजन है। डेटाबेस आरेख here, विशेष रूप से revision table की तुलना करें।

आप जिस तकनीक का उपयोग कर रहे हैं उसके आधार पर, आपको कुछ अच्छे diff/मर्ज एल्गोरिदम मिलना होगा।

यदि यह .NET के लिए है तो this question देखें।

21

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

जब आप वर्तमान रिकॉर्ड देखना चाहते हैं, तो आप वह चुनें जहां endDate शून्य है।

इसे कभी-कभी एक प्रकार 2 Slowly Changing Dimension कहा जाता है। TupleVersioning

+0

क्या मेरी तालिका इस दृष्टिकोण का उपयोग करके काफी बड़ी नहीं होगी? –

+1

हां, लेकिन आप तालिका के अनुक्रमण और/या विभाजन करके इसका सामना कर सकते हैं। इसके अलावा, केवल बड़ी टेबलों की एक छोटी मुट्ठी भर होगी। ज्यादातर बहुत छोटे होंगे। – ConcernedOfTunbridgeWells

3

आप डेटाबेस नहीं कहते हैं, और मैं इसे पोस्ट टैग में नहीं देखता हूं। यदि यह ओरेकल के लिए है, तो मैं डिजाइनर में बनाए गए दृष्टिकोण की सिफारिश कर सकता हूं: journal tables का उपयोग करें।यदि यह किसी भी अन्य डेटाबेस के लिए है, तो भी, मैं मूल रूप से उसी तरह भी अनुशंसा करता हूं ...

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

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

ओरेकल में आपको जो भी चाहिए वह स्वचालित रूप से SQL कोड के रूप में जेनरेट की जाती है, आपको बस इसे संकलित/चलाने के लिए करना है; और यह एक बुनियादी सीआरयूडी आवेदन (वास्तव में केवल "आर") के साथ आता है इसका निरीक्षण करने के लिए।

3

दो विकल्प:

  1. एक इतिहास तालिका है - यह इतिहास तालिका में पुराने डेटा सम्मिलित जब भी मूल अद्यतन किया जाता है।
  2. ऑडिट तालिका - मूल्यों के पहले और बाद में स्टोर करें - केवल ऑडिट तालिका में संशोधित कॉलम के लिए अन्य जानकारी जैसे अपडेट और कब।
2

आप SQL ट्रिगर्स के माध्यम से SQL तालिका पर ऑडिटिंग कर सकते हैं। एक ट्रिगर से आप 2 विशेष टेबल (inserted and deleted) तक पहुंच सकते हैं। इन सारणी में सटीक पंक्तियां होती हैं जिन्हें तालिका अद्यतन होने पर हर बार डाला या हटा दिया गया था। ट्रिगर एसक्यूएल में आप इन संशोधित पंक्तियों को ले सकते हैं और उन्हें ऑडिट तालिका में डाल सकते हैं। इस दृष्टिकोण का अर्थ है कि आपका ऑडिटिंग प्रोग्रामर के लिए पारदर्शी है; उन्हें या किसी कार्यान्वयन संबंधी ज्ञान से कोई प्रयास करने की आवश्यकता नहीं है।

इस दृष्टिकोण का जोड़ा गया बोनस यह है कि एसक्यूएल ऑपरेशन आपके डेटा एक्सेस डीएलएल के माध्यम से या मैन्युअल एसक्यूएल क्वेरी के माध्यम से किया गया था या नहीं; (जैसा कि ऑडिटिंग सर्वर पर ही किया जाता है)।

7

एसक्यूएल करने के लिए नवीनीकरण 2008

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

MSDN SQL 2008 Change Tracking

2

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

जिस तरह से यह काम करेगा, यह है कि एक बार छात्र ने एक सबक किया है, तो उनके परिणाम उनके द्वारा पूरा किए गए संस्करण से जुड़े हुए हैं। यदि कोई परिवर्तन किया जाता है, तो उनके परिणाम हमेशा उनके संस्करण को इंगित करेंगे।

इस तरह, यदि कोई पाठ मानदंड हटा दिया जाता है या स्थानांतरित किया जाता है, तो उनके परिणाम नहीं बदले जाएंगे।

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

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

मेरे दो सेंट।

2

जबकि @WW। उत्तर एक अच्छा जवाब है एक और तरीका एक संस्करण कॉलम बनाना और अपने सभी संस्करणों को एक ही तालिका में रखना है। नवीनतम आला Word Press

  • से संकेत मिलता है या संस्करण outer join की तुलना में एक बुरा अधिक से अधिक करने के लिए

    • उपयोग एक झंडा:

      एक मेज दृष्टिकोण आप या तो के लिए।

    outer join पद्धति का उपयोग करके संशोधन संख्या का एक उदाहरण एसक्यूएल है:

    SELECT tc.* 
    FROM text_content tc 
    LEFT OUTER JOIN text_content mc ON tc.path = mc.path 
    AND mc.revision > tc.revision 
    WHERE mc.revision is NULL 
    AND tc.path = '/stuff' -- path in this case is our natural id. 
    

    बुरी खबर से ऊपर है एक outer join की आवश्यकता है और बाहरी मिलती धीमी गति से हो सकता है। अच्छी खबर यह है कि नई प्रविष्टियां बनाना सैद्धांतिक रूप से सस्ता है क्योंकि आप में लेनदेन (मान लें कि आपका डेटाबेस परमाणु है) के साथ एक लेखन ऑपरेशन कर सकता है।

    एक उदाहरण '/stuff' के लिए एक नया संशोधन कर रही हो सकता है:

    INSERT INTO text_content (id, path, data, revision, revision_comment, enabled, create_time, update_time) 
    (
    SELECT 
    (md5(random()::text)) -- {id} 
    , tc.path 
    , 'NEW' -- {data} 
    , (tc.revision + 1) 
    , 'UPDATE' -- {comment} 
    , 't' -- {enabled} 
    , tc.create_time 
    , now() 
    FROM text_content tc 
    LEFT OUTER JOIN text_content mc ON tc.path = mc.path 
    AND mc.revision > tc.revision 
    WHERE mc.revision is NULL 
    AND tc.path = '/stuff' -- {path} 
    ) 
    

    हम पुराने डेटा का उपयोग करके डालें। यह विशेष रूप से उपयोगी है अगर आप कहते हैं कि आप केवल एक कॉलम अपडेट करना चाहते हैं और आशावादी लॉकिंग और लेनदेन से बचें।

    ध्वज दृष्टिकोण और इतिहास तालिका दृष्टिकोण दो पंक्तियों को डालने/अपडेट करने की आवश्यकता है।

    outer join संशोधन संख्या दृष्टिकोण के साथ अन्य लाभ यह है कि आप हमेशा ट्रिगर्स के साथ कई तालिका दृष्टिकोण पर प्रतिक्रिया कर सकते हैं क्योंकि आपका ट्रिगर अनिवार्य रूप से ऊपर जैसा कुछ करना चाहिए।

  • 5

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

    संबंधित मुद्दे