40

I'm creating a link table which has 3 columns; id, product_id, tournament_id.

Adding a uniqueConstraint to the "id" column is trivial, but I want to ensure that any pair of (product_id, tournament_id) is unique.

The example at Liquibase.org shows

<changeSet author="liquibase-docs" id="addUniqueConstraint-example">
<addUniqueConstraint catalogName="cat"
        columnNames="id, name"
        constraintName="const_name"
        deferrable="true"
        disabled="true"
        initiallyDeferred="true"
        schemaName="public"
        tableName="person"
        tablespace="A String"/>
</changeSet>

but is it possible to accomplish this within a <createTable> block?

Also, just to confirm; does this create a composite unique constraint on the two columns, or does it create two separate unique constraints?

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Alec
  • 1,986
  • 4
  • 23
  • 47

3 Answers3

37

You can read liquibase manual also similar problem you can find here

In your case it should be:

<changeSet author="liquibase-docs" id="addUniqueConstraint-example">
<addUniqueConstraint
        columnNames="product_id, tournament_id"
        constraintName="your_constraint_name"
        tableName="person"
        />
</changeSet>
ciostek223
  • 534
  • 5
  • 6
28

I am pretty certain that:

  1. You can't do it inside the createTable tag itself, but you can do it within the same changeset as when the table is created.
  2. It does create a composite unique constraint on the two columns. One way you can check is to run liquibase with the command to generate the SQL for update rather than running the update command and check what it does for your database. On the command line, rather than running liquibase update you would run liquibase updateSQL.
SteveDonie
  • 8,700
  • 3
  • 43
  • 43
7

In case people like myself are still asking themselves this question years later: (by now) it is possible to do this within the createTable tag itself if you provide the same name for the constraint:

<changeSet id="composite-unique-example" author="composite-unique-example">
  <createTable tableName="example">
    <column name="foo" type="bigint">
      <constraints unique="true" uniqueConstraintName="foo-bar_unique"/>
    </column>
    <column name="bar" type="bigint">
      <constraints unique="true" uniqueConstraintName="foo-bar_unique"/>
    </column>
  </createTable>
</changeSet>

Running Liquibase 4.5.0 and MySQL 5.7:

mysql> insert into example (foo, bar) values (1, 2), (2, 1), (1, 3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from example;
+------+------+
| foo  | bar  |
+------+------+
|    1 |    2 |
|    1 |    3 |
|    2 |    1 |
+------+------+
3 rows in set (0.00 sec)

mysql> insert into example (foo, bar) values (1, 2);
ERROR 1062 (23000): Duplicate entry '1-2' for key 'foo-bar_unique'
pbr
  • 71
  • 1
  • 1
  • This solution works and, in my opinion, is the healthiest solution ✅ Otherwise, we would have to create a constraint outside the table, which is very unhealthy. Having the same constraint names and defining a unique constraint in this way is quite readable and practical. – agitrubard Apr 14 '23 at 16:18