ORM UniqueConstraint, дубликат нулевого значения

У меня есть сущность с уникальным ограничением на 3 поля.

2 поля не обнуляются, а третье обнуляется.

Моя проблема, когда третье поле пустое, ограничение уникальности не работает, поэтому я могу иметь в моей базе данных несколько повторяющихся значений, таких как (5,1,null)(5,1,null)

Для меня, (5,1,null) это уникальное значение, с нулевым тоже.

Есть ли у вас какие-либо идеи?

Это моя линия ORM:

* @ORM\Table(name="table", uniqueConstraints={@ORM\UniqueConstraint(name="table_idx", columns={"field1", "field2", "field3"})})

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

3 ответа

Это может быть достигнуто с помощью двух частичных индексов. Но аннотации к доктрине недостаточно. Мы должны добавить немного SQL, чтобы решить эту проблему.

НОТА! Я использую PostgreSQL и миграции в моем проекте.

Сначала создайте 2 уникальных индекса (я использую YAML):

uniqueConstraints:
    table_idx_2_fields:
        columns: [ field1, field2 ]
    table_idx_3_fields:
        columns: [ field1, field2, field3 ]

Затем сгенерируйте класс миграции, используя консоль:

php app/console doctrine:migrations:diff

SQL будет сгенерирован, но его нужно немного изменить (добавлены предложения WHERE)

class Version20170622165834 extends AbstractMigration
{
    /**
     * @param Schema $schema
     */
    public function up(Schema $schema)
    {
        // ...

        $this->addSql('
            CREATE UNIQUE INDEX table_idx_2_fields ON tbl (field1, field2)
            WHERE field3 IS NULL;
        ');
        $this->addSql('
            CREATE UNIQUE INDEX table_idx_3_fields ON tbl (field1, field2, field3)
            WHERE field3 IS NOT NULL;
        ');
    }

    /**
     * @param Schema $schema
     */
    public function down(Schema $schema)
    {
        // ...
    }
}

Выполнить сгенерированный SQL (перенести):

php app/console doctrine:migrations:migrate -n

Готово!

Я тоже столкнулся с той же проблемой, не нашел способа ее решить.

Наконец добавил еще один столбец varchar в мою таблицу, его значение - комбинация из 3 полей. например:5_1_0(проверка вручную и добавление 0 для нулевого ограничения, в противном случае идентификатор ограничения) и добавление уникального ограничения для нового столбца и удаление существующего ограничения.

У меня был аналогичный случай, когда A всегда был установлен, B и C были нулевыми, но один из них всегда был установлен.

Итак, у меня были следующие возможности:

      A.  B.   C.
123-null-789
123-456-null

Я попытался создать UniqueConstraint как комбинацию A-B-C, но это не сработало.

Что сработало, так это два UniqueConstraints с параметром where:

       @ORM\UniqueConstraint(
      name="unique-key-1",
      columns={"a", "b"},
      options={"where": "b IS NOT NULL"}
   ),
 @ORM\UniqueConstraint(
      name="unique-key-2",
      columns={"a", "c"},
      options={"where": "c IS NOT NULL"}
   )

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

Другие вопросы по тегам