Как reset последовательность в столбцах postgres и заполнять идентификатор с новыми данными?

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

Ответ 1

Если вы не хотите сохранять упорядочение идентификаторов, вы можете

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

Я сомневаюсь, что есть простой способ сделать это в порядке по вашему выбору, не воссоздавая всю таблицу.

Ответ 2

Reset последовательность:

SELECT setval('sequence_name', 0);

Обновление текущих записей:

UPDATE foo SET id = DEFAULT;

Ответ 3

В PostgreSQL 8.4 или новее нет необходимости указывать WITH 1. Будет использоваться начальное значение, которое было записано с помощью CREATE SEQUENCE, или последнее, установленное с помощью ALTER SEQUENCE START WITH (скорее всего, это будет 1).

Сбросить последовательность:

ALTER SEQUENCE seq RESTART;

Затем обновите столбец идентификатора таблицы:

UPDATE foo SET id = DEFAULT;

Источник: Документация PostgreSQL

Ответ 4

Оба предоставленные решения не сработали для меня;

> 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 истинно (Postgres версия 9.0.4)

Решение, которое сработало для меня, это:

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

Ответ 5

Просто для упрощения и уточнения правильного использования ALTER SEQUENCE и SELECT setval для сброса последовательности:

ALTER SEQUENCE sequence_name RESTART WITH 1;

эквивалентно

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

Любое из утверждений может быть использовано для сброса последовательности, и вы можете получить следующее значение nextval ('sequence_name'), как указано здесь:

nextval('sequence_name')

Ответ 6

Лучший способ reset выполнить последовательность, начинающуюся с номера 1, - выполнить следующее:

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

Так, например, для таблицы пользователей это будет:

ALTER SEQUENCE users_id_seq RESTART WITH 1

Ответ 7

FYI: Если вам нужно указать новое начальное значение между диапазоном ID (например, 256 - 10000000):

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

Ответ 8

Чтобы сохранить порядок строк:

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;

Ответ 9

Простое восстановление последовательности и обновление всех строк может привести к дублированию ошибок идентификатора. Во многих случаях вам нужно дважды обновлять все строки. Сначала с более высокими идентификаторами, чтобы избежать дубликатов, а затем с идентификаторами, которые вы действительно хотите.

Пожалуйста, не добавляйте фиксированную сумму ко всем идентификаторам (как рекомендовано в других комментариях). Что произойдет, если у вас больше строк, чем эта фиксированная сумма? Предполагая, что следующее значение последовательности больше всех идентификаторов существующих строк (вы просто хотите заполнить пробелы), я бы сделал это так:

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

Ответ 10

В моем случае я достиг этого:

ALTER SEQUENCE table_tabl_id_seq RESTART WITH 6;

Где моя таблица называется table

Ответ 11

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

  • arg_table: имя таблицы (например, 'example')
  • arg_column: имя столбца первичного ключа (например, 'id')
  • arg_sequence: имя последовательности (например, 'example_id_seq')
  • arg_next_value: следующее значение для столбца после миграции

Он выполняет следующие операции:

  • Переместите значения первичного ключа в свободный диапазон. Я предполагаю, что nextval('example_id_seq') следует за max(id) и начинается последовательность с 1. Это также обрабатывает случай, когда arg_next_value > max(id).
  • Переместить значения первичного ключа в смежный диапазон, начиная с arg_next_value. Порядок ключевых значений сохраняется, но отверстия в диапазон не сохраняется.
  • Распечатайте следующее значение, которое будет следовать в последовательности. Это полезно, если вы хотите перенести столбцы другой таблицы и объединить с этим.

Чтобы продемонстрировать, мы используем последовательность и таблицу, определенные следующим образом (например, используя 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)

Ответ 12

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

ТАБЛИЦА DROP IF EXESTS 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();

Ответ 13

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