链接MySQL中的2个ID

时间:2012-02-01 12:54:20

标签: php mysql mysql5

我有这张桌子

CREATE TABLE IF NOT EXISTS `links` (
  `link_id` int(20) NOT NULL AUTO_INCREMENT,
  `item1_id` int(20) NOT NULL,
  `item2_id` int(20) NOT NULL,
  PRIMARY KEY (`link_id`),
  UNIQUE KEY `item_id` (`item1_id`,`item2_id`)
) ENGINE=InnoDB;

如何限制它,以便the item_id只能在item1_iditem2_id

中出现一次

因为我希望一个项目只链接到另一个项目..

4 个答案:

答案 0 :(得分:5)

  

我想要一个项目只链接到另一个项目

这意味着您不需要链接表。您只需在Item表中使用linkedItemId列,并在其上添加唯一约束。一旦Item2链接到Item1(Item1ID在Item2行的linkedItemId中),那么其他任何东西都不能链接到Item1。

此外,链接表不需要自己的代理键

编辑,请注意MySQL允许在唯一索引中使用多个NULL(与SQL Server不同,在SQL Server中,您使用过滤的唯一索引来忽略NULL)

来自MySQL 5.5 CREATE INDEX

  

对于所有引擎,UNIQUE索引允许可以包含NULL的列的多个NULL值

答案 1 :(得分:1)

我不认为INNODB可以强制执行这样的约束(或MyIsam)。我的建议是创建一个存储过程来处理插入。首先检查您的自定义约束需求,然后如果没有冲突则照常插入。

答案 2 :(得分:1)

您可以将UNIQUE KEY缩小为仅item1_id。这意味着该表定义了1:1关系,而不是1:n关系。此外,您可以删除auto_increment主键,这些“链接”表中不需要它:

CREATE TABLE IF NOT EXISTS links (
   item1_id int(20) NOT NULL,
   item2_id int(20) NOT NULL,
  PRIMARY KEY (item1_id),
  FOREIGN KEY (item1_id)                 --- I assume you have these 2
    REFERENCES item (item_id),           --- Foreign Keys, too
  FOREIGN KEY (item2_id)
    REFERENCES item (item_id)
) ENGINE=InnoDB;

这和@ gbn的答案之间的区别在于,这不允许Null,并且不需要任何存储未链接的项目。两种设计的工作方式几乎相同,只需对插入/删除/更新语句进行少量修改即可。

在这两种设计中,我们可以将以下情侣联系起来:(1 -> 2)(2 -> 3)(3 -> 7)。如果符合要求的规格,两种设计都可以。


但是,如果我们只希望项目只出现在链接的任何一侧的一对链接中,则实现起来比较困难。

一种方法是确保links表中的所有插入都是通过插入(1, 2)(2, 1)对或失败的过程完成的(对于删除/更新类似)必须处理2行的语句。

其他更复杂的方法涉及触发器(或异常结构,如索引视图,MySQL中不可用)。

如果你想要一个标准化的设计,也有这种方法(复杂但没有触发器):

CREATE TABLE IF NOT EXISTS link_help (
   item1_id int(20) NOT NULL,
   item2_id int(20) NOT NULL,
  PRIMARY KEY (item1_id),
  FOREIGN KEY (item1_id) 
    REFERENCES item (item_id),  
  FOREIGN KEY (item2_id)
    REFERENCES item (item_id),
  UNIQUE KEY (item1_id, item2_id)          --- this will be needed below
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS links (
   item1_id int(20) NOT NULL,
   item2_id int(20) NOT NULL,
  PRIMARY KEY (item1_id),
  FOREIGN KEY (item1_id, item2_id) 
    REFERENCES link_help (item1_id, item2_id), 
  FOREIGN KEY (item2_id, item1_id)               --- notice the different 
    REFERENCES link_help (item1_id, item2_id)    --- order here
) ENGINE=InnoDB;

现在,您无法在(1 -> 2)表格中添加(2 -> 3)(3 -> 7)links行。

答案 3 :(得分:1)

......还有一个问题是链接是否有明确的方向 - 即A-B是否与B-A不同?

认为(你需要测试一下)你可以使用触发器处理这两种情况。但是我不知道任何可以用MySQL的过程语言显式抛出错误的方法。既然你已经指定列应该是NOT NULL而没有默认值,并假设NEW是可写的,那么....

CREATE TRIGGER ins_link BEFORE INSERT on links
FOR EACH ROW
BEGIN
  IF (NEW.item1_id = NEW.item2_id) THEN
      NEW.item2_id=NULL; /* subsequent INSERT will fail */
  END IF
  /* if you want AB=BA.... */
  IF (NEW.item1_id > NEW.item2_id) THEN
     @tempvar=NEW.item1_id;
     NEW.item1_id=NEW.item2_id;
     NEW.item2_id=@tempvar;
  END IF;
END;

(您可能还需要更新之前的触发器,但代码的其余部分相同)。