कुछ उपकरण हो सकते हैं जो इसे पहले से ही करते हैं, लेकिन एक प्रारंभिक तालिका से सभी पंक्तियों की तालिकाओं को मनमाने ढंग से निकालने के लिए अपने आप में एक छोटा विकास कार्य है। मैं आपके लिए पूरी बात नहीं लिख सकता, लेकिन मैं आपको शुरू कर सकता हूं - मैंने इसे लिखना शुरू कर दिया, लेकिन लगभग 20 मिनट के बाद, मुझे एहसास हुआ कि यह थोड़ा और काम था जिसे मैं एक अवैतनिक उत्तर के लिए प्रतिबद्ध करना चाहता था।पी>
मैं देख सकता हूं कि यह एक पुनरावर्ती पीएल/एसक्यूएल प्रक्रिया द्वारा सबसे अच्छा किया जा रहा है जो स्रोत तालिका के लिए सम्मिलन विवरण बनाने के लिए dbms_ouput और user_cons_columns और user_constraints का उपयोग करेगा। आप सभी इन्सर्ट को लिखकर थोड़ा धोखा दे सकते हैं जैसे कि कॉलम चार मान थे, क्योंकि Oracle किसी भी चार मानों को सही डेटाटाइप में बदल देगा, यह मानते हुए कि आपके NLS पैरामीटर स्रोत और लक्ष्य प्रणाली पर समान हैं।
ध्यान दें, यदि आपकी तालिकाओं में वृत्ताकार संबंध हैं, तो नीचे दिए गए पैकेज में समस्याएँ होंगी; इसके अलावा, Oracle के पुराने संस्करणों पर, आप dbms_output के साथ बफर स्पेस से बाहर हो सकते हैं। उत्पन्न एसक्यूएल को एक स्टेजिंग टेबल में डालने से दोनों समस्याओं को हल किया जा सकता है जिसमें एसक्यूएल पर एक अद्वितीय इंडेक्स होता है, और यदि आपको एक अद्वितीय कुंजी टकराव मिलता है तो रिकर्सन को रद्द कर दिया जाता है। नीचे दिया गया बड़ा समय बचाने वाला MakeParamList फ़ंक्शन है, जो एक कर्सर को परिवर्तित करता है जो कॉलम की सूची को या तो अल्पविराम से अलग सूची में देता है, या एक एकल अभिव्यक्ति जो उन स्तंभों के मूल्यों को एक उद्धृत, अल्पविराम से अलग किए गए रूप में प्रदर्शित करेगा जब इसे चलाया जाएगा तालिका के सामने एक प्रश्न में खंड का चयन करें।
यह भी ध्यान दें कि निम्न पैकेज वास्तव में तब तक काम नहीं करेगा जब तक आप इसे और संशोधित नहीं करते (एक कारण मैंने इसे लिखना बंद कर दिया):उत्पन्न प्रारंभिक सम्मिलन कथन इस धारणा पर आधारित है कि बाधा_वल तर्क पारित होने के परिणामस्वरूप एक पंक्ति होगी जेनरेट - बेशक, जब आप रिकर्सिंग शुरू करते हैं तो यह लगभग निश्चित रूप से नहीं होता है (क्योंकि आपके पास माता-पिता के लिए कई बच्चे पंक्तियां होंगी)। आपको उन मामलों को संभालने के लिए लूप के अंदर होने के लिए पहले कथन (और बाद की रिकर्सिव कॉल) की पीढ़ी को बदलने की आवश्यकता होगी जहां पहले तत्काल तत्काल कॉल पर कॉल एक की बजाय एकाधिक पंक्तियां उत्पन्न करता है। इसे काम करने की मूल बातें यहां हैं, आपको बस विवरणों को पीसना होगा और बाहरी कर्सर को काम करना होगा।
एक अंतिम नोट भी:यह संभावना नहीं है कि आप पंक्तियों का एक सेट उत्पन्न करने के लिए इस प्रक्रिया को चला सकते हैं, जब लक्ष्य प्रणाली में डाला जाता है, जिसके परिणामस्वरूप डेटा का "साफ" सेट होता है, हालांकि आपको सभी निर्भर डेटा मिलेंगे, वह डेटा उन अन्य तालिकाओं पर निर्भर हो सकता है जिन्हें आपने आयात नहीं किया था (उदाहरण के लिए, आपके सामने आने वाली पहली चाइल्ड टेबल में अन्य विदेशी कुंजियाँ हो सकती हैं जो आपकी प्रारंभिक तालिका से असंबंधित तालिकाओं की ओर इशारा करती हैं)। उस स्थिति में, हो सकता है कि आप विवरण तालिकाओं के साथ शुरुआत करना चाहें और नीचे की बजाय ऊपर की ओर काम करना चाहें; ऐसा करने से, आप अपने द्वारा जेनरेट किए गए कथनों के क्रम को उलटना चाहते हैं, या तो एक स्क्रिप्टिंग उपयोगिता का उपयोग करके, या एसक्यूएल को एक स्टेजिंग टेबल में डालने के द्वारा, जैसा कि मैंने ऊपर उल्लेख किया है, अनुक्रम के साथ, फिर इसे अवरोही प्रकार के साथ चुनना ।
इसे लागू करने के लिए, आप कॉमा से अलग किए गए कॉलम की सूची को कॉन्स्ट्रेस_कोल्स के रूप में पास करते हैं और संबंधित कॉमा से अलग किए गए मानों की सूची को Constent_vals के रूप में पास करते हैं, जैसे:
exec Data_extractor.MakeInserts ('MYTABLE', 'COL1, COL2', '99, 105')
यहाँ यह है:
CREATE OR REPLACE PACKAGE data_extractor
IS
TYPE column_info IS RECORD(
column_name user_tab_columns.column_name%TYPE
);
TYPE column_info_cursor IS REF CURSOR
RETURN column_info;
FUNCTION makeparamlist(
column_info column_info_cursor
, get_values NUMBER
)
RETURN VARCHAR2;
PROCEDURE makeinserts(
source_table VARCHAR2
, constraint_cols VARCHAR2
, constraint_vals VARCHAR2
);
END data_extractor;
CREATE OR REPLACE PACKAGE BODY data_extractor
AS
FUNCTION makeparamlist(
column_info column_info_cursor
, get_values NUMBER
)
RETURN VARCHAR2
AS
BEGIN
DECLARE
column_name user_tab_columns.column_name%TYPE;
tempsql VARCHAR2(4000);
separator VARCHAR2(20);
BEGIN
IF get_values = 1
THEN
separator := ''''''''' || ';
ELSE
separator := '';
END IF;
LOOP
FETCH column_info
INTO column_name;
EXIT WHEN column_info%NOTFOUND;
tempsql := tempsql || separator || column_name;
IF get_values = 1
THEN
separator := ' || '''''', '''''' || ';
ELSE
separator := ', ';
END IF;
END LOOP;
IF get_values = 1
THEN
tempsql := tempsql || ' || ''''''''';
END IF;
RETURN tempsql;
END;
END;
PROCEDURE makeinserts(
source_table VARCHAR2
, constraint_cols VARCHAR2
, constraint_vals VARCHAR2
)
AS
BEGIN
DECLARE
basesql VARCHAR2(4000);
extractsql VARCHAR2(4000);
tempsql VARCHAR2(4000);
valuelist VARCHAR2(4000);
childconstraint_vals VARCHAR2(4000);
BEGIN
SELECT makeparamlist(CURSOR(SELECT column_name
FROM user_tab_columns
WHERE table_name = source_table), 0)
INTO tempsql
FROM DUAL;
basesql := 'INSERT INTO ' || source_table || '(' || tempsql || ') VALUES (';
SELECT makeparamlist(CURSOR(SELECT column_name
FROM user_tab_columns
WHERE table_name = source_table), 1)
INTO tempsql
FROM DUAL;
extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table
|| ' WHERE (' || constraint_cols || ') = (SELECT '
|| constraint_vals || ' FROM DUAL)';
EXECUTE IMMEDIATE extractsql
INTO valuelist;
-- This prints out the insert statement for the root row
DBMS_OUTPUT.put_line(basesql || valuelist || ');');
-- Now we construct the constraint_vals parameter for subsequent calls:
SELECT makeparamlist(CURSOR( SELECT column_name
FROM user_cons_columns ucc
, user_constraints uc
WHERE uc.table_name = source_table
AND ucc.constraint_name = uc.constraint_name
ORDER BY position)
, 1)
INTO tempsql
FROM DUAL;
extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table
|| ' WHERE ' || constraint_cols || ' = ' || constraint_vals;
EXECUTE IMMEDIATE extractsql
INTO childconstraint_vals;
childconstraint_vals := childconstraint_vals;
-- Now iterate over the dependent tables for this table
-- Cursor on this statement:
-- SELECT uc.table_name child_table, uc.constraint_name fk_name
-- FROM user_constraints uc
-- , user_constraints ucp
-- WHERE ucp.table_name = source_table
-- AND uc.r_constraint_name = ucp.constraint_name;
-- For each table in that statement, find the foreign key
-- columns that correspond to the rows
-- in the parent table
-- SELECT column_name
-- FROM user_cons_columns
-- WHERE constraint_name = fk_name
--ORDER BY POSITION;
-- Pass that columns into makeparamlist above to create
-- the constraint_cols argument of the call below:
-- makeinserts(child_table, ChildConstraint_cols, childconstrain_vals);
END;
END;
END data_extractor;