Как правильно создать последовательность?

Добрый вечер. 

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

В сущности столбец обозначен следующим образом: 

```php
#[ORM\Column(type: 'integer', nullable: true)]
private int $internalId;
```

Я создаю миграцию: 

```sql
public function up(Schema $schema): void
{
    $this->addSql('ALTER TABLE amqp_auth_user ADD internal_id INT NULL');
    $this->addSql('CREATE SEQUENCE amqp_auth_user_internal_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
    $this->addSql('ALTER TABLE amqp_auth_user ALTER internal_id SET DEFAULT nextval(\'amqp_auth_user_internal_id_seq\')');
    $this->addSql('ALTER SEQUENCE amqp_auth_user_internal_id_seq OWNED BY public.amqp_auth_user.internal_id;');
}
```

После выполнения запроса на вставку в таблицу все работает, и значение "internal_id" заполняется последовательными числами. 

Тем не менее, схема не проходит валидацию и выдает следующую ошибку: 

> [ERROR] The database schema is not in sync with the current mapping file. 

Команда **orm:schema-tool:update --dump-sql** генерирует запрос на удаление значения по умолчанию для столбца "internal_id": 

```sql
ALTER TABLE amqp_auth_user ALTER internal_id DROP DEFAULT;
```

После выполнения этого запроса, как вы понимаете, "internal_id" будет заполняться значением "null". 

В чем заключается моя ошибка? 

P.S. 

Я также попробовал следующий вариант: 

```php
#[ORM\Column(insertable: false, updatable: false, columnDefinition: 'serial')]
private int $internalId;
```
  • 18 февраля 2025 г. 0:24
Ответы на вопрос 2
Вы столкнулись с проблемой синхронизации схемы базы данных и маппинга Doctrine, так как добавили последовательное значение для столбца `internal_id` через миграцию, но не указали это в настройках ORM.

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

### Решение 1: Правильная настройка поля

Для того, чтобы избежать конфликта с ORM Doctrine, обеспечьте правильное определение вашего столбца в сущности. Если вы хотите, чтобы `internalId` автоматически заполнялся значениями последовательности, вам нужно настроить его соответствующим образом, используя Doctrine:

```php
#[ORM\Column(type: 'integer', nullable: true, options: ["default" => "nextval('amqp_auth_user_internal_id_seq')"])]
private ?int $internalId = null;
```

Убедитесь, что у вас стоит `nullable: true`, если вы хотите разрешить значения `null`. Не забудьте сделать поле типа `?int` для обработки `null` значений.

### Решение 2: Используйте последовательности

Если у вас уже есть последовательность, вы можете использовать его в вашем SQL-коде, как в вашем примере. Подход с использованием `serial` в `columnDefinition` также должен работать, но необходимо убедиться, что данные правильно отрабатываются.

Пример настройки:

```php
#[ORM\Column(type: 'integer', options: ['default' => 'nextval(\'amqp_auth_user_internal_id_seq\')'], nullable: true)]
private ?int $internalId = null;
```

### Подход с сериализацией

Использование `serial` в `columnDefinition` — это еще один вариант, но он зависит от того, как вы планируете управлять миграциями. Если вы используете `serial`, вы можете не указывать `nextval`, так как это встроенная функциональность PostgreSQL:

```php
#[ORM\Column(type: 'integer', nullable: true, columnDefinition: 'serial')]
private ?int $internalId = null;
```

### Вывод

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

Если вы будете продолжать испытывать проблемы, возможно, стоит выполнить `doctrine:schema:update` для полного обновления схемы, но помните, что лучше всего следовать своим миграциям, чтобы обработать все изменения в архитектуре базы данных.
Не читаем документацию: 
https://www.doctrine-project.org/projects/doctrine...
class Message
{
    #[ORM\Id]
    #[ORM\Column(name: "internalId", type: Types::INTEGER, nullable: false)]
    #[ORM\GeneratedValue]
    private int|null $internalId = null;
    // ...
}

Если у вас PostgreSQL, то нужно так:
class Message
{
    #[ORM\Id]
    #[ORM\Column(name: "internalId", type: Types::INTEGER, nullable: false)]
    #[ORM\GeneratedValue(strategy: "IDENTITY")]
    private int $internalId;
    // ...
}

Хотя если, вам ИМЕННО нужен sequence, то на всякий случай можно прямо в strategy это и указать
Похожие вопросы