स्वत: वृद्धि प्राथमिक कुंजी को पुन: व्यवस्थित / रीसेट करें


127

मेरे पास एक ऑटो वृद्धि प्राथमिक कुंजी के साथ एक MySQL तालिका है। मैंने तालिका के बीच में कुछ पंक्तियों को हटा दिया। अब मेरे पास, उदाहरण के लिए, आईडी कॉलम में ऐसा कुछ है: 12, 13, 14, 19, 20। मैंने 15, 16, 17 और 18 पंक्तियों को हटा दिया है।

मैं प्राथमिक कुंजी को पुन: असाइन / रीसेट / फिर से चालू करना चाहता हूं ताकि मेरे पास निरंतरता हो, अर्थात 19 को 15, 20 को 16 और इसी तरह से बनाएं।

मैं यह कैसे कर सकता हूं?

जवाबों:


95

आप प्राथमिक कुंजी कॉलम को छोड़ सकते हैं और इसे फिर से बना सकते हैं। तब सभी आईडी क्रम में पुन: असाइन किए जाने चाहिए।

हालाँकि यह ज्यादातर स्थितियों में एक बुरा विचार है। यदि आपके पास अन्य तालिकाएं हैं जिनके पास इस तालिका में विदेशी कुंजी हैं तो यह निश्चित रूप से काम नहीं करेगा।


मेरे पास अन्य टेबल हैं जो इस तालिका में एक विदेशी कुंजी रखती हैं, लेकिन मैं अभी प्रोजेक्ट शुरू कर रहा हूं इसलिए यह मेरे लिए ठीक है .. धन्यवाद!
जोनाथन

65
यदि आप कोशिश करते हैं और यह स्वीकार करना शुरू करते हैं कि आपकी आईडी हमेशा अनुक्रमिक नहीं होगी, तो यह सबसे अच्छा दीर्घकालिक हो सकता है, अन्यथा जब आप बड़ी परियोजनाओं पर काम करना शुरू करते हैं तो यह वास्तव में पागल हो जाएगा!
सियारन मैकनीकलर

8
ALTER TABLE your_table AUTO_INCREMENT = 1
सिनैक

356

भले ही यह सवाल काफी पुराना लग रहा हो, लेकिन किसी ऐसे व्यक्ति के लिए एक उत्तर पोस्ट करेंगे जो खोज में यहां तक ​​पहुंचता है।

SET @count = 0;
UPDATE `users` SET `users`.`id` = @count:= @count + 1;

यदि स्तंभ अन्य तालिकाओं में एक विदेशी कुंजी के रूप में उपयोग किया जाता है, तो सुनिश्चित करें कि आप उन तालिकाओं में विदेशी कुंजी संबंध के लिए ON UPDATE CASCADEडिफ़ॉल्ट के बजाय उपयोग करते हैं ON UPDATE NO ACTION

इसके अलावा, AUTO_INCREMENTगणना को रीसेट करने के लिए , आप तुरंत निम्नलिखित विवरण जारी कर सकते हैं।

ALTER TABLE `users` AUTO_INCREMENT = 1;

MySQLs के लिए यह मान रीसेट करेगा MAX(id) + 1


विदेशी कुंजियों के साथ यह मेरी मेज के लिए एक बहुत अच्छा समाधान है जहां बहुत सारे कबाड़ डाले जाते हैं और हटाए जाते हैं और मैं सूचकांक स्थान को बचाना चाहता हूं।
मुकुंद

1
mySQL Doc इसके विरुद्ध सलाह देता है: "सामान्य नियम के रूप में, SET कथनों के अलावा, आपको किसी उपयोगकर्ता चर का मान कभी निर्दिष्ट नहीं करना चाहिए और उसी कथन के भीतर मान पढ़ना चाहिए। उदाहरण के लिए, एक चर को बढ़ाने के लिए, यह ठीक है: SET @a = @a + 1; अन्य बयानों के लिए, जैसे कि SELECT, से आपको अपेक्षित परिणाम मिल सकते हैं, लेकिन इसकी गारंटी नहीं है। निम्नलिखित कथन में, आप सोच सकते हैं कि MySQL पहले @a का मूल्यांकन करेगा और फिर असाइनमेंट करेगा। दूसरा: SELECT @a, @a: = @ a + 1, ...; हालांकि, उपयोगकर्ता चर शामिल अभिव्यक्तियों के लिए मूल्यांकन का क्रम अपरिभाषित है। "
ReverseEMF

3
@ReverseEMF: नहीं। असाइनमेंट का क्रम MySQL अभिव्यक्तियों में तय किया गया है। आपने जो उद्धृत किया है, उससे MySQL डॉक्यूमेंटेशन वेरिएबल के कई स्वतंत्र उपयोग के खिलाफ सलाह देता है। उपरोक्त मामले में, अभिव्यक्ति का मूल्यांकन एक पूर्व असाइनमेंट अभिव्यक्ति के कारण पूर्व-निर्धारित क्रम में होने के लिए बाध्य है `` यूजर्स .id` = @count: = @count + 1`। प्रलेखन से: "दाहिने हाथ की ओर का मूल्य एक शाब्दिक मूल्य हो सकता है, एक अन्य चर मान का भंडारण, या कोई कानूनी अभिव्यक्ति जो स्केलर मूल्य देता है"
अंशुल

1
क्या यह बहुत महंगा बयान है? यह बहु गीगाबाइट तालिका में कैसा प्रदर्शन करेगा? मुझे अपने ibdata1 (लंबे लेनदेन) को उड़ाने और बहुत लंबे समय तक तालिका को अवरुद्ध करने का डर है।
स्टीफन

1
@Stefan विदेशी कुंजियों के साथ एक मेज पर (5MB) जो डेटा के 2GB के साथ एक और संदर्भ देता है, इस स्क्रिप्ट ने पांच मिनट से अधिक नहीं लिया। सिस्टम में ssd है, इसलिए मुझे लगता है कि इसने बहुत मदद की। FK पर अद्यतन CASCADE था
fernandezr

60

मेरी उपयोगकर्ता तालिका की आईडी को रीसेट करने के लिए, मैं निम्नलिखित SQL क्वेरी का उपयोग करता हूं। यह ऊपर कहा गया है कि इससे आपके किसी भी अन्य तालिकाओं के साथ संबंध खराब हो सकते हैं।

ALTER TABLE `users` DROP `id`;
ALTER TABLE `users` AUTO_INCREMENT = 1;
ALTER TABLE `users` ADD `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;

584k पंक्तियों के साथ एक MyISAM टेबल पर, लगभग 7.3 सेकंड लग गए।
user1278519

3
अगर मेरे पास 100 वोट होते तो मैं हर समय इसे वोट देता क्योंकि यह मेरे जैसे
दोपहर के

1
दूसरी पंक्ति आवश्यक नहीं है या क्या मैं गलत हूं? यह 1 से अपने आप शुरू होता है ,,,, के लिए InnoDB यह मेरे लिए किया था हालांकि
Thielicious

दूसरी पंक्ति आवश्यक नहीं।
कावईएक्स

1
@ JorgeAugustoMorêradeMoura रिकॉर्ड्स का क्रम नहीं बदला जाएगा
रयान

31

आप बस इस क्वेरी का उपयोग कर सकते हैं

alter table abc auto_increment = 1;

2
यह इस मामले में काम नहीं करेगा। आईएसएएम तालिकाओं के लिए, यह अधिकतम (आईडी) + के लिए ऑटोइनक मान निर्धारित करेगा। इनोबीडी के लिए यह कुछ भी नहीं करेगा। AutoIncrement को बदलने के लिए बदलने की मेज डॉक्स देखें dev.mysql.com/doc/refman/5.0/en/alter-table.html
lreeder

3
@ निर्दोष के लिए 5.6 के बाद के व्यवहार से पैदा करने वाला माइसम के समान है
अंशुल

यदि आपके पास अन्य तालिकाएँ हैं जिनके पास इस तालिका की विदेशी कुंजियाँ हैं, तो क्या यह उन्हें तोड़ देगा?
काइल वासेला

15
SET  @num := 0;

UPDATE your_table SET id = @num := (@num+1);

ALTER TABLE your_table AUTO_INCREMENT =1;

मुझे लगता है कि यह ऐसा करेगा


12

या, PhpMyAdmin से, "AutoIncrement" ध्वज को हटाएं, सहेजें, इसे फिर से सेट करें और सहेजें। इसके बाद इसे फिर से सहेजें।


क्षमा करें, मैं वर्तमान phpmyadmin संस्करणों के साथ परीक्षण नहीं कर सकता। मेरा उत्तर काफी पुराना है ... यदि आपने मुझे अस्वीकृत कर दिया है, तो क्या आप इसमें संशोधन कर सकते हैं?
lbrutti

3
SELECT * from `user` ORDER BY `user_id`; 

SET @count = 0;

UPDATE `user`  SET `user_id` = @count:= @count + 1;

ALTER TABLE `user_id` AUTO_INCREMENT = 1;

यदि आप चाहते हैं order by


1

phpmyadmin में

नोट: यदि आप पिछली पंक्तियों को नहीं मध्य पंक्तियों को हटाते हैं तो यह काम करेगा।

goto your table-> ऑपरेशंस मेनू पर क्लिक करें-> गोटो टेबल विकल्प-> AUTO_INCREMENT को उसमें बदलें, जहाँ से आप शुरू करना चाहते हैं।

आपकी तालिका निरस्तीकरण उसी से शुरू होती है।

कोशिश करो। यहाँ छवि विवरण दर्ज करें


0

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

$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("
    SELECT `rank`, `field1`, `field2`, `field3`, `field4`
        FROM (SELECT (@rank:=@rank+1) as `rank`, `field1`, `field2`, `field3`, `field4`
            FROM (SELECT * FROM `views`) a
            CROSS JOIN (SELECT @rank:=0) b
            ORDER BY rank ASC) c
");
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
    $data[] = $row;
}
foreach ($data as $row) {
    $new_field_1 = (int)$row['rank'];
    $old_field_1 = (int)$row['field1'];
    mysql_query("UPDATE `table` SET `field_1` = $new_field_1 WHERE `field_1` = $old_field_1");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");

यहाँ मैंने एक साहचर्य सारणी बनाई, जिसे मैंने एक चुनिंदा प्रश्न के भीतर क्वेरी के साथ रैंक कॉलम पर जोड़ा था, जिसने प्रत्येक पंक्ति को 1. से शुरू होने वाला रैंक मान दिया। फिर मैंने साहचर्य सरणी के माध्यम से पुनरावृत्ति की।

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

$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("SELECT * FROM `table`");
$updated_key = 0;
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
    $data[] = $row;
}
foreach ($data as $row) {
    $updated_key = $updated_key + 1;
    mysql_query("UPDATE `table` SET `field_1` = '$updated_key' WHERE `field_1` = '$row['field_1']'");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");

0

InnoDB के लिए, ऐसा करें (यह एक तालिका से सभी रिकॉर्ड को हटा देगा, पहले एक बॅकची बनाएं))

SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS ;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION ;
SET NAMES utf8 ;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 ;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 ;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' ;
SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 ;
/* ================================================= */

drop table tablename;
CREATE TABLE `tablename` (
   table structure here!

) ENGINE=InnoDB AUTO_INCREMENT=  ai number to reset  DEFAULT CHARSET= char set here;



/* ================================================= */
SET SQL_MODE=@OLD_SQL_MODE ;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS ;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS ;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT ;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS ;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION ;
SET SQL_NOTES=@OLD_SQL_NOTES ;

0

मुझे एक ही संदेह था, लेकिन तालिका में कोई बदलाव नहीं किया जा सकता था, मैंने निर्णय लिया कि निम्नलिखित को देखकर मेरी आईडी चर @ बस में तय अधिकतम संख्या से अधिक नहीं होगी:

SET @count = 40000000;
UPDATE `users` SET `users`.`id` = @count:= @count + 1;

SET @count = 0;
UPDATE `users` SET `users`.`id` = @count:= @count + 1;

ALTER TABLE `users` AUTO_INCREMENT = 1;

समाधान लेता है, लेकिन यह सुरक्षित है और यह आवश्यक था क्योंकि मेरी तालिका में किसी अन्य तालिका में डेटा के साथ विदेशी कुंजियाँ थीं।


0

सबसे अच्छा विकल्प कॉलम को बदलना और auto_increment विशेषता को निकालना है। फिर एक और परिवर्तन बयान जारी करें और auto_increment को कॉलम पर वापस रखें। यह गिनती को वर्तमान पंक्तियों के अधिकतम + 1 पर रीसेट कर देगा और इस प्रकार विदेशी तालिका के संदर्भों को इस तालिका में वापस रख देगा, आपके डेटाबेस की अन्य तालिकाओं या उस स्तंभ के लिए किसी अन्य कुंजी उपयोग से।


0

मेरी राय एक नया कॉलम बनाने के लिए है जिसे row_order कहा जाता है। फिर उस कॉलम को फिर से चालू करें। मैं प्राथमिक कुंजी में परिवर्तनों को स्वीकार नहीं कर रहा हूँ। एक उदाहरण के रूप में, यदि ऑर्डर कॉलम बैनर_पोजिशन है, तो मैंने कुछ ऐसा किया है, यह बैनर स्थिति कॉलम को हटाने, अपडेट करने, बनाने के लिए है। इस फ़ंक्शन को कॉल करें क्रमशः उन्हें पुन: व्यवस्थित करें।

public function updatePositions(){
    $offers = Offer::select('banner_position')->orderBy('banner_position')->get();
    $offersCount = Offer::max('banner_position');
    $range = range(1, $offersCount);

    $existingBannerPositions = [];
    foreach($offers as $offer){
        $existingBannerPositions[] = $offer->banner_position;
    }
    sort($existingBannerPositions);
    foreach($existingBannerPositions as $key => $position){
        $numbersLessThanPosition = range(1,$position);
        $freshNumbersLessThanPosition = array_diff($numbersLessThanPosition, $existingBannerPositions);
        if(count($freshNumbersLessThanPosition)>0) {
            $existingBannerPositions[$key] = current($freshNumbersLessThanPosition);
            Offer::where('banner_position',$position)->update(array('banner_position'=> current($freshNumbersLessThanPosition)));
        }
    }
}

0

यह काम करता है - https://stackoverflow.com/a/5437720/10219008.....but यदि आप किसी समस्या 'त्रुटि कोड: 1265 में चलाते हैं तो' पंक्ति 1 पर कॉलम 'आईडी' के लिए डेटा काट दिया गया ... फिर चलाएं निम्नलिखित। अपडेट क्वेरी पर ध्यान न देना।

SET @count = 0;
set sql_mode = 'STRICT_ALL_TABLES';
UPDATE IGNORE web_keyword SET id = @count := (@count+1);

-2

आप साधारण कुंजी के रूप में संख्यात्मक आईडी का उपयोग करने से भी बच सकते हैं। यदि देश देशों की जानकारी रखता है, तो आप देश के कोड को प्राथमिक आईडी के रूप में उपयोग कर सकते हैं, या यदि आप उदाहरण के लिए लेख रखते हैं, तो आप पर्मलिंक का उपयोग कर सकते हैं।

तुम भी बस एक यादृच्छिक, या एक MD5 मूल्य का उपयोग कर सकते हैं। इन सभी विकल्पों के अपने फायदे हैं, विशेष रूप से आईटी सेकंड पर। संख्यात्मक आईडी गणना करना आसान है।


1
... आप इस पर क्या आधार देते हैं? हो सकता है कि बस "पूर्ण_सुमेर_इन्फो_एक्सपोर्ट.फैप? यूजरिड = 34" जैसे पृष्ठ न बनाएं? आंतरिक रूप से एक स्ट्रिंग या अन्य यादृच्छिक मूल्य को इंडेक्स / पहचानकर्ता के रूप में उपयोग करना वास्तव में एक बुरा विचार है। यह हल करता है की तुलना में अधिक समस्याएं पैदा करता है (यदि यह किसी भी समस्याओं को हल करता है)
रोब

एमडी 5 मूल्य पूरी तरह से सबसे खराब संभावना है क्योंकि यह संभव है कि दो अलग-अलग मूल्य या डेटासेट एक ही एमडी 5 मूल्य का उत्पादन करते हैं। इसलिए मैं इसे समाधान नहीं कहूंगा।
डेविड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.