Reputation: 1242
Here is what I attempt to acheive :
I have one table fabric
containing fabrics to build a product. When the administrator record a new fabric he can define if this fabric can be selected with another one (for compatibility of materials).
This exclusion relationship is commutative. If X doesn't go with Y, it means that Y can't go with X.
To implement that I created a table fabric_exclusion
with two fields (id_fabric1
and id_fabric2
) forming a primary key.
But how can I have CRUD operations working with this underlaying logic (id_fabric1=X|id_fabric2=Y) = (id_fabric1=Y|id_fabric2=X)
?
UPDATE: Here is what I already tried :
CREATE TABLE IF NOT EXISTS `PREFIX_fabric_exclusion` (
`id_fabric1` INT(10) NOT NULL,
`id_fabric2` INT(10) NOT NULL,
CONSTRAINT `ids` UNIQUE (`id_fabric1`, `id_fabric2`),
PRIMARY KEY `ids`
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Upvotes: 0
Views: 171
Reputation: 542
I know I am probably late, And as I scratched my head through this, I found one viable solution to enforce this.
Usually, when you have such a commutative pair, the order doesn't really matter.
I started adding a BEFORE INSERT TRIGGER.
CREATE TRIGGER `tbl_BEFORE_INSERT` BEFORE INSERT ON `thread` FOR EACH ROW
BEGIN
SET @l = least(new.id1, new.id2);
SET @l2 = greatest(new.id1, new.id2);
SET new.id1 = @l;
SET new.id2 = @m;
END;
With this, you always insert in order and never have to violate it. Because, it essentially assigns the smaller one to one field, and the larger one to another. Since they're guaranteed to call in each row, you're almost as sure as an integrity constraint, but with some overhead. But, another interesting way I found is by having a pairing function, again, in the same way, but for commutativeness, I would say, I would use an unordered pairing function, but they're not as space efficient as these.
Upvotes: 1
Reputation: 35154
Probably a little overhead, but you could use a calculated field based on id_fabric1
combined with id_fabric2
and a unique constraint (or even a primary key) on the calculated field. Thereby, it is ensured that, for example, a tuple (4,3)
cannot be inserted if a tuple (3,4)
exists and vice versa:
CREATE TABLE `PREFIX_fabric_exclusion` (
`id_fabric1` INT(10) NOT NULL,
`id_fabric2` INT(10) NOT NULL,
combinedKey int(21) as (if (id_fabric1 < id_fabric2, id_fabric1*100000000+ id_fabric2, id_fabric2*100000000+id_fabric1)) stored primary key
)
insert into PREFIX_fabric_exclusion(id_fabric1, id_fabric2) values (3, 4);
insert into PREFIX_fabric_exclusion(id_fabric1, id_fabric2) values (4, 3); # Error: Duplicate entry '300000004' for key 'PRIMARY'
Upvotes: 1