I\'m trying to create a relation where any of four different parts may be included, but any collection of the same parts should be handled as unique.
Example: An ass
I see that this was asked in 2009. However it is often requested from MySQL: https://bugs.mysql.com/bug.php?id=8173 and https://bugs.mysql.com/bug.php?id=17825 for example. People can click on affects me to try and get attention from MySQL.
Since MySQL 5.7 we can now use the following workaround:
ALTER TABLE test
ADD generatedLocationID INT AS (ifNull(locationID, 0)) NOT NULL,
ADD generatedWorkgroupID INT AS (ifNull(workgroupID, 0)) NOT NULL,
ADD generatedProgramID INT AS (ifNull(programID, 0)) NOT NULL,
ADD UNIQUE INDEX (companyID, generatedLocationID, generatedWorkgroupID, generatedProgramID);
The generated columns are virtual generated columns, so they have no storage space. When a user inserts (or updates) then the unique index cause the value of the generated columns to be generated on the fly which is a very quick operation.
The only way I can think of handling this without additional triggers/programming would be to have a single "None of the Above" value in each of the referenced tables, so that your test would look like
INSERT INTO test VALUES (1, NO_LOCATION, NO_WORKGROUP, NO_PROGRAM),
(1, NO_LOCATION, NO_WORKGROUP, NO_PROGRAM)
Where the NO_*
identifiers are the right type/length for your ID columns. This would then fail, as you'd expect it.
In MySQL NULL != NULL, or anything. So that is what the UNIQUE doesn't work. You should use another default value for blanks, like zero
I think it's important to note that there is a proper way for NULL values to be interpreted and handled, and the behavior exhibited by the OP is exactly what's intended. You can disregard that behavior, and you can handle your query any way you want without objection from me, but it might be well to "Accept" an answer that describes some form of Best Practices, rather than a non-standard personal preference.
Or if you don't agree with the consensus Best Practice, you can just not Accept any answer.
It's not a race to get an answer accepted as quickly as possible. Deliberation and collaboration are also intended to be part of the process, I think.
This is a Feature (though not what I expected, either).
This thread suggests making your key a Primary key to get the behavior you expected:
This is a feature - a NULL value is an undefined value, therefore two NULL values are not the same. Can be a little confusing but makes sense when you think about it.
A UNIQUE index does ensure that non-NULL values are unique; you could specify that your column not accept NULL values.