2009-04-12 20 views
10

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

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

उदाहरण के लिए, मैं एमवी 5.पोस्ट्स से चयन कर रहा हूं और एमवी 6.पोस्ट्स में डालने वाला हूं। सम्मिलित करने पर, मैं MV6.Posts में नई पंक्ति की आईडी पुनर्प्राप्त करता हूं और इसे पुराने MV5.Posts.MV6ID फ़ील्ड में अद्यतन करता हूं।

क्या इस अद्यतन को INSERT के माध्यम से चयन करने का कोई तरीका है इसलिए मुझे प्रत्येक रिकॉर्ड को मैन्युअल रूप से संसाधित करने की आवश्यकता नहीं है? मैं एसक्यूएल सर्वर 2005, देव संस्करण का उपयोग कर रहा हूँ।

उत्तर

9

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

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

विशेष रूप से जटिल प्रत्येक संबंधित तालिका के लिए एक या अधिक परीक्षण मामलों शामिल करना न भूलें डेटा के कुछ परीक्षण मामलों बाहर उठाओ। मौजूदा मानों को कार्य तालिका में संग्रहीत करें।

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

फिर संबंधित तालिकाओं के साथ ऐसा ही करें। तब की तरह कुछ के साथ विदेशी कुंजी फ़ील्ड अपडेट कर तालिका में पुराने कुंजी मान का उपयोग करें:

Update t2 
set fkfield = newkey 
from table2 t2 
join table1 t1 on t1.oldkey = t2.fkfield 

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

0

AFAIK, आप एक ही एसक्यूएल बयान

आप फिर भी प्राप्त करने के लिए आप क्या करना चाहते हैं चलाता उपयोग कर सकते हैं के साथ दो अलग-अलग टेबल अद्यतन नहीं कर सकते।

2

सबसे अच्छा आप कर सकते हैं जो मुझे पता है output clause के साथ है। मान लें कि आप एसक्यूएल 2005 या 2008 है

USE AdventureWorks; 
GO 
DECLARE @MyTableVar table(ScrapReasonID smallint, 
          Name varchar(50), 
          ModifiedDate datetime); 
INSERT Production.ScrapReason 
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate 
     INTO @MyTableVar 
VALUES (N'Operator error', GETDATE()); 

यह अभी भी एक दूसरे मूल तालिका अद्यतन करने के लिए पास की आवश्यकता होगी; हालांकि, यह आपके तर्क को आसान बनाने में मदद कर सकता है। क्या आपको स्रोत तालिका को अपडेट करने की आवश्यकता है? आप बस नई आईडी को तीसरी क्रॉस संदर्भ तालिका में स्टोर कर सकते हैं।

1

हे। मुझे माइग्रेशन में ऐसा करना याद है।

नई तालिका में पुरानी_आईडी डालने से अद्यतन दोनों आसान हो जाता है - आप केवल insert into newtable select ... from oldtable, और रिकॉर्ड के बाद के "सिलाई" को आसान बना सकते हैं। "सिलाई" में आप या तो नए माता-पिता (insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild) पर उप-चयन करके, बाल तालिकाओं की विदेशी कुंजी को सम्मिलित करेंगे, या आप बच्चों को सम्मिलित करेंगे और विदेशी कुंजी को ठीक करने के लिए एक अलग अपडेट करेंगे।

इसे एक डालने में करना तेज है; इसे एक अलग चरण माप में कर रहे हैं कि आपके आवेषण क्रम पर निर्भर नहीं हैं, और यदि आवश्यक हो तो फिर से किया जा सकता है।

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

दरअसल, यदि आपके पास विदेशी कुंजी सही ढंग से परिभाषित हैं, तो आप अपने सम्मिलित विवरण उत्पन्न करने के लिए सिस्टेबल/सूचना-स्कीमा का उपयोग कर सकते हैं।

4

शायद सबसे आसान तरीका एमवी 6 पर कॉलम जोड़ना होगा। पुराने आईडी के लिए पोस्ट, फिर पुरानी तालिका से सभी रिकॉर्ड्स को नई तालिका में डालें।

UPDATE mv5.posts 
SET newid = n.id 
FROM mv5.posts o, mv6.posts n 
WHERE o.id = n.oldid 

आप को साफ और oldId स्तंभ ड्रॉप बाद में, जब आप कर सकते हैं: अंतिम, की तरह कुछ के साथ नई तालिका में oldId पर पुराने तालिका मिलान अद्यतन करें।

+0

मैं वास्तव में लगता है कि नए मेज पर oldId छोड़ने वर्ष मेज पर एक एक newId है, जो इस और भी आसान बनाता होने के लिए बेहतर है। – ninesided

0

MV5.Post

से .. MV6.Post.OldMV5Id

में

MV6.Post में एक डालने का चयन बनाने के एक स्तंभ बनाने

तो MV5.Post की एक अद्यतन करते हैं।एमवी 6आईडी

1

क्या इस अद्यतन को INSERT के माध्यम से चयन करने का कोई तरीका है इसलिए मुझे प्रत्येक रिकॉर्ड को मैन्युअल रूप से संसाधित करने की आवश्यकता नहीं है?

जब से तुम यह मैन्युअल नहीं करना चाहता है, लेकिन स्वचालित रूप से, MV6.Posts पर ट्रिगर बनाने ताकि UPDATE स्वचालित रूप से MV5.Posts पर तब होता है जब आप MV6.Posts में सम्मिलित करें। एक मौजूदा बैकअप के बिना सबसे पहले, कुछ भी नहीं करते:

और आपके ट्रिगर की तरह कुछ लग सकता है,

create trigger trg_MV6Posts 
on MV6.Posts 
after insert 
as 
begin 
    set identity_insert MV5.Posts on 

    update MV5.Posts 
    set ID = I.ID 
    from inserted I 

    set identity_insert MV5.Posts off 
end 
संबंधित मुद्दे