【问题标题】:How to enforce a unique combination of two similar fields in MySQL如何在 MySQL 中强制两个相似字段的唯一组合
【发布时间】:2011-07-20 19:20:58
【问题描述】:

我有一组由 id 定义的点,以及一个定义这些点之间的连接的数据库表:

[点1,点2]

现在我可以强制 point1 和 point2 的排列是唯一的。所以只有 1 个条目 point1 = xpoint2 = y。但我想要独特的组合,这意味着如果有一个带有 point1 = xpoint2 = y 的条目,则应该不可能获得带有 point1 的条目= ypoint2 = x.

是否可以为此配置表,还是我必须通过代码强制执行?

【问题讨论】:

  • (x,y) 和 (y,x) 有什么区别?
  • 你在使用auto increment吗?在表格字段中还是这些随机值?
  • @Vaughn:点 ID 在另一个表中定义,并且是自动递增的。点 1 != 点 2。
  • @AJ:有一个苹果和一个梨意味着我也有一个梨和一个苹果。
  • @Clavus - 我不明白你的水果类比。 (x,y) 是指笛卡尔平面上的特定坐标。请注意,仅当 (IFF) x=y 时,(x,y) 才等于 (y,x)。

标签: mysql field


【解决方案1】:

这个结构应该适合你吗?

正确

--
-- Table structure for table `points`
--

CREATE TABLE IF NOT EXISTS `points` (
  `point1` int(11) NOT NULL,
  `point2` int(11) NOT NULL,
  UNIQUE KEY `point1_point2_ux` (`point1`,`point2`),
  UNIQUE KEY `point2_point1_ux` (`point2`,`point1`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Triggers `points`
--
DROP TRIGGER IF EXISTS `testpoints`;
DELIMITER //
CREATE TRIGGER `testpoints` BEFORE INSERT ON `points`
 FOR EACH ROW BEGIN
  DECLARE num INTEGER DEFAULT 0;
  DECLARE point INTEGER DEFAULT NULL;

  SELECT count(*) INTO num FROM points WHERE point2 = NEW.point1 AND point1 = NEW.point2;

  IF(num>0) THEN
    SET point = NEW.point1;
    SET NEW.point1 = NEW.point2;
    SET NEW.point2 = point;
  END IF;

  END
//
DELIMITER ;

【讨论】:

  • 这不会阻止 (x,y) = (y,x) 条件。
【解决方案2】:

我会结合

  1. (point1, point2) 上的唯一索引
  2. 强制执行point1 <= point2 的触发器(即,如果违反该条件,则反转触发器中的两个值)。

【讨论】:

  • 嗯,阅读 MySQL 触发器。似乎是我正在寻找的:)
【解决方案3】:

我建议像

这样搜索那个组合

SELECT id WHERE pointx = 'value' AND pointy = 'value'; 寻找那个组合。

$numrows = mysql_num_rows($result);

if($numrows !> 0){ //do what ever with the points. }

【讨论】:

    【解决方案4】:

    这个触发器可以完成这项工作:

    DELIMITER $$
    
    CREATE
        TRIGGER `db`.`on_points_before_insert` BEFORE INSERT
        ON `db`.`points`
        FOR EACH ROW BEGIN
        DECLARE num_reg INT;
    
        SELECT COUNT(*) FROM points WHERE 
        (p1 = new.p1 AND p2 = new.p2) OR (p1 = new.p2 AND p2 = new.p1)  INTO num_reg;
        IF(num_reg != 0) THEN
            CALL my_non_existant_procedure();
        END IF;
        END$$
    
    DELIMITER ;
    

    我只是通过计算条件 (p1 = new.p1 AND p2 = new.p2) OR (p1 = new.p2 AND p2 = new.p1) 返回的记录数来测试您是否尝试插入的值的组合,如果该数字不同于 0,我将调用一个不存在的过程使触发器失败,避免插入新记录。

    【讨论】:

      猜你喜欢
      • 2015-01-11
      • 2014-06-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-12
      • 2012-12-22
      • 1970-01-01
      • 2021-07-15
      相关资源
      最近更新 更多