Как исправить ошибку «Неправильный синтаксис около конструкции "AUTO_INCREMENT"» в MS SQL Server?

Программист IT и автоматизация бизнеса
← На главную

Приветствуем вас! При написании прямых SQL-запросов к базам данных разработчики часто сталкиваются с досадными синтаксическими ошибками. Одной из наиболее типичных проблем при миграции кода или проектировании новых таблиц является ошибка «Сообщение 102, уровень 15, состояние 1: Неправильный синтаксис около конструкции "AUTO_INCREMENT"». В этом материале мы подробно разберем, почему возникает эта ошибка в СУБД от Microsoft, как ее исправить, а также рассмотрим лучшие практики обеспечения кроссплатформенности SQL-кода.

Разбор причины возникновения ошибки

Проанализируем ситуацию. Разработчик пытается выполнить следующий SQL-запрос для создания таблицы пользователей:


CREATE TABLE Users(
    id INT NOT NULL AUTO_INCREMENT, 
    login CHAR(10),
    CONSTRAINT MainKey PRIMARY KEY (id, login),
    path TEXT
)

В ответ на это Microsoft SQL Server возвращает ошибку синтаксиса. Выясним причину этой проблемы. Дело в том, что язык SQL, несмотря на наличие стандартов, имеет множество различных диалектов. Конструкция AUTO_INCREMENT является специфичной для СУБД MySQL и MariaDB. В MS SQL Server (использующем диалект Transact-SQL) аналогичный механизм автоматического приращения числового поля реализуется с помощью совершенно другого ключевого слова — IDENTITY.

Правильное решение для MS SQL Server

Для того чтобы успешно создать таблицу с автоинкрементным полем в MS SQL Server, нам необходимо заменить инструкцию AUTO_INCREMENT на IDENTITY(1,1). Параметры в скобках означают следующее: первый аргумент — это начальное значение (seed, с которого начинается отсчет), а второй — шаг приращения (increment) для каждой новой записи.

Посмотрим на пример работающего запроса:


CREATE TABLE Users(
    id INT NOT NULL IDENTITY(1,1), 
    login CHAR(10),
    CONSTRAINT UsersKey PRIMARY KEY (id, login),
    path TEXT
)

Этот запрос успешно выполнится на MS SQL Server. Поле id автоматически будет заполняться последовательными целыми числами (1, 2, 3 и так далее) при добавлении строк. Обратите внимание, что явная ручная вставка значений в поле с флагом IDENTITY по умолчанию запрещена. Если вам все же потребуется записать туда конкретное число вручную, придется временно включить специальный режим сессии с помощью команды SET IDENTITY_INSERT Users ON.

Реализация автоинкремента в других популярных СУБД

Рассмотрим подробнее, как реализуется автоинкремент в различных базах данных, если вам в будущем придется переносить этот код на другие платформы:

  1. MySQL / MariaDB: Используется ключевое слово AUTO_INCREMENT. Такое поле обязательно должно быть проиндексировано (чаще всего его делают частью первичного ключа PRIMARY KEY).
  2. PostgreSQL: В Postgres существует два основных подхода. Исторически популярным является использование псевдотипов данных семейства SERIAL (SMALLSERIAL, SERIAL, BIGSERIAL):
    
    CREATE TABLE Users (
        id SERIAL PRIMARY KEY,
        login CHAR(10)
    );
    
    При указании типа SERIAL база данных автоматически создает скрытый вспомогательный объект последовательности (Sequence) и привязывает его к полю в качестве значения по умолчанию. Современный же подход в PostgreSQL (начиная с версии 10) базируется на стандарте SQL:2003.
  3. Oracle Database: В старых версиях (до 11g включительно) приходилось вручную создавать отдельный генератор последовательностей (Sequence) и писать триггер на событие BEFORE INSERT. Начиная с версии 12c, СУБД поддерживает стандартную конструкцию автоинкремента.
  4. SQLite: В этой легковесной базе данных автоинкремент создается с помощью конструкции INTEGER PRIMARY KEY AUTOINCREMENT.

Единый стандарт SQL:2003

Разработчики часто задаются вопросом: существует ли универсальный способ создания автоинкремента, соответствующий международным стандартам? Да, начиная со спецификации SQL:2003, был утвержден единый синтаксис:

GENERATED [ALWAYS | BY DEFAULT] AS IDENTITY

Выясним разницу между этими режимами:

Этот стандартный синтаксис полностью поддерживается в современных версиях PostgreSQL (10+), Oracle (12c+) и IBM DB2. К сожалению, MS SQL Server и MySQL на данный момент этот стандарт не поддерживают, продолжая использовать свои классические конструкции IDENTITY и AUTO_INCREMENT.

Как решить проблему кроссплатформенности на практике?

Если перед вами стоит задача разработать приложение, которое должно безболезненно переключаться между различными СУБД без изменения исходного SQL-кода, написание «сырых» (raw) SQL-запросов создания таблиц вручную является антипаттерном. Посмотрим, как решают эту задачу профессиональные разработчики:

  1. Использование ORM (Object-Relational Mapping):

    Это самый популярный подход в современной разработке. ORM-системы (такие как NHibernate или Entity Framework для C#, Hibernate для Java, SQLAlchemy для Python) позволяют описывать структуру данных в виде классов объектно-ориентированного программирования. На основе этих классов ORM автоматически генерирует нужный диалект SQL под конкретную подключенную базу данных. Например, если вы укажете, что свойство класса является автоинкрементным идентификатором, ORM превратит это в IDENTITY(1,1) для MS SQL Server и в AUTO_INCREMENT для MySQL.

  2. Инструменты миграции баз данных:

    Специализированные инструменты, такие как Liquibase или Flyway, позволяют описывать схему базы данных в нейтральном формате (XML, YAML, JSON). Инструмент сам анализирует тип целевой СУБД и транслирует абстрактное описание структуры (например, тег автоинкремента) в корректные команды конкретного SQL-диалекта.

Специфика платформы 1С:Предприятие

Разберем, как эта проблема решается внутри экосистемы 1С. Разработчикам на платформе «1С:Предприятие» вообще не приходится писать запросы CREATE TABLE вручную. Платформа полностью абстрагирует разработчика от используемой СУБД (будь то MS SQL, PostgreSQL, Oracle или IBM DB2):

Таким образом, понимание различий в диалектах СУБД и использование современных инструментов абстракции (таких как ORM или встроенные возможности платформы 1С) позволяет создавать гибкие, надежные и легко переносимые информационные системы.

← На главную