12 ответов:
Если вы не хотите сохранять порядок идентификаторов, то вы можете
ALTER SEQUENCE seq RESTART WITH 1; UPDATE t SET idcolumn=nextval('seq');Я сомневаюсь, что есть простой способ сделать это в порядке вашего выбора, не воссоздавая всю таблицу.
сброс последовательности:
SELECT setval('sequence_name', 0);обновление текущей записи:
UPDATE foo SET id = DEFAULT;
оба предоставленных решения не работали для меня;
> 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принимает следующие аргументы:
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)
Если вы используете pgAdmin3, разверните "последовательности", щелкните правой кнопкой мыши на последовательности, перейдите в "свойства" и на вкладке "определение" измените "текущее значение" на любое значение, которое вы хотите. Нет необходимости в запросе.
Comments