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



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

2876   12  

12 ответов:

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

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

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

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

SELECT setval('sequence_name', 0);

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

UPDATE foo SET id = DEFAULT;

С PostgreSQL 8.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, так как сл.is_called верно (версия Postgres 9.0.4)

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

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

просто для упрощения и уточнения правильного использования ИЗМЕНИТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ и выберите setval для сброса последовательности:

ALTER SEQUENCE sequence_name RESTART WITH 1;

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

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

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

nextval('sequence_name')

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

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

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

ALTER SEQUENCE users_id_seq RESTART WITH 1

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

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

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

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;

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

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

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

в моем случае я достиг этого с помощью:

ALTER SEQUENCE table_tabl_id_seq RESTART WITH 6;

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

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

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

Comments

    Ничего не найдено.