Что такое sequence в PostgreSQL?

JuniorPostgreSQL · Backend·Обновлено 8 июля 2026
Коротко
Sequence — это объект базы данных в PostgreSQL, который генерирует уникальные последовательные целочисленные значения. Чаще всего используется для автоматической генерации первичных ключей.

Sequence в PostgreSQL

Sequence (последовательность) — это специальный объект схемы базы данных, который генерирует уникальные числа в заданном порядке. PostgreSQL гарантирует, что каждый вызов функции nextval() вернёт уникальное значение, даже в условиях параллельных транзакций.

Зачем нужны sequences

Главная цель — автоматически генерировать уникальные идентификаторы для строк таблицы. Это безопаснее и производительнее, чем вручную вычислять MAX(id) + 1, поскольку sequence работает вне транзакции и защищён от гонки данных.

Создание sequence

-- Создать последовательность вручную
CREATE SEQUENCE user_id_seq
    START WITH 1
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;

Основные функции для работы

-- Получить следующее значение (изменяет состояние)
SELECT nextval('user_id_seq');

-- Получить текущее значение (не изменяет состояние, только после вызова nextval в сессии)
SELECT currval('user_id_seq');

-- Установить значение счётчика вручную
SELECT setval('user_id_seq', 1000);

Привязка sequence к колонке таблицы

-- Явное использование sequence как значения по умолчанию
CREATE TABLE users (
    id INTEGER DEFAULT nextval('user_id_seq') PRIMARY KEY,
    name TEXT NOT NULL
);

Типы SERIAL и IDENTITY — синтаксический сахар

PostgreSQL предоставляет удобные псевдотипы, которые автоматически создают sequence под капотом:

-- SERIAL — устаревший, но широко распространённый способ
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    total NUMERIC
);

-- GENERATED ALWAYS AS IDENTITY — современный стандарт SQL (PostgreSQL 10+)
CREATE TABLE products (
    id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name TEXT
);

SERIAL создаёт sequence и привязывает его через DEFAULT nextval(...). IDENTITY — более строгий стандарт SQL:2003, который не позволяет случайно вставить произвольное значение без явного OVERRIDING SYSTEM VALUE.

Важные свойства sequence

  • Атомарность без транзакции: nextval() не откатывается при откате транзакции — пропуски в нумерации это нормально.
  • CACHE: можно кэшировать несколько значений в памяти сессии для производительности, но это увеличивает риск пропусков при сбое.
  • CYCLE / NO CYCLE: определяет, начнёт ли sequence отсчёт заново после достижения MAXVALUE.

Просмотр существующих sequences

-- Список всех sequences в текущей схеме
SELECT sequence_name, start_value, increment
FROM information_schema.sequences
WHERE sequence_schema = 'public';

Что хочет услышать интервьюер

Понимание, что sequence — это объект схемы БД, а не просто свойство колонки

Знание основных функций: nextval(), currval(), setval()

Понимание разницы между SERIAL и GENERATED AS IDENTITY

Осознание того, что пропуски в sequence — нормальное поведение при откате транзакций

Понимание, зачем sequence нужен в условиях параллельных транзакций (защита от гонки)

Пример: Использование sequence через TypeORM

// Пример: создание таблицы с автоинкрементом через TypeORM (под капотом использует sequence)
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity('users')
export class User {
  // TypeORM генерирует SERIAL или IDENTITY в зависимости от настроек
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;
}

// Эквивалентный SQL, который TypeORM выполнит:
// CREATE SEQUENCE users_id_seq START 1;
// CREATE TABLE users (
//   id INTEGER DEFAULT nextval('users_id_seq') PRIMARY KEY,
//   name TEXT NOT NULL
// );

Пример: Работа с sequence через node-postgres

// Пример: получить следующее значение sequence напрямую через pg (node-postgres)
import { Pool } from 'pg';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

async function getNextUserId(): Promise<number> {
  const result = await pool.query("SELECT nextval('users_id_seq') AS next_id");
  return Number(result.rows[0].next_id);
}

// Сброс счётчика после ручной вставки данных с явными ID
async function resetSequenceAfterImport(maxId: number): Promise<void> {
  // setval с третьим параметром false означает: следующий nextval вернёт именно это значение
  await pool.query(`SELECT setval('users_id_seq', $1, false)`, [maxId + 1]);
}

Типичные ошибки

Путают sequence с AUTO_INCREMENT из MySQL — в PostgreSQL это разные механизмы с разными гарантиями

Считают, что значения sequence всегда будут без пропусков — при откате транзакции значение не возвращается

Используют устаревший SERIAL вместо современного GENERATED AS IDENTITY

Не знают, что currval() работает только в той же сессии, где уже был вызван nextval()

Думают, что setval() опасно использовать в продакшене — на самом деле это стандартный способ сброса счётчика после bulk-вставки

Лучшие курсы по теме

изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Node.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее