কিভাবে পোস্টগ্রিসে ক্রম পুনরায় সেট করবেন এবং নতুন ডেটা দিয়ে আইডি কলামটি পূরণ করবেন?


126

আমার মিলিয়ন মিলিয়ন সারি সহ একটি টেবিল রয়েছে। আমার ক্রমটি পুনরায় সেট করতে হবে এবং নতুন মানগুলি (1, 2, 3, 4 ... ইত্যাদি ...) সহ আইডি কলামটি পুনরায় নিয়োগ করা দরকার। এটি করার কোনও সহজ উপায়?


6
আসল প্রশ্ন: পৃথিবীতে আপনি এটি করতে চান কেন? সম্ভবত আইডিটি প্রাথমিক কী, সুতরাং প্রাথমিক কীটি পরিবর্তন করে কোনও লাভ নেই। একটি প্রাথমিক কী একটি অর্থহীন (আপনার ক্ষেত্রে কৃত্রিম) মান। "নামকরণ" এটি কোনও সম্পর্কিত ডেটাবেজে কোনও বুদ্ধিমান উদ্দেশ্য পরিবেশন করে না।
a_horse_with_no_name

2
প্রথমদিকে আমার কাছে স্থানীয়ভাবে অ্যাপটি চলছিল, তারপরে আমি ডেটাটি প্রোডাকশনে অনুলিপি করেছিলাম। তবে idএর সূচনাটি 1 থেকে শুরু হয়নি। সুতরাং আদেশটি নিম্নরূপে চালু হয়েছিল: 150, 151 ..., 300, 1, 2 ... এবং এটি নকল আইডির ত্রুটি ঘটবে শেষ পর্যন্ত আমি মনে করি, যদি আমি পুনরায় নাম্বার না করে থাকি এইডস অতিরিক্তভাবে, অর্ডার দ্বারা idঅর্ডার করা আদেশের চেয়ে সাধারণত ভাল created_at। এবং আমার জন্য কি কাজ করেছে তা এখানে ।
এক্স-ইউরি

এটি করার মূল বিষয়টি যাতে আপনি একটি ডাটাবেসে প্রাইমারি কীটির জন্য বিগিন্টের পরিবর্তে নিয়মিত ইন্ট ব্যবহার করা চালিয়ে যেতে পারেন যা ক্রমবর্ধমান কীটি বাড়িয়ে দেয় তবে ক্রমাগতভাবে নতুন ডেটা পাওয়া যায়। আপনি দ্রুত স্বাক্ষরিত পূর্ণসংখ্যার সীমাতে চলে যাবেন এবং যদি বিদ্যমান আইডি ধরে রাখা গুরুত্বপূর্ণ না হয় তবে এই প্রক্রিয়াটি আপনাকে পরিচালনযোগ্য আইডি নম্বরগুলিতে ফিরিয়ে আনবে।
বেন উইলসন

এর জন্য আরেকটি ব্যবহার হচ্ছে পরীক্ষা করা। প্রতিটি পরীক্ষা শুরুর আগে আপনি কোনও টেবিলকে জ্ঞাত রাজ্যে পুনরায় সেট করতে চান এবং এর জন্য পুনরায় সেট করার জন্য আইডির প্রয়োজন হয়।
সাফা আলাই

উত্তর:


203

আপনি যদি আইডির ক্রম ধরে রাখতে চান না, তবে আপনি পারেন

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

আমি সন্দেহ করি যে পুরো টেবিলটি পুনরায় তৈরি না করে আপনার পছন্দের ক্রমে এটি করার একটি সহজ উপায় আছে।


4
তা কি হওয়া উচিত নয় ALTER SEQUENCE seq RESTART WITH 1;?
লার্স হগসেট

5
এটি ডুপ্লিকেট আইডির কারণ হতে পারে। এটি প্রতিরোধ করতে, আপনি প্রথমে খুব উচ্চ মানগুলিতে সেট করতে পারেন: আপডিকেট সেট সেট আইডকোলোম = 1000000 + নেক্সটাল ('সিক'); তারপরে উপরের স্ক্রিপ্টটি চালান।
তাহাঘ

5
SELECT setval('seq', 1, FALSE)একই কাজ করা উচিত (এখানে, তৃতীয় যুক্তি, মিথ্যা, nextval
যাদুটি

@ ভ্যাসিলেনডন্টচেভ, একেবারে।
মাইকেল ক্রেলিন - হ্যাকার

55

PostgreSQL 8.4 বা আরও নতুন এর সাথে WITH 1আর নির্দিষ্ট করার দরকার নেই। দ্বারা শুরু করা CREATE SEQUENCEবা সর্বশেষ সেট দ্বারা রেকর্ড করা শুরুর মান ALTER SEQUENCE START WITHব্যবহার করা হবে (সম্ভবত এটি সম্ভবত 1 হবে)।

ক্রমটি পুনরায় সেট করুন:

ALTER SEQUENCE seq RESTART;

তারপরে সারণির আইডি কলাম আপডেট করুন:

UPDATE foo SET id = DEFAULT;

উত্স: পোস্টগ্রিএসকিউএল ডক্স


3
এটি সর্বোত্তম উত্তরের মতো বলে মনে হচ্ছে কারণ এটি অনুক্রমের প্রারম্ভিক মান সম্পর্কে অনুমান করা এড়ানো যায়।
ভেড়াডগ

আমার ক্ষেত্রেও সেরা উত্তর। আমি এই উত্তর মেশা এই এক তাই আমি দ্বারা 'SeQ' পরিবর্তিত, যা ALTER SEQUENCE কমান্ড ব্যাখ্যা করে ... mytable_id_seq যেখানে 'mytable' আমার টেবিল নাম এবং হল 'id' আমার সিরিয়াল কলামের নাম
Javi

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
এখানেও একই সমস্যা। আপনার সমাধান পোস্টগ্র্রেএসকিউএল 8.3.10 এর জন্যও কাজ করে।
পেকএনপি

17

ক্রমটি পুনরায় সেট করার জন্য কেবলমাত্র ALTER SEQUENCE এবং SELECT সেটওয়ালের যথাযথ ব্যবহার সরলকরণস্পষ্ট করার জন্য:

ALTER SEQUENCE sequence_name RESTART WITH 1;

সমতুল্য

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

উভয় বিবৃতি ক্রম পুনরায় সেট করতে ব্যবহার করা যেতে পারে এবং আপনি এখানে বর্ণিত হিসাবে পরের ('সিকোয়েন্স_নাম') দ্বারা পরবর্তী মান পেতে পারেন :

nextval('sequence_name')

ধন্যবাদ আলী। আমি কেবলমাত্র খেয়াল করেছি যে সেটাল ফাংশনটি দিয়ে 3rd র্থ প্যারামিটারটিকে মিথ্যা হিসাবে সেট করা গুরুত্বপূর্ণ
ডেভিড হায়োগো

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

এফওয়াইআই: আপনার যদি আইডির একটি পরিসরের মধ্যে একটি নতুন সূচনা মূল্য নির্দিষ্ট করতে হয় (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

এখানে অন্যান্য উত্তরের দ্বারা অনুপ্রাণিত হয়ে, আমি একটি ক্রম মাইগ্রেশন করার জন্য একটি এসকিউএল ফাংশন তৈরি করেছি। ফাংশনটি একটি প্রাথমিক কী সিকোয়েন্সকে কোনও নতুন মান (> = 1) দ্বারা বিদ্যমান সিকোয়েন্সের ব্যাপ্তির ভিতরে বা বাইরে শুরু করে একটি নতুন সাবলীল সিকোয়েন্সে নিয়ে যায়।

আমি এখানে ব্যাখ্যা করছি যে আমি কীভাবে একই স্কিমার সাথে দুটি ডাটাবেসের স্থানান্তরিত করতে কিন্তু এই একই ফাংশনটি একটি ডাটাবেসে বিভিন্ন মান ব্যবহার করেছি।

প্রথমত, ফাংশন (যা উত্পন্ন এসকিউএল কমান্ডগুলি প্রিন্ট করে যাতে প্রকৃতপক্ষে কী ঘটছে তা পরিষ্কার হয়ে যায়):

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 দিয়ে শুরু হয় This এটি যেখানে কেস পরিচালনা করে 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

এমনকি স্বতঃবৃদ্ধি কলামও পিকে নয় (এই উদাহরণে এটি সেক - ওরফে সিকোয়েন্স বলা হয়) আপনি ট্রিগার দিয়ে এটি অর্জন করতে পারেন:

টেবিলটি ড্রপ করুন যদি অস্তিত্ব থাকে তবে ডিওপস_গাইড ক্যাসকেড করুন;

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

আপনি যদি পিজিএডমিন 3 ব্যবহার করছেন, 'সিকোয়েন্সগুলি প্রসারিত করুন', একটি সিকোয়েন্সে ডান ক্লিক করুন, 'প্রোপার্টিস' এ যান এবং 'সংজ্ঞা' ট্যাবে 'বর্তমান মান' পরিবর্তন করে আপনি যে মানটি চান তা পরিবর্তন করুন। কোনও প্রশ্নের প্রয়োজন নেই।


3
আপনি কোন সরঞ্জামটি ব্যবহার করছেন তা যদি আপনি কমপক্ষে আমাদের না জানান তবে আপনার উত্তরটির কোনও মূল্য নেই।
11101101b

3
এটিই সহজতম উপায়, স্পষ্টতই আমি মনে করি তিনি
পিজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.