id INTEGER PRIMARY KEY
по своему усмотрению гарантирует (требует) уникальное целочисленное значение и будет, если никакое значение не назначено специально, предоставлять его до тех пор, пока наибольшее значение не достигнет максимально допустимого значения для 64-разрядного целого числа со знаком (9223372036854775807), после чего неиспользованноезначение может быть найдено и применено.
При AUTOINCREMENT
существует гарантия (если не обойти) всегда предоставлять более высокое значение, НО, если достигается 9223372036854775807 вместо выделения неиспользуемого числа, в результате возникнет ошибка SQLITE_FULL.Это единственное различие с точки зрения того, какое число будет присвоено.
Ни один из них не гарантирует монотонно возрастающее значение.
Без AUTOINCREMENT расчет / алгоритм эквивалентен
1 + max (rowid), и если значение больше 9223372036854775807, делается попытка найти неиспользуемое и, следовательно, более низкое значение.
- Я не видел, чтобы кто-нибудьстолкнулся с ситуацией, когда случайное неиспользуемое значение не было присвоено.
При AUTOINCREMENT расчет / алгоритм равен
больше 1 + max (rowid) или SELECT seq FROM sqlite_sequence WHERE name = 'the_table_name_the_rowid_is_being_assigned_to', а если значение больше 9223372036854775807, то SQLITE_FULL ERROR.
, если это не таквероятность того, что максимальное значение rowid предназначено для строки, которая в итоге не вставляется, и, следовательно, может стать пробелом.
Ответ, возможно, лучше всего сформулировать так: лучше / рекомендуется использовать столбец id исключительно для его предполагаемой цели, для эффективной идентификации строки, а не каксредство обработки других требований к данным, и в этом случае нет необходимости в AUTOINCREMENT (который имеет накладные расходы )
Короче
Гарантирует ли эточто идентификатор будет автоматически увеличиваться
NO
значения для удаленных строк не будут использоваться повторно?
NO для данного кода
для: -
CREATE TABLE names (id INTEGER PRIMARY KEY AUTOINCREMENT name TEXT NOT NULL)
снова NO , как будто достигается 9223372036854775807, тогда возникнет ошибка SQLITE_FULL,в противном случае ДА .
Таким образом, действительно, AUTOINCREMENT действительно действительно (только если идентификатор используется как ожидалось / предполагалось), когда 9223372036854775807-ая строка была вставлена.
Возможно, рассмотрим следующее: -
DROP TABLE IF EXISTS table1;
DROP TABLE IF EXISTS table2;
CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY, somecolumn TEXT);
CREATE TABLE IF NOT EXISTS table2 (id INTEGER PRIMARY KEY AUTOINCREMENT, somecolumn TEXT);
INSERT INTO table1 VALUES (9223372036854775807,'blah');
INSERT INTO table2 VALUES (9223372036854775807,'blah');
INSERT INTO table1 (somecolumn) VALUES(1),(2),(3);
SELECT * FROM table1;
INSERT INTO table2 (somecolumn) VALUES(1),(2),(3);
Это создает две одинаковые таблицы, единственное отличие заключается в использовании AUTOINCREMENT.В каждую вставлена строка с максимально допустимым значением для столбца id .
Затем делается попытка вставить 3 строки, в которых SQLite будет назначать id ..
3 строки вставляются в таблицу без AUTOINCREMENT, но при использовании AUTOINCREMENT строки не вставляются.согласно: -
CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY, somecolumn TEXT)
> OK
> Time: 0.098s
CREATE TABLE IF NOT EXISTS table2 (id INTEGER PRIMARY KEY AUTOINCREMENT, somecolumn TEXT)
> OK
> Time: 0.098s
INSERT INTO table1 VALUES (9223372036854775807,'blah')
> Affected rows: 1
> Time: 0.094s
INSERT INTO table2 VALUES (9223372036854775807,'blah')
> Affected rows: 1
> Time: 0.09s
INSERT INTO table1 (somecolumn) VALUES(1),(2),(3)
> Affected rows: 3
> Time: 0.087s
SELECT * FROM table1
> OK
> Time: 0s
INSERT INTO table2 (somecolumn) VALUES(1),(2),(3)
> database or disk is full
> Time: 0s
Результат SELECT для таблицы1 (который может отличаться из-за случайности) был: -
![enter image description here](https://i.stack.imgur.com/mzhhe.png)