Установите начальное значение для AUTOINCREMENT в SQLite

Как установить начальное значение для поля AUTOINCREMENT в SQLite?


person Christian Davén    schedule 28.03.2009    source источник


Ответы (6)


Явно вставьте value-1 в таблицу, затем удалите строку.

Изменить: следующий комментарий ниже, в котором обсуждается непосредственное редактирование таблицы SQLITE_SEQUENCE, вероятно, предпочтительнее: https://stackoverflow.com/a/692871/10093

person dave mankoff    schedule 28.03.2009
comment
Я полагаю, что это лучший способ сделать это, но это некрасиво. - person Christian Davén; 03.04.2009
comment
Это не работает для меня. Если у меня есть таблица «Пользователи» только с 1 записью (идентификатор 1), а автоинкремент равен 3, тогда другой пользователь вставляется с идентификатором -1, а затем удаляется, следующий вставленный пользователь по-прежнему имеет идентификатор 4 (расширение диспетчера SQLite для firefox, если это имеет значение) - person Assimilater; 08.04.2015
comment
похоже на обходной путь. я предпочитаю обращаться к записи таблицы sqlite_sequence для рассматриваемой таблицы. - person tony gil; 17.08.2016

С веб-сайта SQLite:

SQLite отслеживает самый большой ROWID, который когда-либо содержала таблица, используя специальную таблицу SQLITE_SEQUENCE. Таблица SQLITE_SEQUENCE создается и инициализируется автоматически всякий раз, когда создается обычная таблица, содержащая столбец AUTOINCREMENT. Содержимое таблицы SQLITE_SEQUENCE можно изменить с помощью обычных операторов UPDATE, INSERT и DELETE. Но внесение изменений в эту таблицу, скорее всего, нарушит алгоритм генерации ключей AUTOINCREMENT. Прежде чем вносить такие изменения, убедитесь, что вы знаете, что делаете.

Я пробовал это, и это работает:

UPDATE SQLITE_SEQUENCE SET seq = <n> WHERE name = '<table>'

Где n+1 — это следующий ROWID, который вам нужен, а table — это имя таблицы.

person Christian Davén    schedule 28.03.2009
comment
Не уверен, так как я не уверен, как работают внутренние компоненты sqlite. Стоит отметить, что jle и мои предложения выше - это то, как библиотека PHP MDB2 поддерживает изменение идентификатора. Взгляните на их источник драйвера sqlite: cvs.php.net/viewvc.cgi/pear/MDB2/MDB2/Драйвер/ - person dave mankoff; 28.03.2009
comment
Честность не проблема (я думаю, не эксперт или что-то в этом роде). Я полагаю, что проблема, о которой они предупреждают, заключается в том, что вы удаляете строку с идентификатором меньше MAX (ID) и пытаетесь вручную установить автоинкремент таким образом. Вы застрянете после первой вставленной строки из-за нарушения первичного ключа. - person Assimilater; 08.04.2015
comment
Точный алгоритм задокументирован на связанной странице и не будет изменен ни в одной из версий 3.x для сохранения совместимости. - person CL.; 27.05.2015
comment
Идеальный! Простое и элегантное решение. - person Nesar; 28.05.2017
comment
Единственная проблема заключается в том, что это не работает, если в sqlite_sequence еще нет записи для таблицы. Смотрите ответ iTech для правильного пути. - person w00t; 24.01.2018
comment
Это работает только в том случае, если вы явно используете ключевое слово AUTOINCREMENT в SQLite, которое не рекомендуется для стандартных случаев использования: ключевое слово AUTOINCREMENT накладывает дополнительные ресурсы ЦП, памяти, дискового пространства и дискового ввода-вывода, и его следует избегать, если это не строго необходимо. Обычно в этом нет необходимости. (цитата по вашей ссылке!). Функция неявного автоматического увеличения для столбца INTEGER PRIMARY KEY работает иначе (как псевдоним для ROWID). - person schlamar; 23.03.2021

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

BEGIN TRANSACTION;

UPDATE sqlite_sequence SET seq = <n> WHERE name = '<table>';

INSERT INTO sqlite_sequence (name,seq) SELECT '<table>', <n> WHERE NOT EXISTS 
           (SELECT changes() AS change FROM sqlite_sequence WHERE change <> 0);
COMMIT;
person iTech    schedule 13.10.2014
comment
Это единственное полностью правильное решение здесь. Однако изменения вуду вызывают у меня слезы на глазах ;) - person w00t; 24.01.2018
comment
Почему здесь используется «changes()»? Разве вы не можете просто сделать: ГДЕ НЕ СУЩЕСТВУЕТ ВЫБРАТЬ имя из sqlite_sequence ГДЕ имя = 'таблица' - person ndw; 14.03.2019

Один из способов сделать это — вставить первую строку, явно указав идентификатор строки, с которой вы хотите начать. Затем SQLite вставит идентификаторы строк, которые выше, чем предыдущий самый высокий.

person jle    schedule 28.03.2009

В решении с таблицей SQLITE_SEQUENCE кажется, что запись в эту таблицу добавляется после первой вставки в таблицу с добавлением столбца автоинкремента. В некоторых случаях это может вызвать проблемы (например, автоинкремент по-прежнему начинается с 1, а не с желаемого значения).

person Raivo Laanemets    schedule 29.01.2012

Просто хотел добавить несколько заметок к очень ценному ответу от iTech:

  • Столбец имени в sqlite_sequence чувствителен к регистру. (Возможно, это только я, но, исходя из других баз данных, я всегда предполагаю, что сравнение строк нечувствительно к регистру).
  • SQLite кажется надежным: если число в sqlite_sequence неверно и приведет к дублированию значения rowid, sqlite будет использовать следующий доступный номер для rowid (проверено с помощью sqlite 3.28)
  • То же самое верно, если строка в sqlite_sequence удаляется.
  • Я использовал, как было предложено в комментарии, «ГДЕ НЕ СУЩЕСТВУЕТ ВЫБРАТЬ имя из sqlite_sequence, ГДЕ имя =« таблица »» вместо проверки «изменения ()»
person Bernhard    schedule 06.07.2019