Есть ли в sqlite автоматическое приращение?

109

Я пытаюсь создать таблицу с автоинкрементом primary keyв Sqlite3 . Я не уверен, возможно ли это на самом деле, но я надеюсь, что мне нужно указать только другие поля.

Например:

CREATE TABLE people (id integer primary key auto increment, first_name varchar(20), last_name varchar(20));

Затем, когда я добавляю значение, я надеялся, что мне нужно будет только сделать:

INSERT INTO people
VALUES ("John", "Smith");

Это вообще возможно?

Я работаю sqlite3под управлением cygwinWindows 7.

эвок
источник

Ответы:

167

Вы получаете один бесплатно под названием ROWID. Это есть в каждой таблице SQLite, просите вы об этом или нет.

Если вы включаете столбец типа INTEGER PRIMARY KEY, этот столбец указывает (является псевдонимом) на автоматический столбец ROWID.

ROWID (как бы вы его ни называли) присваивается значение всякий раз, когда вы ВСТАВЛЯЕТЕ строку, как и следовало ожидать. Если вы явно назначите значение, отличное от NULL, для INSERT, он получит это указанное значение вместо автоинкремента. Если вы явно присваиваете значение NULL для INSERT, он получит следующее значение автоинкремента.

Также следует избегать:

 INSERT INTO people VALUES ("John", "Smith");

и использовать

 INSERT INTO people (first_name, last_name) VALUES ("John", "Smith");

вместо. Первая версия очень хрупкая - если вы когда-либо добавляете, перемещаете или удаляете столбцы в определении вашей таблицы, INSERT либо завершится ошибкой, либо выдаст неверные данные (со значениями в неправильных столбцах).

Ларри Люстиг
источник
53
ROWID - это не совсем то же самое, что истинный автоинкремент, так как ТО ЖЕ значение может генерироваться более одного раза. Например, с пустой таблицей, вставка 3 строк дает 3-й строке ROWID 3, как и ожидалось. Однако вставьте 2 строки, удалите последнюю и вставьте другую, дает 3-й вставленной строке ROWID 2, как и 2-я строка. Следовательно, существует очевидная серьезная проблема, если таблицы ссылаются на ROWID в таблице, в которой происходят удаления, и где удаления или обнуление ROWID также не выполняются в связанных таблицах.
Ник
10
В случае, если это не очевидно из ответа, вы можете использовать ROWID в своем операторе выбора, напримерselect rowid from people;
Colin D
@Nick, чтобы дополнить вашу идею: поэтому автоматическое приращение - это мера безопасности. И мы не говорим о столкновении двух строк в ROWID.
YoussefDir
69

Да, это возможно. Согласно SQLite FAQ :

Объявленный столбец INTEGER PRIMARY KEYбудет автоматически увеличиваться.

Мэтт Халс
источник
12
Предостережение, упомянутое Уку и также объясненное в документации, заключается в том, что вам необходимо передать NULL для идентификатора, чтобы это работало.
Мэтт Халс,
22
Вам нужно использовать NULL только в том случае, если вы опускаете список столбцов для INSERT - никогда не рекомендуется. Если вы укажете столбцы, вы можете просто опустить столбец с автоинкрементом, и он получит следующее значение.
Ларри Ластиг
5
Еще одно предостережение: напишите «INTEGER ...» точно так, как указано выше. Сокращение «INT ...» НЕ будет работать.
Марцин Войнарски
27

На сегодняшний день - июнь 2018 г.


Вот что говорится в официальной документации SQLite по этому поводу (полужирный и курсив - мои):

  1. В AUTOINCREMENT ключевое слово навязывает дополнительный процессор, память, дисковое пространство, и диск I / O накладные расходы и следует избегать , если не строго необходимо. Обычно в этом нет необходимости.

  2. В SQLite столбец с типом INTEGER PRIMARY KEY является псевдонимом для ROWID (кроме таблиц WITHOUT ROWID), который всегда является 64-битным целым числом со знаком.

  3. При INSERT, если столбцу ROWID или INTEGER PRIMARY KEY явно не присвоено значение, он будет автоматически заполнен неиспользуемым целым числом, обычно на единицу больше, чем самый большой ROWID, используемый в настоящее время . Это верно независимо от того, используется ли ключевое слово AUTOINCREMENT.

  4. Если ключевое слово AUTOINCREMENT появляется после INTEGER PRIMARY KEY , это изменяет алгоритм автоматического назначения ROWID, чтобы предотвратить повторное использование ROWID в течение срока службы базы данных. Другими словами, цель AUTOINCREMENT - предотвратить повторное использование ROWID из ранее удаленных строк.


источник
11

Вы это читали? Как создать поле AUTOINCREMENT.

INSERT INTO people
VALUES (NULL, "John", "Smith");
Уку Лоскит
источник
Итак, вы говорите, что то, что я пытаюсь сделать, невозможно, но я могу моделировать. Мне нужно использовать нуль во вставке?
ewok
1
вам не нужно ничего делать, но всегда вставляйте NULL в качестве идентификатора, это просто объясняет, как sqlite делает это внутри.
Уку Лоскит
7
NULL для INSERT требуется только в том случае, если вы не укажете список столбцов для INSERT (в этом случае вам нужно количество значений, точно соответствующее количеству столбцов, и вы должны использовать NULL в качестве заполнителя). Но выполнение INSERT без указания списка столбцов никогда не является хорошей практикой. Если вы укажете список столбцов, просто оставьте столбец с автоинкрементом и значение NULL, и вы получите ожидаемый результат.
Ларри Ластиг
4

Не следует указывать AUTOINCREMENTключевое слово рядом PRIMARY KEY. Пример создания первичного ключа автоинкремента и вставки:

$ sqlite3 ex1

CREATE TABLE IF NOT EXISTS room(room_id INTEGER PRIMARY KEY, name VARCHAR(25) NOT NULL, home_id VARCHAR(25) NOT NULL);

INSERT INTO room(name, home_id) VALUES ('test', 'home id test');

INSERT INTO room(name, home_id) VALUES ('test 2', 'home id test 2');

SELECT * FROM room;

дам:

1|test|home id test
2|test 2|home id test 2
Денис Кутлубаев
источник
4

Помимо rowid, вы можете определить собственное поле автоматического увеличения, но это не рекомендуется. Когда мы используем автоматически увеличиваемый rowid, это всегда будет лучшим решением.

В AUTOINCREMENTключевом слове навязывает дополнительный процессор, память, дисковое пространство, и диск I / O накладных расходов и следует избегать , если не строго необходимо. Обычно в этом нет необходимости.

Подробную информацию читайте здесь .

sonvx
источник
очевидно, rowid не всегда увеличивается автоматически, см. комментарий Ника
rogerdpack
1
Не правда. Автоматическое приращение в некоторых отношениях лучше, так как оно не будет использовать повторно идентификаторы - довольно важное требование для многих систем.
O'Rooney
4

SQLite AUTOINCREMENT - это ключевое слово, используемое для автоматического увеличения значения поля в таблице. Мы можем автоматически увеличивать значение поля, используя ключевое слово AUTOINCREMENT при создании таблицы с определенным именем столбца, чтобы автоматически увеличивать его.

Ключевое слово AUTOINCREMENT можно использовать только с полем INTEGER. Синтаксис:

Основное использование ключевого слова AUTOINCREMENT следующее:

CREATE TABLE table_name(
   column1 INTEGER AUTOINCREMENT,
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);

Для примера см. Ниже: Предположим, что таблица КОМПАНИЯ создается следующим образом:

sqlite> CREATE TABLE TB_COMPANY_INFO(
   ID INTEGER PRIMARY KEY   AUTOINCREMENT,
   NAME           TEXT      NOT NULL,
   AGE            INT       NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

Теперь вставьте следующие записи в таблицу TB_COMPANY_INFO:

INSERT INTO TB_COMPANY_INFO (NAME,AGE,ADDRESS,SALARY)
VALUES ( 'MANOJ KUMAR', 40, 'Meerut,UP,INDIA', 200000.00 );

Теперь выберите запись

SELECT *FROM TB_COMPANY_INFO
ID      NAME            AGE     ADDRESS             SALARY
1       Manoj Kumar     40      Meerut,UP,INDIA     200000.00
mkumar0304
источник
2

Я знаю, что этот ответ немного запоздал.
Моя цель в этом ответе - дать ссылку всем, если они столкнутся с таким типом проблемы с SQLite сейчас или в будущем, и им будет сложно с этим.

Теперь, оглядываясь на ваш запрос, он должен быть примерно таким.

CREATE TABLE people (id integer primary key autoincrement, first_name varchar(20), last_name varchar(20));

Это работает с моей стороны. Вот так,

введите описание изображения здесь

На всякий случай, если вы работаете с SQLite, я предлагаю вам проверить DB Browser для SQLite . Также работает на разных платформах.

Кент Агилар
источник
0

То, что вы делаете, правильно, но правильный синтаксис для «автоинкремента» не должен содержать пробелов:

CREATE TABLE people (id integer primary key autoincrement, first_name string, last_name string);

(Также обратите внимание, что я изменил ваши varchars на строки. Это потому, что SQLite внутренне преобразует varchar в строку, так зачем беспокоиться?)

тогда ваша вставка должна быть на максимально стандартном языке SQL:

INSERT INTO people(id, first_name, last_name) VALUES (null, 'john', 'doe');

Хотя верно, что если вы опустите id, он будет автоматически увеличиваться и назначаться, я лично предпочитаю не полагаться на автоматические механизмы, которые могут измениться в будущем.

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

HTH

Лука Нанетти
источник
В этом отношении я полностью разделяю то, что говорит О'Руни.
Лука Нанетти
И если вы попытаетесь установить флажок AI в браузере БД для диалогового окна Modify Table SQLite, он не сохранит это, если в таблице уже есть записи. Моя работа заключалась в том, чтобы выполнить экспорт «всего» и изменить спецификацию PK в файле .sql, чтобы добавить AUTOINCREMENT, а затем использовать этот файл для импорта обратно в базу данных. Он не только сохранил AI, но и сохранил значения PK такими, какими они были, даже если они не начинались с 1.
Майк V