У меня есть таблица с более чем миллионом строк. Мне нужно reset последовательность и переназначить столбец id новыми значениями (1, 2, 3, 4... и т.д.). Есть ли простой способ сделать это?
Как reset последовательность в столбцах postgres и заполнять идентификатор с новыми данными?
Ответ 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, разверните "Последовательности", щелкните правой кнопкой мыши по последовательности, перейдите в "Свойства", а на вкладке "Определение" измените "Текущее значение" на любое значение, которое вы хотите. Нет необходимости в запросе.