Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ORM UniqueConstraint, null value duplicate

I have an entity with an unique constraint on 3 fiels.

2 fields are not nullable, and the third is nullable.

My problem, when the third field is null, the unique constraint doesn't work, so i can have in my database some duplicate values like (5,1,null)(5,1,null)

For me, (5,1,null) is an unique value, with null too.

Do you have any ideas ?

This is my ORM line :

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

Edit : The nullable value is a foreign key to an other entity, so i can't put a custom value. It's an entity or null.

like image 281
Clément Andraud Avatar asked Apr 02 '14 10:04

Clément Andraud


People also ask

IS null allowed in unique constraint?

You can insert NULL values into columns with the UNIQUE constraint because NULL is the absence of a value, so it is never equal to other NULL values and not considered a duplicate value.

Does unique index allow null?

Therefore, unique indexes do not enforce primary key constraints by themselves because they allow null values.

Can Unique Key accept multiple null values?

Remember, you cannot add more than one null value to a unique key column since the second null value will be the duplicate of the first one – and duplicates are not allowed.

Does primary key allow null values?

Primary key constraintsNULL values are not allowed. If the column(s) contain NULL values, the system will not add the primary key constraint. See ALTER TABLE statement for more information.


1 Answers

This could be achieved using two partial indexes. But doctrine annotations is not enough. We should add some SQL to solve the issue.

NOTE! I'm using PostgreSQL and migrations in my project.

First create 2 unique indexes (I use YAML):

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

Then generate migration class using console:

php app/console doctrine:migrations:diff

SQL will be generated, but must be modified a little bit (WHERE clauses added)

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)
    {
        // ...
    }
}

Execute generated SQL (migrate):

php app/console doctrine:migrations:migrate -n

Done!

like image 131
Jekis Avatar answered Oct 14 '22 02:10

Jekis