पोस्टग्रेज में अनुक्रम कैसे रीसेट करें और नए डेटा के साथ आईडी कॉलम भरें?


126

मेरे पास लाखों से अधिक पंक्तियों वाली एक तालिका है। मुझे नए मूल्यों (1, 2, 3, 4 ... आदि ...) के साथ अनुक्रम और पुन: असाइन किए गए आईडी कॉलम को रीसेट करने की आवश्यकता है। क्या ऐसा करने का कोई आसान तरीका है?


6
असली सवाल: पृथ्वी पर आप ऐसा क्यों करना चाहेंगे? संभवत: आईडी प्राथमिक कुंजी है, इसलिए प्राथमिक कुंजी को बदलने में कोई लाभ नहीं है। एक प्राथमिक कुंजी एक अर्थहीन (आपके मामले में कृत्रिम) मूल्य है। "नवीनीकरण" यह एक संबंधपरक डेटाबेस में किसी भी समझदार उद्देश्य की सेवा नहीं करता है।
a_horse_with_no_name 22

2
प्रारंभ में मेरे पास स्थानीय रूप से चलने वाला ऐप था, फिर मैंने उत्पादन पर डेटा की प्रतिलिपि बनाई। लेकिन idएस 1 से शुरू नहीं हुआ था। इसलिए ऑर्डर निम्नानुसार निकला: 150, 151 ..., 300, 1, 2 ... और यह डुप्लिकेट आईडी त्रुटियों का कारण बनेगा, अंततः मुझे लगता है, अगर मैंने नहीं बदला था आईडी। इसके अतिरिक्त, ऑर्डर idआमतौर पर ऑर्डर से बेहतर है created_at। और यहाँ मेरे लिए क्या काम किया है
x-yuri

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

इसके लिए एक और उपयोग परीक्षण कर रहा है। आप प्रत्येक परीक्षण शुरू करने से पहले एक ज्ञात स्थिति में एक तालिका को रीसेट करना चाहते हैं और इसके लिए आईडी को रीसेट करने की आवश्यकता होती है।
सफा अलाई

जवाबों:


203

यदि आप आईडी के क्रम को बनाए रखना नहीं चाहते हैं, तो आप ऐसा कर सकते हैं

ALTER SEQUENCE seq RESTART WITH 1;
UPDATE t SET idcolumn=nextval('seq');

मुझे संदेह है कि पूरी मेज को फिर से बनाए बिना आपकी पसंद के क्रम में ऐसा करने का एक आसान तरीका है।


4
ऐसा नहीं होना चाहिए ALTER SEQUENCE seq RESTART WITH 1;?
लार्स हग्सथ

5
यह डुप्लिकेट आईडी का कारण हो सकता है। इसे रोकने के लिए, आप पहले सभी को बहुत उच्च मानों पर सेट कर सकते हैं: अपडेट करें सेट आईडी = 1000000 + अगला ('seq'); फिर उपरोक्त स्क्रिप्ट चलाएँ।
ताहघ

5
SELECT setval('seq', 1, FALSE)वही करना चाहिए (यहां, तीसरा तर्क, एफएएलएसई, जादू करता है, जैसा कि यह दर्शाता है कि nextval2 के बजाय 1 होना चाहिए)
वासिलन डोनचेव

@VassilenDontchev, बिल्कुल।
माइकल क्रेलिन -

55

PostgreSQL 8.4 या नए के साथ WITH 1अब और निर्दिष्ट करने की आवश्यकता नहीं है। प्रारंभ मूल्य जो द्वारा CREATE SEQUENCEया अंतिम सेट द्वारा रिकॉर्ड किया गया था, का ALTER SEQUENCE START WITHउपयोग किया जाएगा (शायद यह 1 होगा)।

अनुक्रम रीसेट करें:

ALTER SEQUENCE seq RESTART;

फिर तालिका के आईडी कॉलम को अपडेट करें:

UPDATE foo SET id = DEFAULT;

स्रोत: PostgreSQL डॉक्स


3
यह सबसे अच्छा उत्तर की तरह लगता है क्योंकि यह अनुक्रम के प्रारंभ मूल्य के बारे में धारणा बनाने से बचता है।
भेड़चाल

मेरे मामले के लिए भी सबसे अच्छा जवाब। मैं इस उत्तर को इस के साथ जोड़ देता हूं , जो ALTER SEQUENCE कमांड के बारे में बताता है ... इसलिए मैंने mytable_id_seq द्वारा 'seq' को बदल दिया, जहां 'mytable' मेरी टेबल का नाम है और 'id' मेरे सीरियल कॉलम का नाम है
Jee

42

अनुक्रम रीसेट करें:

SELECT setval('sequence_name', 0);

वर्तमान रिकॉर्ड अपडेट करना:

UPDATE foo SET id = DEFAULT;

3
अनुक्रम 0. से अधिक न्यूनतम मूल्य हो सकता है (और प्रकार द्वारा उपयोग किया जाने वाला डिफ़ॉल्ट न्यूनतम मूल्य है serialऔर CREATE SEQUENCE1 है!)
brk

18

दोनों प्रदान समाधान मेरे लिए काम नहीं किया;

> SELECT setval('seq', 0);
ERROR:  setval: value 0 is out of bounds for sequence "seq" (1..9223372036854775807)

setval('seq', 1) 2 के साथ नंबरिंग शुरू करता है, और ALTER SEQUENCE seq START 1 2 के साथ भी नंबरिंग शुरू करता है, क्योंकि seq.is_called सच है (संस्करण 9.0.4 पोस्ट करता है)

समाधान है कि मेरे लिए काम किया है:

> ALTER SEQUENCE seq RESTART WITH 1;
> UPDATE foo SET id = DEFAULT;

1
यहां भी यही समस्या। आपका समाधान PostgreSQL 8.3.10 के लिए भी काम करता है।
PeqNP

17

अनुक्रम को रीसेट करने के लिए ALTER SEQUENCE और SELECT सेवल के उचित उपयोग को सरल और स्पष्ट करने के लिए:

ALTER SEQUENCE sequence_name RESTART WITH 1;

के बराबर है

SELECT setval('sequence_name', 1, FALSE);

या तो बयान के अनुक्रम पुनर्स्थापित करने के लिए इस्तेमाल किया जा सकता है और आप nextval ( 'sequence_name') द्वारा अगले मूल्य प्राप्त कर सकते हैं के रूप में कहा गया है यहाँ भी:

nextval('sequence_name')

धन्यवाद अली। मैंने अभी देखा कि सेटलेट फंक्शन के साथ यह 3 पैरामीटर झूठा होना महत्वपूर्ण है
डेविडहोगो

14

नंबर 1 के साथ वापस शुरू करने के लिए एक अनुक्रम को रीसेट करने का सबसे अच्छा तरीका निम्नलिखित को निष्पादित करना है:

ALTER SEQUENCE <tablename>_<id>_seq RESTART WITH 1

इसलिए, उदाहरण के लिए उपयोगकर्ताओं की तालिका के लिए यह होगा:

ALTER SEQUENCE users_id_seq RESTART WITH 1

6

पंक्तियों के क्रम को बनाए रखने के लिए:

UPDATE thetable SET rowid=col_serial FROM 
(SELECT rowid, row_number() OVER ( ORDER BY lngid) AS col_serial FROM thetable ORDER BY lngid) AS t1 
WHERE thetable.rowid=t1.rowid;

4

FYI करें: यदि आपको ID की सीमा (उदाहरण के लिए 256 - 10000000) के बीच एक नया प्रारंभ निर्दिष्ट करने की आवश्यकता है:

SELECT setval('"Sequence_Name"', 
       (SELECT coalesce(MAX("ID"),255) 
           FROM "Table_Name" 
           WHERE "ID" < 10000000 and "ID" >= 256)+1
       ); 

2

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

कृपया सभी आईडी में एक निश्चित राशि जोड़ने से बचें (जैसा कि अन्य टिप्पणियों में अनुशंसित है)। यदि आपके पास इस निश्चित राशि से अधिक पंक्तियाँ हैं तो क्या होगा? अनुक्रम के अगले मूल्य को मानते हुए मौजूदा पंक्तियों के सभी आईडी से अधिक है (आप बस अंतराल को भरना चाहते हैं), मैं इसे पसंद करूंगा:

UPDATE table SET id = DEFAULT;
ALTER SEQUENCE seq RESTART;
UPDATE table SET id = DEFAULT;

1

मेरे मामले में, मैंने इसे हासिल किया:

ALTER SEQUENCE table_tabl_id_seq RESTART WITH 6;

जहां मेरी टेबल का नाम टेबल है


आपकी तालिका के नाम के साथ एक ठोस उदाहरण शामिल करने के लिए धन्यवाद। अन्य उत्तर थोड़े अस्पष्ट थे।
ब्रायली क्रिस्टोफर ऑक्ले

0

यहाँ अन्य उत्तरों से प्रेरित होकर, मैंने अनुक्रम प्रवास करने के लिए एक SQL फ़ंक्शन बनाया। फ़ंक्शन किसी प्राथमिक मान अनुक्रम को किसी भी मान (> = 1) से शुरू करके नए अनुक्रम अनुक्रम में ले जाता है जो मौजूदा अनुक्रम सीमा के अंदर या बाहर होता है।

मैं यहां समझाता हूं बताता हूं कि कैसे मैंने एक ही स्कीमा के साथ दो डेटाबेसों के प्रवास में इस फ़ंक्शन का उपयोग किया लेकिन एक डेटाबेस में अलग-अलग मान।

सबसे पहले, फ़ंक्शन (जो उत्पन्न SQL कमांड को प्रिंट करता है ताकि यह स्पष्ट हो कि वास्तव में क्या हो रहा है):

CREATE OR REPLACE FUNCTION migrate_pkey_sequence
  ( arg_table      text
  , arg_column     text
  , arg_sequence   text
  , arg_next_value bigint  -- Must be >= 1
  )
RETURNS int AS $$
DECLARE
  result int;
  curr_value bigint = arg_next_value - 1;
  update_column1 text := format
    ( 'UPDATE %I SET %I = nextval(%L) + %s'
    , arg_table
    , arg_column
    , arg_sequence
    , curr_value
    );
  alter_sequence text := format
    ( 'ALTER SEQUENCE %I RESTART WITH %s'
    , arg_sequence
    , arg_next_value
    );
  update_column2 text := format
    ( 'UPDATE %I SET %I = DEFAULT'
    , arg_table
    , arg_column
    );
  select_max_column text := format
    ( 'SELECT coalesce(max(%I), %s) + 1 AS nextval FROM %I'
    , arg_column
    , curr_value
    , arg_table
    );
BEGIN
  -- Print the SQL command before executing it.
  RAISE INFO '%', update_column1;
  EXECUTE update_column1;
  RAISE INFO '%', alter_sequence;
  EXECUTE alter_sequence;
  RAISE INFO '%', update_column2;
  EXECUTE update_column2;
  EXECUTE select_max_column INTO result;
  RETURN result;
END $$ LANGUAGE plpgsql;

फ़ंक्शन migrate_pkey_sequenceनिम्न तर्क लेता है:

  1. arg_table: तालिका का नाम (जैसे 'example' )
  2. arg_column: प्राथमिक कुंजी स्तंभ नाम (उदा 'id' )
  3. arg_sequence: अनुक्रम नाम (उदा 'example_id_seq')
  4. arg_next_value: माइग्रेशन के बाद कॉलम के लिए अगला मान

यह निम्नलिखित कार्य करता है:

  1. प्राथमिक कुंजी मानों को एक मुक्त श्रेणी में ले जाएं। मुझे लगता है कि nextval('example_id_seq')इस प्रकार है max(id)और अनुक्रम 1 के साथ शुरू होता है। यह भी मामले को संभालता है जहां arg_next_value > max(id)
  2. प्राथमिक कुंजी मान को सन्निहित सीमा से शुरू करें arg_next_value। प्रमुख मूल्यों का क्रम संरक्षित है लेकिन सीमा में छेद संरक्षित नहीं हैं।
  3. अगले मूल्य को प्रिंट करें जो अनुक्रम में अनुसरण करेगा। यदि आप किसी अन्य तालिका के स्तंभों को स्थानांतरित करना चाहते हैं और इस एक के साथ विलय करना चाहते हैं तो यह उपयोगी है।

प्रदर्शित करने के लिए, हम एक अनुक्रम और तालिका को निम्नानुसार परिभाषित करते हैं (उदाहरण के लिए psql):

# CREATE SEQUENCE example_id_seq
  START WITH 1
  INCREMENT BY 1
  NO MINVALUE
  NO MAXVALUE
  CACHE 1;
# CREATE TABLE example
  ( id bigint NOT NULL DEFAULT nextval('example_id_seq'::regclass)
  );

फिर, हम कुछ मान डालें (शुरू में, उदाहरण के लिए, 3 पर):

# ALTER SEQUENCE example_id_seq RESTART WITH 3;
# INSERT INTO example VALUES (DEFAULT), (DEFAULT), (DEFAULT);
-- id: 3, 4, 5

अंत में, हम example.id1 से शुरू करने के लिए मानों को स्थानांतरित करते हैं।

# SELECT migrate_pkey_sequence('example', 'id', 'example_id_seq', 1);
INFO:  00000: UPDATE example SET id = nextval('example_id_seq') + 0
INFO:  00000: ALTER SEQUENCE example_id_seq RESTART WITH 1
INFO:  00000: UPDATE example SET id = DEFAULT
 migrate_pkey_sequence
-----------------------
                     4
(1 row)

परिणाम:

# SELECT * FROM example;
 id
----
  1
  2
  3
(3 rows)

0

यहां तक ​​कि ऑटो-इन्क्रीमेंट कॉलम PK नहीं है (इस उदाहरण में इसे seq - aka अनुक्रम कहा जाता है) जिसे आप एक ट्रिगर के साथ प्राप्त कर सकते हैं:

DROP TABLE IF IF EXISTS devops_guide CASCADE;

SELECT 'create the "devops_guide" table'
;
   CREATE TABLE devops_guide (
      guid           UUID NOT NULL DEFAULT gen_random_uuid()
    , level          integer NULL
    , seq            integer NOT NULL DEFAULT 1
    , name           varchar (200) NOT NULL DEFAULT 'name ...'
    , description    text NULL
    , CONSTRAINT pk_devops_guide_guid PRIMARY KEY (guid)
    ) WITH (
      OIDS=FALSE
    );

-- START trg_devops_guide_set_all_seq
CREATE OR REPLACE FUNCTION fnc_devops_guide_set_all_seq()
    RETURNS TRIGGER
    AS $$
       BEGIN
         UPDATE devops_guide SET seq=col_serial FROM
         (SELECT guid, row_number() OVER ( ORDER BY seq) AS col_serial FROM devops_guide ORDER BY seq) AS tmp_devops_guide
         WHERE devops_guide.guid=tmp_devops_guide.guid;

         RETURN NEW;
       END;
    $$ LANGUAGE plpgsql;

 CREATE TRIGGER trg_devops_guide_set_all_seq
  AFTER UPDATE OR DELETE ON devops_guide
  FOR EACH ROW
  WHEN (pg_trigger_depth() < 1)
  EXECUTE PROCEDURE fnc_devops_guide_set_all_seq();

-1

यदि आप pgAdmin3 का उपयोग कर रहे हैं, तो 'अनुक्रम' का विस्तार करें, एक अनुक्रम पर राइट क्लिक करें, 'गुण' पर जाएं और 'परिभाषा' टैब में 'करंट वैल्यू' को जो भी मान चाहें, बदल दें। क्वेरी की कोई आवश्यकता नहीं है।


3
यदि आप कम से कम हमें यह नहीं बताते हैं कि आप किस उपकरण का उपयोग कर रहे हैं, तो आपका जवाब नहीं है।
11101101 बी

3
यह सबसे आसान तरीका है, जाहिर है मुझे लगता है कि वह pg admin 3 कह रहा है
MvcCmsJon
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.