Проектирование баз данных
April 18

Всё, что вы хотели знать об автоинкременте, но стеснялись спросить

Автоинкремент — это функция в базах данных SQL, которая автоматически генерирует уникальный номер для каждой новой строки в таблице.

Разработчик узнавший об автоинкременте

Автоинкремент — это функция в базах данных, которая автоматически генерирует уникальный номер для каждой новой строки, добавленной в таблицу.

Как правило этот номер используется в качестве первичного ключа для уникальной идентификации каждой строки в таблице.

При добавлении новой строки в таблицу, где одна из колонок сконфигурирована как автоинкремент, база данных автоматически присваивает каждому новому ряду в этой колонке следующий доступный номер, избавляя пользователя от необходимости вручную управлять значениями первичного ключа. Это упрощает процесс добавления новых строк и гарантирует, что каждая строка имеет уникальный идентификатор.

Если вы хотите попрактиковаться в создании таблиц с "автоинкрементальными" колонками и выполнении операторов SQL, вы можете попробовать использовать онлайн-редактор SQL, такой как SQLize.online, который позволяет создавать таблицы, вставлять данные и выполнять SQL-запросы в действующей базе данных.

Создание таблицы

Ниже показано, как создать таблицу с колонкой - автоинкемкнтом в различных РСУБД.

SQLite:

CREATE TABLE example_table ( 
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    name VARCHAR(50), age INT 
);

В этом примере столбец id определен как целочисленный тип данных с ключевым словом AUTOINCREMENT. Он также задан как первичный ключ таблицы (PRIMARY KEY).

MySQL и MariaDB:

CREATE TABLE example_table (
   id INTEGER PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(50),
   age INT
);

В этом примере столбец id определен как столбец с автоматическим инкрементом с помощью ключевого слова AUTO_INCREMENT. Он также установлен в качестве первичного ключа таблицы.

SQL Server:

CREATE TABLE example_table (
   id INTEGER PRIMARY KEY IDENTITY(1, 1),
   name VARCHAR(50),
   age INT
);

В отличии от двух первых примеров, в SQL Server не используется термин AUTO INCREMENT, Вместо этого столбец id определен как столбец идентичности с помощью ключевого слова IDENTITY. Он также определён как первичный ключ таблицы. Параметры (1, 1) задают начальное значение и шаг автоинкремента. В приведённом примере поле id будет получать значения начиная с 1 и каждый раз увеличиваться на 1 для каждой новой строки. (1, 2, 3, ...) Максимальное значение ограничивается размерностью типа INTEGER. Изменив параметры на IDENTITY(100, 10) мы можем начать нумерацию с 100 и каждый раз прибавлять 10 (100, 110, 120, 130…). Больше того, в качестве начала и шага можно использовать отрицательные числа. Попробуйте сами здесь.

Oracle:

В этой базе данных всё немного сложнее. Здесь нет простого механизма автонумерации и приходится использовать более сложный механизм - последовательности.

CREATE SEQUENCE example_table_seq;

CREATE TABLE example_table (
   id INTEGER DEFAULT example_table_seq.nextval PRIMARY KEY,
   name VARCHAR2(50),
   age INT
);

В этом примере сначала создается последовательность (SEQUENCE) с помощью оператора CREATE SEQUENCE. Затем столбец id определяется как числовой тип данных INTEGER со значением по умолчанию, равным следующему значению последовательности. Он также задается в качестве первичного ключа таблицы. В приведенном примере (по умолчанию) будет создана последовательность с начальным значением 1 и шагом 1. Если нам нужен другой вариант последовательности мы можем указать параметры INCREMENT BY и START WITH при её создании:

CREATE SEQUENCE example_table_seq 
    INCREMENT BY 10
    START WITH 10;

PostgreSQL:

Данная СУБД имеет несколько вариантов определения автоинкрементного столбца. Наиболее простым и популярным является ключевое слово SERIAL - которое является псевдонимом для колонки типа INTEGER с автоувеличением. Также в PostgreSQL допустимы варианты SMALLSERIAL и BIGSERIAL для типов SMALLINT и BIGINT соответственно

CREATE TABLE example_table (
   id SERIAL PRIMARY KEY,
   name VARCHAR(50),
   age INT
);

В этом примере столбец id определен как последовательный тип данных, что эквивалентно столбцу с автоматическим инкрементом в других СУБД. Он также задан как первичный ключ таблицы

Кроме того, для создания автоинкрементного столбца в PostgreSQL можно использовать как синтаксис IDENTITY, так и синтаксис SEQUENCE.

Вот примеры создания автоинкрементного столбца с использованием такого синтаксиса в PostgreSQL:

CREATE TABLE example_table (
   id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
   name VARCHAR(50),
   age INT
);
CREATE SEQUENCE example_table_seq;

CREATE TABLE example_table (
   id INT DEFAULT nextval('example_table_seq') PRIMARY KEY,
   name VARCHAR(50),
   age INT
);

Как и в примере с Oracle DB, вариант с SEQUENCE предлагает возможности гибкой конфигурации автоинкремента в отличии от SERIAL

Добавление данных

Чтобы вставить новую строку в таблицу с автоинкрементным столбцом, мы можем использовать оператор INSERT INTO, указав для всех столбцов, кроме автоинкрементного:

INSERT INTO example_table (name, age) VALUES ('John Smith', 30);

Большинство диалектов SQL позволяет вставлять несколько строк в один запрос.

INSERT INTO example_table (name, age)
VALUES
  ('Джейн Доу', 25),
  ('Боб Джонсон', 40),
  ('Элис Браун', 35);

Если сейчас сделать выборку из таблицы Мы увидим что столбец `id` был автоматически заполнен последовательными числами:

+====+=============+=====+
| id | name        | age |
+====+=============+=====+
| 1  | Джейн Доу   | 25  |
| 2  | Боб Джонсон | 40  |
| 3  | Элис Браун  | 35  |
+----+-------------+-----+

SQLite, MySQL & MariaDB позволяет вставлять произвольные значения в столбец с автоматическим увеличением и обновлять последовательность.

INSERT INTO example_table (id, name, age) VALUES (11, 'John Smith', 30);
INSERT INTO example_table (name, age) VALUES  
        ('Jane Doe', 25),  ('Bob Johnson', 40),  ('Alice Brown', 35);

SELECT * FROM example_table;

В приведенном выше примере мы вставляем 'John Smith' с id = 11 и затем ещё три строки без указания значений id. Эти строки будут вставлены со следующими значениями последовательности 12, 13, 14 Проверьте это здесь.

+====+=============+=====+
| id | name        | age |
+====+=============+=====+
| 11 | John Smith  | 30  |
| 12 | Jane Doe    | 25  |
| 13 | Bob Johnson | 40  |
| 14 | Alice Brown | 35  |
+----+-------------+-----+

MS SQL Server по умолчанию не допускает такого волюнтаризма и вернёт нам ошибку если мы попытаемся это сделать.

INSERT INTO example_table (id, name, age) VALUES (11, 'John Smith', 30);
[SQL Server]Cannot insert explicit value for identity column in table 'example_table' when IDENTITY_INSERT is set to OFF.

Поэтому, если нам нужно вставить значение в столбец identity, мы должны включить параметрIDENTITY_INSERT в нашей таблице (и не забыть выключить его после вставки):

SET IDENTITY_INSERT example_table ON
INSERT INTO example_table (id, name, age) VALUES (11, 'John Smith', 30)
SET IDENTITY_INSERT example_table OFF;

Приведенный выше запрос вставляет запись с id = 11 и перемещает вверх счетчик для вставки последующих записей.

А как насчет Oracle? Эта DB позволяет вставлять значения в столбец id, без влияния на последовательности, поэтому мы можем вставлять строку с произвольным id, но это может привести к конфликту, как в следующем примере:

CREATE SEQUENCE example_table_seq;

CREATE TABLE example_table (
   id NUMBER DEFAULT example_table_seq.nextval PRIMARY KEY,
   name VARCHAR2(50),
   age NUMBER
);
--вставляем строку с id = 3
INSERT INTO example_table (id, name, age) VALUES (3, 'John Smith', 30);

-- следующие запросы вставят строки с id 1 и 2
INSERT INTO example_table (name, age) VALUES ('Jane Doe', 25); -- 1
INSERT INTO example_table (name, age) VALUES ('Bob Johns', 40); -- 2

-- здесь получаем ошибку OCIStmtExecute: 
-- ORA-00001: unique constraint (0c7690dacb6b.SYS_C009760) violated 
INSERT INTO example_table (name, age) VALUES ('Alice Brown', 35); 

SELECT * FROM example_table;

PostgreSQL с синтаксисом SERIAL или SEQUENCE для столбца с автоматическим увеличением показывают нам такое же поведение, как и Oracle (строка вставлена, последовательность не обновлена, ошибка при дублировании). Но при использовании синтаксиса IDENTITY вставка строки с произвольным идентификатором не допускается. Это ограничение может быть обойдено переопределением системного значения, как в следующем примере, но опять же это не обновляет последовательность и может вызвать конфликт.

CREATE TABLE example_table (
   id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
   name VARCHAR(50),
   age INT
);
INSERT INTO example_table (id, name, age) OVERRIDING SYSTEM VALUE VALUES (3, 'John Smith', 30);
INSERT INTO example_table (name, age) VALUES ('Jane Doe', 25);
INSERT INTO example_table (name, age) VALUES ('Bob Johnson', 40);
INSERT INTO example_table (name, age) VALUES ('Alice Brown', 35);

SELECT * FROM example_table;

Двигаемся дальше!

Как изменить значение автоинкремента?

SQLite:

В SQLite можно сбросить значение автоматического увеличения для таблицы с помощью таблицы sqlite_sequence.

Таблица sqlite_sequence — это внутренняя таблица, используемая SQLite для отслеживания следующего значения автоинкремента для каждой таблицы в базе данных. Каждая строка в таблице sqlite_sequence представляет таблицу в базе данных, а в столбце seq хранится следующее значение автоматического увеличения для этой таблицы. Поэтому, когда нам нужно изменить его, просто попробуйте следующее:

UPDATE sqlite_sequence SET seq = 100 WHERE name = 'example_table';

INSERT INTO example_table (name, age) VALUES ('John Gold', 30);

Приведенный выше код изменит значение автоприращения на 100, а следующая вставленная строка получит id = 101;

Мы можем удалить автоинкремент следующим запросом:

DELETE FROM sqlite_sequence WHERE name = 'example_table';

или установить его меньше максимального значения в автоматически увеличиваемом столбце, но после вставки новой строки sqlite_sequence будет исправлен автоматически. Просто посмотрите следующий фрагмент кода:

CREATE TABLE example_table (
   id INTEGER PRIMARY KEY AUTOINCREMENT,
   name VARCHAR(50),
   age INT
);

INSERT INTO example_table (name, age)
VALUES
  ('Jane Doe', 25),
  ('Bob Johnson', 40),
  ('Alice Brown', 35);

SELECT * FROM sqlite_sequence WHERE name = 'example_table';

данный код вернет следующий результат:

+===============+=====+
| name          | seq |
+===============+=====+
| example_table | 3   |
+---------------+-----+

Удалим его и убедимся что данные исчезли:

DELETE FROM sqlite_sequence WHERE name = 'example_table';

SELECT * FROM sqlite_sequence WHERE name = 'example_table';

но после следующей записи вставленное значение последовательности также будет восстановлено. Попробуйте здесь.

MySQL & MariaDB:

MySQL & MariaDB также позволяет изменять автоинкремент с помощью запроса ALTER TABLE, но оно не может быть меньше максимального значения в автоматически увеличенном столбце:

ALTER TABLE example_table AUTO_INCREMENT = 100;

В Oracle можно изменить последовательность с помощью инструкции ALTER SEQUENCE. Этот оператор позволяет изменять характеристики последовательности, такие как минимальное и максимальное значения, шаг и начальное значение. Если необходимо внести более существенные изменения в последовательность, например изменить ее тип данных или полностью удалить ее, может потребоваться удалить и пересоздать последовательность.

DROP SEQUENCE example_table_seq;

CREATE SEQUENCE example_table_seq INCREMENT BY 1 START WITH 100;

Обратите внимание, что в Oracle нет проверки конфликтов между новым значением последовательности и существующими записями. Поэтому важно проявлять осторожность и использовать эту функцию ответственно, чтобы избежать непредвиденных последствий.

PostgreSQL:

В PostgreSQL не имеет значения, как создается столбец с автоматическим увеличением (SERIAL, GENERATED ALWAYS AS IDENTITY или с помощью CREATE SEQUENCE), поскольку для изменения последовательности можно использовать инструкцию ALTER SEQUENCE. Однако данная СУБД не гарантирует отсутствие конфликтов после модификации последовательности, поэтому важно проявлять осторожность.

ALTER SEQUENCE example_table_id_seq RESTART WITH 100;

В качестве заключения

Автоинкремент — это функция баз данных, которая генерирует уникальный номер для каждой новой строки, добавляемой в таблицу, избавляя пользователя от необходимости вручную управлять значениями первичного ключа.

Эта функция поддерживается большинством СУБД и может быть легко реализована с использованием разного синтаксиса в каждой базе данных. SQLite, MySQL и MariaDB поддерживают столбцы с автоинкрементом, а также PostgreSQL и Oracle, которые также допускают более продвинутые параметры, такие как последовательности и последовательные типы данных.

Хотя каждая база данных имеет свой собственный синтаксис для реализации и управления автоинкрементом.

В целом функция автоинкремента значительно упрощает процесс добавления новых строк и гарантирует, что каждая строка будет иметь уникальный идентификатор, что необходимо для многих операций с базой данных.