可交换列的{s}主键

时间:2017-03-07 18:29:22

标签: mysql sql

这是我试图实现的目标:

我有一个表fabric包含用于构建产品的结构。当管理员记录新结构时,他可以定义是否可以使用另一个结构选择此结构(用于材料的兼容性)。

这种排斥关系是可交换的。如果X不与Y一起使用,则意味着Y不能与X一起使用。

为了实现这一点,我创建了一个表fabric_exclusion,其中包含两个字段(id_fabric1id_fabric2),形成一个主键。

但是如何让CRUD操作使用这个底层逻辑(id_fabric1=X|id_fabric2=Y) = (id_fabric1=Y|id_fabric2=X)

更新:以下是我的尝试:

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;

2 个答案:

答案 0 :(得分:1)

可能有点开销,但您可以在计算字段上使用基于id_fabric1id_fabric2的计算字段以及唯一约束(甚至是主键)。因此,确保例如,如果存在元组(4,3)则不能插入元组(3,4),反之亦然:

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'

答案 1 :(得分:1)

我知道我可能已经迟到了。当我摸不着头脑时,我找到了一个可行的解决方案来强制执行此操作。

通常,当你有这样一个交换对时,顺序并不重要。

我开始添加一个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;

有了这个,你总是按顺序插入,永远不必违反它。因为,它基本上将较小的一个分配给一个字段,而将较大的一个分配给另一个字段。由于它们可以保证在每一行中调用,因此您几乎可以确定完整性约束,但需要一些开销。但是,我发现另一个有趣的方法是通过配对功能再次以相同的方式,但是对于交换性,我会说,我会使用无序的配对函数,但它们不像这些那样具有空间效率。