बल्क इंसर्ट M: N रिलेशन इन पोस्टग्रेक्यूक्यूएल


9

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

CREATE TABLE employee (ident TEXT PRIMARY KEY, name TEXT, supervisor_name TEXT)

अब, नया डेटाबेस इस प्रकार है:

CREATE TABLE person (id BIGSERIAL PRIMARY KEY, name TEXT, old_ident TEXT);
CREATE TABLE team (id BIGSERIAL PRIMARY KEY);
CREATE TABLE teammember (person_id BIGINT, team_id BIGINT, role CHAR(1));

यही है, अपने पर्यवेक्षकों के नामों के साथ कर्मचारियों की सादे तालिका के बजाय, नया (अधिक सामान्य) डेटाबेस लोगों की टीम बनाने में सक्षम बनाता है। कर्मचारी भूमिका के साथ सदस्य हैं 'e', भूमिका के साथ पर्यवेक्षक हैं 's'

सवाल यह है कि employeeनई संरचना से डेटा को आसानी से कैसे स्थानांतरित किया जाए , प्रति कर्मचारी-पर्यवेक्षक जोड़ी एक टीम। उदाहरण के लिए, कर्मचारी

employee: ('abc01', 'John', 'Dave'), ('abc02', 'Kyle', 'Emily')

के रूप में माइग्रेट किया जाना है

person: (1, 'John', 'abc01'), (2, 'Dave', NULL), (3, 'Kyle', 'abc02'), (4, 'Emily', NULL)
team: (1), (2)
teammember: (1, 1, 'e'), (2, 1, 's'), (3, 2, 'e'), (4, 2, 's')

मैं एक डेटा-संशोधित सीटीई का उपयोग करने पर विचार करूंगा, पहले कर्मचारियों और पर्यवेक्षकों को सम्मिलित करूंगा, उसके बाद टीमों को। हालाँकि, CTE केवल सम्मिलित तालिका पंक्ति से डेटा वापस कर सकता है। इस प्रकार, मैं यह देखने में सक्षम नहीं हूं कि कौन पर्यवेक्षक कौन था।

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

कई हजारों कर्मचारियों के लिए मोटे तौर पर कई सैकड़ों होंगे। हालांकि यह आम तौर पर एक अच्छा अभ्यास है, मेरे मामले में, मैं पुराने के आधार पर नई आईडी उत्पन्न नहीं करना चाहूंगा, क्योंकि पुरानी आईडी की तरह तार हैं *.GM2। मैं उन्हें old_identसंदर्भ के लिए कॉलम में संग्रहीत करता हूं ।


3
मैं नई टेबलों में कुछ अस्थायी पहचानकर्ताओं को जोड़ने का सुझाव दूंगा। इस तरह आप पुराने कनेक्शन होने के दौरान भी उनमें डेटा डाल सकते हैं - फिर आप पुरानी टेबल से आवश्यक पंक्तियाँ ला सकते हैं और उन्हें अगले टेबल में डाल सकते हैं इत्यादि। इसके लिए, मैं अलग SQL कथनों का उपयोग करूँगा, जटिल CTEs या प्रक्रियात्मक कार्यों की कोई आवश्यकता नहीं।
dezso

@dezso सुझाव के लिए धन्यवाद। एक अस्थायी पहचानकर्ता जोड़ना team, जो उस व्यक्ति की आईडी धारण करेगा जिसके लिए टीम बनाई गई थी वह समस्या का समाधान करेगा। मैं अभी भी उत्सुक हूं कि क्या अधिक सुरुचिपूर्ण (यानी, डीडीएल का उपयोग नहीं) समाधान है, हालांकि।
ओडिन्ज बौडा

@ Ond possibleejBouda CTE प्रश्नों के रूप में तालिकाओं का निर्माण संभव हो सकता है, लेकिन यह काफी जटिल हो सकता है। उदाहरण के लिए, पंक्ति गणना की जाँच करके (अस्थायी) टेबल समाधान आपको व्यक्तिगत रूप से चरणों के परीक्षण की विलासिता देता है।
dezso

जवाबों:


1

आपके पास नई जानकारी है जो आपको नए डेटाबेस को पुराने से 4 डालने के बयानों के साथ आबाद करने की आवश्यकता है:

create table team_ids (id serial, name TEXT)

insert into team_ids (name)
select distinct supervisor_name from employee

-- now supervisors have ids assigned by "serial" type

insert into person (id, name, old_ident)
select ident, name, ident from employee
union
select ident, supervisor_name, ident from employee

insert into team (id) -- meh
select id from team_ids

insert into teammember (person_id, team_id, role)
select e.ident, t.id, 'e')
from employee as e, join team_ids as t
on t.name = e.supervisor_name
union -- and, I guess
select t.id, t.id, 'm')
from team_ids as t

आपको स्वाद के लिए समायोजित करना पड़ सकता है। मैं मान रहा हूं कि person.id पर employee.ident को मैप किया जा सकता है, और यह कि आपका DBMS ऑटो-जनरेट वैल्यू वाले कॉलम को मान असाइन करने की अनुमति देता है। सिवाय इसके कि, यह सिर्फ मूल एसक्यूएल है, कुछ भी नहीं फैंसी और, ज़ाहिर है , कोई लूप नहीं।

अतिरिक्त टिप्पणी:

  • विभाग के लिए 'टीम' तालिका (अधिक परंपरागत रूप से) का नाम बदला जा सकता है ।
  • SERIAL(इसकी 2 बिलियन संभावनाओं के साथ) बहुत होना चाहिए, ए की कोई आवश्यकता नहीं है BIGSERIAL
  • टीम के लिए प्रबंधक की 1: 1 कार्डिनैलिटी लागू करने के लिए कोई डेटाबेस तंत्र प्रतीत नहीं होता है। क्या हर टीम को परिभाषा के हिसाब से नेता की जरूरत नहीं है? वहाँ एक नहीं है CHECKया FOREIGN KEYबाधा teammember.role के लिए? शायद सवाल ने इन विवरणों को सरल बना दिया।
  • "टीममम्बर" तालिका का नाम अधिक परंपरागत रूप से शब्द सीमा होगा, उदाहरण के लिए टीममेम्बर या टीम_मेम्बर।

1
इस तरह आपके पास personतालिका में डुप्लिकेट आईडी होगी ।
dezso

0

PL / PgSQL काम करेगा।

DO $$
DECLARE
  _e record;
  _personid bigint;
  _suppersonid bigint;
  _teamid bigint;
BEGIN
  FOR _e IN
    SELECT ident, name, supervisor_name FROM employee
  LOOP
    -- insert person record for employee
    INSERT INTO person (name, old_ident)
      SELECT _e.name, _e.ident
      RETURNING id INTO _personid;
    -- lookup or insert person record for supervisor
    SELECT id INTO _suppersonid FROM person
      WHERE p.name = _e.supervisor_name;
    IF _suppersonid IS NULL THEN
      INSERT INTO person (name) SELECT _e.supervisor_name
        RETURNING id INTO _suppersonid;
    END IF;
    -- lookup team by supervisor or insert new team
    SELECT team_id INTO _teamid FROM teammember tm
      WHERE tm.person_id = _suppersonid AND tm.role = 's';
    IF _teamid IS NULL THEN
      -- new supervisor: insert new team and supervisor
      INSERT INTO team (id) VALUES(DEFAULT) RETURNING id INTO _teamid;
      INSERT INTO teammember (person_id, team_id, role) SELECT _suppersonid, _teamid, 's';
    END IF;
    -- insert team member (non-supervisor) record
    INSERT INTO teammember (person_id, team_id, role) SELECT _personid, _teamid, 'e';
  END LOOP;
END; $$;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.