I'm trying to rewrite the Postgres schema to fit the MySQL (8.0.32) dialect. As you know, MySQL does not support partial indexes.
In the following case, there will only be an index that enforces unique data on customer_group.name
if deleted_at
is null.
This makes sense since there is no point in ensuring that deleted entries are unique. However, I don't understand how to implement the same constraints without partial indexing.
CREATE TABLE "customer_group" ( "id" integer NOT NULL AUTO_INCREMENT, "created_at" datetime NOT NULL DEFAULT NOW(), "updated_at" datetime NOT NULL DEFAULT NOW(), "deleted_at" datetime, "name" text NOT NULL, "metadata" text, CONSTRAINT "PK_142c3338-da81-4d0c-8cd8-490bb41cd187" PRIMARY KEY ("id") ); -- solve this -- ensure name is unique when one customer_group is not deleted CREATE UNIQUE INDEX "IDX_d12ecf48-302c-4292-8c8d-d2cc7c8149f9" ON "customer_group" ("name") WHERE "deleted_at" IS NULL;
P.S. I do use ANSI_QUOTES
.
Someone suggested that I try using a unique index on 2 columns instead of one. However, if the constraint is UNIQUE INDEX "IDX_d12ecf48-302c-4292-8c8d-d2cc7c8149f9" ON "customer_group" ("name", "deleted_at")
then I get the opposite result of what I want: deleted_at
is NULL, then name
can be repeated.
Using calculated columns, you can do the following:
With index:
P.S. I did not use ANSI_QUOTES.
See: DBFIDDLE
MySQL does not support partial indexes, but does support expression indexes (starting with MySQL 8.0). Here is a demo:
Because UNIQUE follows ANSI's NULL rules, if the second column of a unique index is NULL, there may be any number of duplicates in the first column. The second column when NULL is not equal to any other row, so it is always "unique".
So if the second column is a fixed non-NULL value only when "deleted_at" is NULL, then "name" is unique on all rows where "deleted_at" is NULL.
I had to change the type of "name" because you can't create an index on a TEXT column in MySQL and it might be too long for the 3072 byte limit of the index.
Also changed the PRIMARY KEY to omit the constraint name. MySQL will always name the primary key simply
PRIMARY
.