2013-06-21 10 views
7

मेरे पास एक डेटाबेस है जिसे मैं यूयूआईडी को पोस्टग्रेस्क्ल में प्राथमिक कुंजी के रूप में उपयोग करना चाहता हूं।यूयूआईडी प्राथमिक कुंजी का उपयोग करने के लिए जटिल रेल डेटाबेस को माइग्रेट करने के लिए कैसे करें Postgresql

मेरे पास गहरे बहु-स्तरीय संघों के साथ लगभग 30 टेबल हैं। क्या सभी मौजूदा आईडी को यूयूआईडी में बदलने का कोई आसान तरीका है?

इससे: https://coderwall.com/p/n_0awq, मैं देख सकता हूं कि मैं माइग्रेशन में तालिका को बदल सकता हूं। मैं कुछ इस तरह सोच रहा था:

for client in Client.all 
    # Retrieve children 
    underwritings = client.underwritings 
    # Change primary key 
    execute 'ALTER TABLE clients ALTER COLUMN id TYPE uuid;' 
    execute 'ALTER TABLE clients ALTER COLUMN id SET DEFAULT uuid_generate_v1();' 
    # Get new id - is this already generated? 
    client_id = client.id 
    for underwriting in underwritings 
    locations = underwriting.locations 
    other_record = underwriting.other_records... 

    execute 'ALTER TABLE underwritings ALTER COLUMN id TYPE uuid;' 
    execute 'ALTER TABLE underwritings ALTER COLUMN id SET DEFAULT uuid_generate_v1();' 
    underwriting.client_id = client_id 
    underwriting.saved 
    underwriting_id = underwriting.id 

    for location in locations 
     buildings = location.buildings 
     execute 'ALTER TABLE locations ALTER COLUMN id TYPE uuid;' 
     execute 'ALTER TABLE locations ALTER COLUMN id SET DEFAULT uuid_generate_v1();' 
     location.undewriting_id = underwriting_id 
     location.save 
     location_id = location.id 

     for building in buildings 
     ... 
     end 
    end 
    for other_record in other_records 
     ... 
    end 
    ... 
    ... 
    end 
end 

सवाल:

  • क्या यह काम करता है?
  • क्या ऐसा करने का कोई आसान तरीका है?
  • क्या प्राथमिक रिकॉर्ड बदलने से पहले जब तक उन्हें पुनर्प्राप्त किया जाता है तब तक बच्चे के रिकॉर्ड ठीक से पुनर्प्राप्त किए जाएंगे?
  • क्या नई प्राथमिक कुंजी पहले से ही परिवर्तित तालिका के रूप में उत्पन्न हो जाएगी?

ऐसा करने में किसी भी मदद या सुझाव के लिए बहुत बहुत धन्यवाद।

+0

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

उत्तर

4

मुझे लगता है कि रेल के माध्यम से ऐसा कुछ करने की कोशिश करना सिर्फ जटिलताओं को जटिल करेगा। मैं पूरी तरह से रेल की तरफ से अनदेखा करता हूं और इसे एसक्यूएल में करता हूं।

आपका पहला कदम आपके डेटाबेस का पूर्ण बैकअप ले लेता है। फिर उस बैकअप को किसी अन्य डेटाबेस में पुनर्स्थापित करें:

  1. सुनिश्चित करें कि आपका बैकअप काम करता है।
  2. आपको यथार्थवादी प्लेपेन दें जहां आप बिना किसी परिणाम के गलतियां कर सकते हैं।

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

अब आपके पास नए यूयूआईडी संस्करणों के लिए जगह बनाने के लिए स्वच्छ डेटा, rename all your tables है। एक तालिका t के लिए, हम नामित तालिका को t_tmp के रूप में देखेंगे। प्रत्येक t_tmp के लिए, इस तरह id है, कुछ नया UUID करने के लिए पुराने integerid रों से मानचित्रण धारण करने के लिए एक और तालिका बनाने:

create table t_id_map (
    old_id integer not null, 
    new_id uuid not null default uuid_generate_v1() 
) 

और फिर इसे पॉप्युलेट:

insert into t_id_map (old_id) 
select id from t_tmp 

और तुम ' आप यहां होने पर शायद t_id_map.old_id को इंडेक्स करना चाहते हैं।

यह हमें integer आईडी के साथ पुरानी टेबल और प्रत्येक t_tmp के लिए एक लुकअप टेबल देता है जो पुराने id को नए में मानचित्र करता है।

अब id एस वाले सभी पुराने integer और serial कॉलम को बदलने वाले यूयूआईडी के साथ नई टेबल बनाएं; मैं इस बिंदु पर असली विदेशी कुंजी भी जोड़ूंगा; आपको अपने डेटा के बारे में पागल होना चाहिए: टूटा कोड अस्थायी है, टूटा डेटा आमतौर पर हमेशा के लिए होता है।

नई टेबल से पॉप्युलेट इस बिंदु पर बहुत आसान है: बस नए लोगों के लिए पुराने id रों मैप करने के लिए उचित t_id_map तालिकाओं के लिए insert into ... select ... from निर्माणों का उपयोग करें और शामिल हों। एक बार डेटा मैप किया गया है और कॉपी किया गया है, तो आप यह सुनिश्चित करने के लिए कुछ सैनिटी जांच करना चाहेंगे कि सबकुछ अभी भी समझ में आता है। फिर आप अपना t_tmp और t_id_map टेबल छोड़ सकते हैं और अपने जीवन के साथ आगे बढ़ सकते हैं।

उस प्रक्रिया का अभ्यास करें जो आपके डेटाबेस की प्रतिलिपि पर है, इसे स्क्रिप्ट करें, और दूर जाएं।

आप निश्चित रूप से इस काम को करने के दौरान अपने डेटाबेस तक पहुंचने वाले किसी भी एप्लिकेशन को बंद करना चाहते हैं।

1

विदेशी कुंजी नहीं जोड़ना चाहते थे, और रेल माइग्रेशन का उपयोग करना चाहते थे। वैसे भी, यहाँ है मैं क्या किया है, तो दूसरों को ऐसा करने के लिए देख रहे हैं (2 टेबल के लिए उदाहरण के लिए, मैं कुल 32 में किया था):

def change 
    execute 'CREATE EXTENSION "uuid-ossp";' 
    execute <<-SQL 
     ALTER TABLE buildings ADD COLUMN guid uuid DEFAULT uuid_generate_v1() NOT NULL; 
     ALTER TABLE buildings ALTER COLUMN guid SET DEFAULT uuid_generate_v1(); 
     ALTER TABLE buildings ADD COLUMN location_guid uuid; 

     ALTER TABLE clients ADD COLUMN guid uuid DEFAULT uuid_generate_v1() NOT NULL; 
     ALTER TABLE clients ALTER COLUMN guid SET DEFAULT uuid_generate_v1(); 
     ALTER TABLE clients ADD COLUMN agency_guid uuid; 
     ALTER TABLE clients ADD COLUMN account_executive_guid uuid; 
     ALTER TABLE clients ADD COLUMN account_representative_guid uuid; 
    SQL 

    for record in Building.all 
     location = record.location 
     record.location_guid = location.guid 

     record.save 
    end 

    for record in Client.all 
     agency = record.agency 
     record.agency_guid = agency.guid 

     account_executive = record.account_executive 
     record.account_executive_guid = account_executive.guid unless account_executive.blank? 

     account_representative = record.account_representative 
     record.account_representative_guid = account_representative.guid unless account_representative.blank? 

     record.save 
    end 

    execute <<-SQL 
     ALTER TABLE buildings DROP CONSTRAINT buildings_pkey; 
     ALTER TABLE buildings DROP COLUMN id; 
     ALTER TABLE buildings RENAME COLUMN guid TO id; 
     ALTER TABLE buildings ADD PRIMARY KEY (id); 
     ALTER TABLE buildings DROP COLUMN location_id; 
     ALTER TABLE buildings RENAME COLUMN location_guid TO location_id; 

     ALTER TABLE clients DROP CONSTRAINT clients_pkey; 
     ALTER TABLE clients DROP COLUMN id; 
     ALTER TABLE clients RENAME COLUMN guid TO id; 
     ALTER TABLE clients ADD PRIMARY KEY (id); 
     ALTER TABLE clients DROP COLUMN agency_id; 
     ALTER TABLE clients RENAME COLUMN agency_guid TO agency_id; 
     ALTER TABLE clients DROP COLUMN account_executive_id; 
     ALTER TABLE clients RENAME COLUMN account_executive_guid TO account_executive_id; 
     ALTER TABLE clients DROP COLUMN account_representative_id; 
     ALTER TABLE clients RENAME COLUMN account_representative_guid TO account_representative_id; 
    SQL 
    end 
9

मैं इन काफी थकाऊ हो पाया। मौजूदा डेटा के साथ तालिका को कन्वर्ट करने के लिए PostgreSQL को सीधी क्वेरी का उपयोग करना संभव है।

प्राथमिक कुंजी के लिए:

ALTER TABLE students 
     ALTER COLUMN id DROP DEFAULT, 
     ALTER COLUMN id SET DATA TYPE UUID USING (uuid(lpad(replace(text(id),'-',''), 32, '0'))), 
     ALTER COLUMN id SET DEFAULT uuid_generate_v4() 

अन्य संदर्भ के लिए:

ALTER TABLE students 
     ALTER COLUMN city_id SET DATA TYPE UUID USING (uuid(lpad(replace(text(city_id),'-',''), 32, '0'))) 

ऊपर बाईं पैड शून्य से पूर्णांक मान और एक UUID को बदल देता है। इस दृष्टिकोण को आईडी मैपिंग की आवश्यकता नहीं है और यदि आवश्यक पुरानी आईडी पुनर्प्राप्त की जा सकती है।

चूंकि कोई डेटा कॉपी नहीं है, यह दृष्टिकोण काफी तेज़ काम करता है।

पॉलिमॉर्फिक संघों के इन और अधिक जटिल मामले को संभालने के लिए कृपया https://github.com/kreatio-sw/webdack-uuid_migration का उपयोग करें। यह मणि इन माइग्रेशन को कम करने के लिए ActiveRecord :: माइग्रेशन में अतिरिक्त सहायक जोड़ता है।

+0

धन्यवाद - यह यूजर को पूर्णांक – house9

+0

से माइग्रेशन को सरल बनाता है यह संबंधों को अद्यतन नहीं करता है? – riley

+0

@riley इस बात पर निर्भर करता है कि रेल माइग्रेशन के किस संस्करण का मूल रूप से उपयोग किया जाता था। यदि विदेशी कुंजी संबंध परिभाषित किए गए हैं (जो कुछ रेल संस्करण करते हैं), तो यह संबंधित कॉलम अपडेट करने का प्रयास करेगा। यदि नहीं, तो आपको अपने आप को संबंधों को अपडेट करना होगा (ऐसा करने के लिए सहायक विधि है)। –

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

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