Я столкнулся с проблемой, что моя первичная ключевая последовательность не синхронизирована со строками моей таблицы.
То есть, когда я вставляю новую строку, я получаю ошибку дублированного ключа, потому что последовательность, подразумеваемая в последовательном типе данных, возвращает число, которое уже существует.
Кажется, это вызвано тем, что импорт / восстановление не поддерживает последовательность должным образом.
Ответы:
Источник - Рубиновый Форум
источник
SELECT setval('your_table_id_seq', coalesce((select max(id)+1 from your_table), 1), false);
SELECT setval('your_seq',(SELECT GREATEST(MAX(your_id)+1,nextval('your_seq'))-1 FROM your_table))
pg_get_serial_sequence
может использоваться, чтобы избежать любых неправильных предположений о названии последовательности. Это сбрасывает последовательность в одном кадре:Или более кратко:
Однако эта форма не может правильно обрабатывать пустые таблицы, так как max (id) является нулем, и вы также не можете установить 0, потому что он будет вне диапазона последовательности. Одним из способов решения этой проблемы является использование
ALTER SEQUENCE
синтаксиса, т.е.Но
ALTER SEQUENCE
имеет ограниченное применение, поскольку имя последовательности и значение перезапуска не могут быть выражениями.Кажется, лучшее универсальное решение - это вызов
setval
с false в качестве 3-го параметра, что позволяет нам указать «следующее значение для использования»:Это помечает все мои коробки:
Наконец, обратите внимание, что это
pg_get_serial_sequence
работает , только если последовательность принадлежит столбцу. Это будет иметь место, если столбец увеличения был определен какserial
тип, однако, если последовательность была добавлена вручную, необходимо убедиться, чтоALTER SEQUENCE .. OWNED BY
она также выполняется.т.е. если
serial
для создания таблицы использовался тип, все это должно работать:Но если последовательности были добавлены вручную:
источник
setval()
устанавливает текущее значение иnextval()
уже вернет текущее значение +1.Самый короткий и быстрый способ:
tbl_id
являясьserial
столбцом таблицыtbl
, рисуя из последовательностиtbl_tbl_id_seq
(которая является автоматическим именем по умолчанию).Если вы не знаете имя присоединенной последовательности (которая не обязательно должна быть в форме по умолчанию), используйте
pg_get_serial_sequence()
:Здесь нет единой ошибки. По документации:
Жирный акцент мой.
Если таблица может быть пустой и фактически начинаться с 1 в этом случае:
Мы не можем просто использовать форму 2-paremater и начать с
0
того, что нижняя граница последовательностей по умолчанию равна 1 (если не настроена).совпадение
Пока нет защиты от одновременной активности последовательности или записи в таблицу в вышеуказанных запросах. Если это актуально, вы можете заблокировать таблицу в эксклюзивном режиме. Он не позволяет одновременным транзакциям записывать большее число, пока вы пытаетесь синхронизироваться. (Это также временно блокирует безвредные записи, не связываясь с максимальным числом.)
Но это не учитывает клиентов, которые могли заранее получить порядковые номера без каких-либо блокировок на главной таблице (что может случиться). Чтобы учесть это, тоже только увеличивайте текущее значение последовательности, но никогда не уменьшайте его. Это может показаться параноидальным, но это соответствует природе последовательностей и защите от проблем параллелизма.
источник
EXECUTE format()
(например, @ EB.) Является важной функцией! Как исправить это отсутствие стандартной библиотеки в PostgreSQL ????Это сбросит все последовательности из общедоступного, не делая никаких предположений относительно имен таблиц или столбцов. Проверено на версии 8.4
источник
substring(column_default, '''(.*)''')
вместоtable_name || '_' || column_name || '_seq'
. Работает отлично.quote_literal
иquote_ident
, или предпочтительноformat
функция, действительно должны использоваться здесь.substring(column_default from 'nextval\(''(.+)''::regclass\)')
чтобы явно захватить имя последовательности. Работал как шарм.substring(column_default, '''(.*)''') instead of table_name || '_' || column_name || '_seq'
ALTER SEQUENCE sequence_name RESTART WITH (SELECT max (id) FROM table_name);Не работаетСкопировано из ответа @tardate:
источник
Эта команда только для изменения автоматически сгенерированного значения последовательности клавиш в postgresql
Вместо нуля вы можете поставить любое число, с которого вы хотите перезапустить последовательность.
имя последовательности по умолчанию будет
"TableName_FieldName_seq"
. Например, если имя вашей таблицы и имя"MyTable"
вашего поля"MyID"
, то имя вашей последовательности будет"MyTable_MyID_seq"
.Этот ответ такой же, как ответ @ murugesanponappan, но в его решении есть синтаксическая ошибка. Вы не можете использовать подзапрос
(select max()...)
вalter
команде. Так что либо вы должны использовать фиксированное числовое значение, либо вам нужно использовать переменную вместо подзапроса.источник
Сброс всех последовательностей, никаких предположений об именах, за исключением того, что первичным ключом каждой таблицы является «id»:
источник
pg_get_serial_sequence(''"' || tablename || '"''
EXECUTE format( 'SELECT setval(pg_get_serial_sequence(%L, %L), coalesce(max(id),0) + 1, false) FROM %I;', $1,$2,$1 );
Эти функции чреваты опасностями, когда имена последовательностей, имен столбцов, имен таблиц или схем имеют смешные символы, такие как пробелы, знаки пунктуации и тому подобное. Я написал это:
Вы можете вызвать его для одной последовательности, передав ему OID, и он вернет наибольший номер, используемый любой таблицей, в которой эта последовательность установлена по умолчанию; или вы можете запустить его с таким запросом, чтобы сбросить все последовательности в вашей базе данных:
Используя другую квалификацию, вы можете сбросить только последовательность в определенной схеме и т. Д. Например, если вы хотите настроить последовательности в «публичной» схеме:
Обратите внимание, что из-за того, как работает setval (), вам не нужно добавлять 1 к результату.
В качестве заключительного замечания я должен предупредить, что некоторые базы данных, по-видимому, имеют значения по умолчанию, связанные с последовательностями таким образом, что не позволяют системным каталогам иметь полную информацию о них. Это происходит, когда вы видите такие вещи в psql's \ d:
Обратите внимание, что вызов nextval () в этом предложении по умолчанию имеет приведение :: text в дополнение к приведению :: regclass. Я думаю, это связано с тем, что базы данных были pg_dump'ом из старых версий PostgreSQL. Что произойдет, так это то, что функция sequence_max_value () выше будет игнорировать такую таблицу. Чтобы устранить проблему, вы можете переопределить предложение DEFAULT, чтобы ссылаться на последовательность напрямую без приведения:
Тогда psql отображает это правильно:
Как только вы исправите это, функция будет работать правильно для этой таблицы, а также для всех других, которые могут использовать ту же последовательность.
источник
newmax := r.max::bigint;
чтобы оно работало правильно для меня.'SELECT max(' || quote_ident(colname) || ') FROM '
=>'SELECT max(' || quote_ident(colname) || '::bigint) FROM '
заметить добавленное::bigint
приведение в динамически построенном запросе.Еще один plpgsql - сбрасывается только если
max(att) > then lastval
также комментирование строки
--execute format('alter sequence
даст список, фактически не сбрасывая значениеисточник
Сбросить всю последовательность из общего
источник
Я предлагаю это решение, найденное на postgres wiki. Он обновляет все последовательности ваших таблиц.
Как использовать (из Вики Postgres):
Пример:
Оригинальная статья (также с исправлением последовательности владения) здесь
источник
Некоторые действительно жесткие ответы здесь, я предполагаю, что это было действительно плохо примерно в то время, когда об этом спрашивали, так как многие ответы отсюда не работают для версии 9.3. Документация , начиная с версии 8.0 дает ответ на этот самый вопрос:
Кроме того, если вам нужно позаботиться о именах последовательностей с учетом регистра, вот как вы это делаете:
источник
Эта проблема возникает у меня при использовании сущностной инфраструктуры для создания базы данных, а затем заполнения базы данных исходными данными, что приводит к несоответствию последовательности.
Я решил это, создав скрипт для запуска после заполнения базы данных:
источник
MAX("Id") + 1
это работает лучше для меня, когда последовательность = макс.Моя версия использует первую, с некоторой проверкой ошибок ...
источник
RAISE WARNING
определили для меня.Собираем все вместе
исправит
id'
последовательность данной таблицы (как обычно необходимо, например, для django).источник
прежде чем я еще не попробовал код: в следующем я выкладываю версию для sql-кода для решений Klaus и user457226, которая работала на моем компьютере [Postgres 8.3], с небольшими изменениями для Klaus и моей версии для пользователя 457226 один.
Клаус решение:
user457226 решение:
источник
Перепроверьте всю последовательность в публичной функции схемы
источник
Чтобы перезапустить всю последовательность до 1, используйте:
источник
Ответ Клауса - самый полезный, за исключением небольшой ошибки: вы должны добавить DISTINCT в операторе select.
Однако, если вы уверены, что никакие имена таблиц и столбцов не могут быть эквивалентны для двух разных таблиц, вы также можете использовать:
который является расширением решения user457226 для случая, когда какое-то интересующее имя столбца не является «ID».
источник
Если вы видите эту ошибку при загрузке пользовательских данных SQL для инициализации, другой способ избежать этого:
Вместо того чтобы писать:
Удалить
id
(первичный ключ) из исходных данныхЭто поддерживает последовательность Postgres в синхронизации!
источник
Этот ответ является копией от Мауро.
источник
Я потратил час, пытаясь получить ответ djsnowsill для работы с базой данных, используя таблицы и столбцы Mixed Case, и, наконец, наткнулся на решение благодаря комментарию от Мануэля Дарво, но я подумал, что могу сделать его немного понятнее для всех:
Это имеет преимущество:
Чтобы объяснить, проблема заключалась в том, что
pg_get_serial_sequence
для определения того, на что вы ссылаетесь , нужны строки, поэтому если вы это сделаете:Это достигается с помощью
''%1$I''
в строке формата,''
делает апостроф1$
означает первый аргумент иI
означает в кавычкахисточник
источник
Гадкий взлом, чтобы исправить это с помощью некоторой магии оболочки, не очень хорошее решение, но может вдохновить других на подобные проблемы :)
источник
Попробуйте переиндексировать .
ОБНОВЛЕНИЕ: Как отмечено в комментариях, это было в ответе на оригинальный вопрос.
источник
SELECT setval...
делает JDBC борком, поэтому вот Java-совместимый способ сделать это:источник
Метод для обновления всех последовательностей в вашей схеме, которые используются в качестве идентификатора:
источник
Просто запустите команду ниже:
источник
Здесь много хороших ответов. У меня возникла такая же необходимость после перезагрузки базы данных Django.
Но мне нужно было:
Кажется, это очень похоже на то, что было в оригинальном запросе.
Благодаря Балдири и Мауро вывели меня на правильный путь.
Затем выполнить и увидеть изменения:
Возвращает
источник