2011-08-19 20 views
8

में कुछ पंक्तियों को कुशलता से डुप्लिकेट करें मेरे पास PostgreSQL 9 डेटाबेस है जो प्राथमिक कुंजी के रूप में स्वत: वृद्धिशील पूर्णांक का उपयोग करता है। मैं एक पंक्ति में कुछ पंक्तियों को डुप्लिकेट करना चाहता हूं (कुछ फ़िल्टर मानदंडों के आधार पर), एक या दो मानों को बदलते समय, यानी आईडी (जो स्वत: जेनरेट किया गया है) और संभवतः एक और कॉलम को छोड़कर सभी कॉलम मानों की प्रतिलिपि बनाएँ।PostgreSQL तालिका

हालांकि, मैं भी पुराने से नए आईडी में मैपिंग प्राप्त करना चाहता हूं। क्या ऐसा करने का कोई बेहतर तरीका है तो पंक्तियों के लिए पहली बार प्रतिलिपि बनाने के लिए पूछताछ करें और फिर एक बार में नई पंक्तियां डालें?

अनिवार्य रूप से मैं इस तरह कुछ करना चाहता हूँ:

INSERT INTO my_table (col1, col2, col3) 
SELECT col1, 'new col2 value', col3 
FROM my_table old 
WHERE old.some_criteria = 'something' 
RETURNING old.id, id; 

हालांकि, इस ERROR: missing FROM-clause entry for table "old" साथ विफल रहता है और मैं देख सकता हूँ क्यों: Postgres का चयन पहले कर रही होगी और फिर इसे डालने और RETURNING खंड केवल पहुँच गया है नई डाली गई पंक्ति के लिए।

+0

आप विचार है करने के लिए कैसे आपकी क्वेरी करने के लिए डब्ल्यू/सभी विशेषताओं नामकरण ओ मैं प्रतिलिपि बनाना चाहते हो रहे हैं? मेरे पास बहुत बड़ी मेज है (बहुत सारे गुणों के साथ) और उन सभी को टाइप करना और भूलना एक दर्द नहीं है ... –

+0

एक ही चीज़ के बारे में दो प्रश्न क्यों? http://stackoverflow.com/questions/29256888/insert-into-from-select-returning-id-mappings – murison

उत्तर

8

रिटर्निंग केवल अंतिम, सम्मिलित पंक्ति में कॉलम का संदर्भ दे सकता है। आप "OLD" आईडी को इस तरह से संदर्भित नहीं कर सकते हैं जब तक कि तालिका में कोई कॉलम न हो और उसे नई आईडी न हो।

INSERT INTO my_table (col1, col2, col3) 
    SELECT col1, 'new col2 value', col3 
    FROM my_table AS old 
    WHERE old.some_criteria = 'something' 
RETURNING *; 

यह आप इच्छित व्यवहार नहीं मिलेगा, लेकिन बेहतर कैसे लौटने डिज़ाइन किया गया है उदाहरण देकर स्पष्ट करना चाहिए:

इस जो काम करना चाहिए और सभी संभव मूल्यों है कि आप लौटने के माध्यम से प्राप्त कर सकते हैं दिखाएगा चलाने की कोशिश करें काम करने के लिए।

+0

धन्यवाद - लेकिन मेरा मानना ​​है कि मैं पहले ही समझता हूं कि रिटर्निंग कैसे काम करती है। – EMP

0

'पुराना' एक आरक्षित शब्द है, जो नियम पुनर्लेखन प्रणाली द्वारा उपयोग किया जाता है। [मुझे लगता है कि यह क्वेरी खंड एक नियम का हिस्सा नहीं है; उस स्थिति में आप अलग-अलग प्रश्न का उच्चारण करेंगे]

+0

हां, आप सही हैं - मैंने पोस्ट के लिए क्वेरी तैयार की है क्योंकि वास्तविक एक अधिक जटिल है। – EMP

2

अच्छा! मैं इस कोड का परीक्षण, लेकिन मैं (WHERE some_criteria = 'something')

में (FROM my_table) इस (FROM my_table AS old) और इस (WHERE old.some_criteria = 'something') बदलने के इस अंतिम कोड है कि मैं का उपयोग कर रहा है

INSERT INTO my_table (col1, col2, col3) 
    SELECT col1, 'new col2 value', col3 
    FROM my_table AS old 
    WHERE some_criteria = 'something' 
RETURNING *; 

धन्यवाद!

0
DROP TABLE IF EXISTS tmptable; 
CREATE TEMPORARY TABLE tmptable as SELECT * FROM products WHERE id = 100; 
UPDATE tmptable SET id = sbq.id from (select max(id)+1 as id from products) as sbq; 
INSERT INTO products (SELECT * FROM tmptable); 
DROP TABLE IF EXISTS tmptable; 

एक और क्षेत्र

UPDATE tmptable SET another = 'data'; 
+0

'अद्यतन लक्षण एसईटी आईडी =' केवल तभी काम करता है जब आईडी एक पूर्णांक है, न कि यह धारावाहिक है – DarkMukke

2

इस डेटा-modifiying सीटीई की मदद से किया जा सकता है संशोधित करने के लिए डालने से पहले एक और अद्यतन जोड़ने (Postgres 9.1+):

WITH sel AS (
    SELECT id, col1, col3 
     , row_number() OVER (ORDER BY id) AS rn -- order any way you like 
    FROM my_table 
    WHERE some_criteria = 'something' 
    ORDER BY id -- match order or row_number() 
    ) 
, ins AS (
    INSERT INTO my_table (col1, col2, col3) 
    SELECT col1, 'new col2 value', col3 
    FROM sel 
    ORDER BY id -- redundant to be sure 
    RETURNING id 
) 
SELECT s.id AS old_id, i.id AS new_id 
FROM (SELECT id, row_number() OVER (ORDER BY id) AS rn FROM ins) i 
JOIN sel s USING (rn); 

SQL Fiddle प्रदर्शन।

यह अनियंत्रित कार्यान्वयन विवरण पर निर्भर करता है कि SELECT से पंक्तियों को प्रदान किए गए क्रम में डाला गया है (और प्रदान किए गए क्रम में लौटाया गया है)। यह पोस्टग्रेज़ के सभी मौजूदा संस्करणों में काम करता है और तोड़ने वाला नहीं है।संबंधित:

विंडो कार्यों RETURNING खंड में अनुमति नहीं है, इसलिए मैं एक और सबक्वेरी में row_number() लागू होते हैं। इस संबंधी बाद में जवाब में

अधिक स्पष्टीकरण: