Как сбросить последовательность в postgres и заполнить столбец id новыми данными? - PullRequest
90 голосов
/ 13 января 2011

У меня есть таблица с более чем миллионом строк.Мне нужно сбросить последовательность и переназначить столбец id с новыми значениями (1, 2, 3, 4 ... и т. Д.).Есть ли простой способ сделать это?

Ответы [ 13 ]

0 голосов
/ 07 декабря 2018

Даже столбец автоинкремента не является PK (в этом примере он называется seq - aka sequence), вы можете добиться этого с помощью триггера:

УДАЛИТЬ СТОЛ, ЕСЛИ СУЩЕСТВУЕТ 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();
0 голосов
/ 06 июля 2016

Вдохновленный другими ответами здесь, я создал функцию 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.id, чтобы начать с 1.

# 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 голосов
/ 08 ноября 2013

Если вы используете pgAdmin3, разверните «Последовательности», щелкните правой кнопкой мыши последовательность, перейдите к «Свойствам» и на вкладке «Определение» измените «Текущее значение» на любое значение, которое вы хотите. Нет необходимости в запросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...