2009-04-08 17 views
75

मुझे थोड़ी देर की तलाश है लेकिन मुझे मेरी समस्या का आसान समाधान नहीं मिल रहा है। मैं एक तालिका में एक रिकॉर्ड डुप्लिकेट करना चाहता हूं, लेकिन निश्चित रूप से, अद्वितीय प्राथमिक कुंजी को अद्यतन करने की आवश्यकता है।एक ही MySQL तालिका में डुप्लिकेट/कॉपी रिकॉर्ड

INSERT INTO invoices 
    SELECT * FROM invoices AS iv WHERE iv.ID=XXXXX 
    ON DUPLICATE KEY UPDATE ID = (SELECT MAX(ID)+1 FROM invoices) 

समस्या यह है कि यह सिर्फ पंक्ति के ID बदल जाता पंक्ति को कॉपी करने की बजाय है:

मैं इस प्रश्न हैं। क्या कोई जनता है कि यह कैसे ठीक किया जाता है ?

// संपादित करें: मैं सभी फ़ील्ड नाम टाइप किए बिना ऐसा करना चाहता हूं क्योंकि फ़ील्ड नाम समय के साथ बदल सकते हैं।

उत्तर

115

जिस तरह से मैं आमतौर पर इसके बारे में जाता हूं वह एक अस्थायी तालिका का उपयोग कर रहा है। यह शायद कम्प्यूटेशनल रूप से कुशल नहीं है लेकिन यह ठीक काम करता प्रतीत होता है! यहां मैं रिकार्ड 99 को पूरी तरह से डुप्लिकेट कर रहा हूं, रिकॉर्ड 100 बना रहा हूं।

CREATE TEMPORARY TABLE tmp SELECT * FROM invoices WHERE id = 99; 

UPDATE tmp SET id=100 WHERE id = 99; 

INSERT INTO invoices SELECT * FROM tmp WHERE id = 100; 

आशा है कि आपके लिए ठीक काम करता है!

+0

मुझे यह पसंद है, चीजों पर नजर रखने के लिए मध्य में एक कदम – SeanDowney

+3

यदि आप एक रिकॉर्ड की प्रतिलिपि बना रहे हैं तो आप दोनों अपडेट और डालने में कहां छोड़ सकते हैं। फिर आप MySQL कंसोल में दो बार दबा सकते हैं जो इतिहास में अंतिम ऑपरेशन के आगे लाएगा, अंत में सुविधाजनक अपडेट में आईडी को बदलें, एंटर दबाएं, दबाएं, कुछ भी बदले बिना फिर से एंटर दबाएं, फिर दोहराना कई प्रतियों के लिए प्रक्रिया। काफी तेज। –

+0

बहुत उपयोगी धन्यवाद! – Elankeeran

11

आप निश्चित रूप से पता है कि नकली चाबी ट्रिगर किया जाएगा, इस प्रकार आप मैक्स (ID) +1 पहले से चुन सकते हैं:

INSERT INTO invoices SELECT MAX(ID)+1, ... other fields ... FROM invoices AS iv WHERE iv.ID=XXXXX 
+1

हाँ, लेकिन मैं अन्य सभी फ़ील्ड टाइप नहीं करना चाहता हूं (वहां कम या कम 20 हैं, और वे समय के साथ बदल सकते हैं)। मैं हर बार tablestructre परिवर्तन कोड को बदलना नहीं चाहता। – Digits

+0

आपको करना होगा। आप बेहतर एक स्क्रिप्ट बनाते हैं जो SQL कथन को फ़ील्ड की सूची से उत्पन्न करता है। यह तुच्छ है। – Ingo

+0

एकमात्र अन्य विकल्प एक डालने ट्रिगर का उपयोग करना है (यदि mysql इसका समर्थन करता है)। – Ingo

1

मैं भी इस आवश्यकता थी; मेरा समाधान एसक्यूएलवाईओजी (फ्री संस्करण) का उपयोग एसक्यूएल के रूप में वांछित रिकॉर्ड निर्यात करने के लिए किया गया था (एक डालने बनाता है)।

मैंने आईडी को हटाने के लिए इसे संपादित किया है क्योंकि इसे स्वत: जेनरेट करने की आवश्यकता है और उसके बाद इसे निष्पादित करने के लिए SQLYog में सम्मिलित किया गया है। यह दर्द रहित था। मुझे लगता है कि अन्य MySQL GUI भी यह कर सकते हैं।

यह मुझे एक रिकॉर्ड प्रदान करता है जिसे मैं लाइव सिस्टम पर परीक्षण उद्देश्यों के लिए उपयोग कर सकता हूं।

अब मेरे पास इस पुन: उपयोग के लिए भी सम्मिलित है, क्योंकि तालिका प्रतिदिन फिर से लिखी जाती है।

75

एलेक्स के उत्तर को बहु-ग्राहक वातावरण में कुछ देखभाल (जैसे लॉकिंग या लेनदेन) की आवश्यकता है।

मानते हैं कि AUTO ID फ़ील्ड तालिका में पहला (सामान्य मामला) है, हम अंतर्निहित लेनदेन का उपयोग कर सकते हैं।

 
    CREATE TEMPORARY TABLE tmp SELECT * from invoices WHERE ...; 
    ALTER TABLE tmp drop ID; # drop autoincrement field 
    # UPDATE tmp SET ...; # just needed to change other unique keys 
    INSERT INTO invoices SELECT 0,tmp.* FROM tmp; 
    DROP TABLE tmp; 

MySQL डॉक्स से:

का उपयोग AUTO_INCREMENT: आप स्पष्ट रूप से शून्य या 0 स्तंभ के लिए अनुक्रम संख्या उत्पन्न करने के लिए प्रदान कर सकते हैं।

+3

यह मेरे लिए वास्तव में उपयोगी था, धन्यवाद। – rotanimod

+0

बिल्कुल वही जो मैं चाहता था, धन्यवाद! – Yos

+0

यह मेरे लिए 0 की आईडी के साथ रिकॉर्ड डालता है, भले ही मेरे पास AUTO_INCREMENT फ़ील्ड है।इसे शून्य करने के लिए बदलना, इसलिए मेरा सुझाव है कि आप कोड को 0 के बदले नल का उपयोग करने के लिए बदलें। मैं MySQL 5.5.35 (उबंटू) पर हूं। –

2

मैं एक ऐसी ही समस्या होती है और यह है whant मैं

insert into Preguntas (`EncuestaID`, `Tipo` , `Seccion` , `RespuestaID` , `Texto`) select '23', `Tipo`, `Seccion`, `RespuestaID`, `Texto` from Preguntas where `EncuestaID`= 18 

गया Preguntas कर रहा हूँ:

CREATE TABLE IF NOT EXISTS `Preguntas` (
    `ID` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `EncuestaID` int(11) DEFAULT NULL, 
    `Tipo` char(5) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `Seccion` int(11) DEFAULT NULL, 
    `RespuestaID` bigint(11) DEFAULT NULL, 
    `Texto` text COLLATE utf8_unicode_ci , 
    PRIMARY KEY (`ID`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=522 ; 

तो, ID स्वचालित रूप से वृद्धि की जाती है और यह भी मैं उपयोग कर रहा हूँ `EncuestaID

+0

क्षमा करें, मुझे अभी एहसास हुआ कि आप कॉलम नाम का उपयोग नहीं करना चाहते हैं, इसलिए यह –

10

के लिए एक निश्चित मान ('23') आपका दृष्टिकोण अच्छा है लेकिन समस्या यह है कि आप फ़ील्ड नाम को बजाय" * "का उपयोग करते हैं रों।यदि आप सभी कॉलम नामों को प्राथमिक कुंजी से बाहर रखते हैं तो आपकी स्क्रिप्ट एक या कई रिकॉर्ड पर आकर्षण की तरह काम करेगी।

INSERT INTO invoices (iv.field_name, iv.field_name,iv.field_name ) SELECT iv.field_name, iv.field_name,iv.field_name FROM invoices AS iv WHERE iv.ID=XXXXX

0

मामूली बदलाव, मुख्य अंतर यह है प्राथमिक कुंजी क्षेत्र ("VARNAME") शून्य पर है, जो एक चेतावनी का उत्पादन लेकिन काम करता है स्थापित करने के लिए किया जा रहा है। प्राथमिक कुंजी को शून्य पर सेट करके, अंतिम विवरण में रिकॉर्ड डालने पर ऑटो-वृद्धि कार्य करता है।

इस कोड को भी पिछले प्रयास को साफ, और समस्याओं के बिना एक से अधिक बार चलाया जा सकता है:

DELETE FROM `tbl` WHERE varname="primary key value for new record"; 
DROP TABLE tmp; 
CREATE TEMPORARY TABLE tmp SELECT * FROM `tbl` WHERE varname="primary key value for old record"; 
UPDATE tmp SET varname=NULL; 
INSERT INTO `tbl` SELECT * FROM tmp; 
1

मैं सिर्फ यह उचित बनाने के लिए एलेक्स के महान जवाब विस्तार करने के लिए करता है, तो आप एक पूरे डुप्लिकेट करना चाहते हैं के लिए हो चाहता था अभिलेखों का सेट:

SET @x=7; 
CREATE TEMPORARY TABLE tmp SELECT * FROM invoices; 
UPDATE tmp SET [email protected]; 
INSERT INTO invoices SELECT * FROM tmp; 

मुझे बस ऐसा करना पड़ा और एलेक्स के जवाब को एकदम सही कूदने का बिंदु मिला! बेशक, आपको तालिका में उच्चतम पंक्ति संख्या में @x सेट करना होगा (मुझे यकीन है कि आप इसे एक क्वेरी के साथ पकड़ सकते हैं)। यह केवल इस विशिष्ट स्थिति में उपयोगी है, इसलिए जब आप सभी पंक्तियों को डुप्लिकेट नहीं करना चाहते हैं तो इसका उपयोग सावधान रहें। आवश्यकतानुसार गणित समायोजित करें।

3

मुझे एक देर का जवाब पता है, लेकिन यह अभी भी एक आम सवाल है, मैं एक और जवाब जोड़ना चाहता हूं कि यह केवल मेरे लिए काम करता है, केवल एक पंक्ति insert into कथन का उपयोग करके, और मुझे लगता है कि यह सीधे आगे है, बिना किसी बनाये नई तालिका (क्योंकि यह CREATE TEMPORARY TABLE अनुमति के साथ एक मुद्दा हो सकता है):

INSERT INTO invoices (col_1, col_2, col_3, ... etc) 
    SELECT 
    t.col_1, 
    t.col_2, 
    t.col_3, 
    ... 
    t.updated_date, 
    FROM invoices t; 

समाधान AUTO_INCREMENT आईडी स्तंभ के लिए काम कर रहा है, अन्यथा, आप ID स्तंभ के रूप में अच्छी तरह से बयान करने के लिए जोड़ सकते हैं:

INSERT INTO invoices (ID, col_1, col_2, col_3, ... etc) 
    SELECT 
    MAX(ID)+1, 
    t.col_1, 
    t.col_2, 
    t.col_3, 
    ... etc , 
    FROM invoices t; 

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

+1

लागू नहीं होता है यह कॉपी करते समय कुछ फ़ील्ड को संशोधित करने के लिए भी एक अच्छा आधार है। मैंने अभी तक wp_options का चयन किया है, 'theme_pods_twopress', विकल्प_value, wp_options से autoload जहां विकल्प_नाम = 'theme_mods_onepress'; 'प्रविष्टि को बढ़ाने के दौरान प्रतिलिपि बनाने के लिए' (ऊपर से AUTO_INCREMENT' 'NULL' चाल) और' option_name' फ़ील्ड भी। –

+0

हाँ .. मेरे लिए अच्छा विचार। धन्यवाद!! –

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