如何在 MySQL 中强制执行两个相似字段的唯一组合

发布于 2024-11-25 01:59:16 字数 339 浏览 2 评论 0原文

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

[point1, point2]

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

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

I have a set of points, defined by an id, and a database table which defines a connection between those points:

[point1, point2]

Now I can enforce that permutations of point1 and point2 are unique. So there's only 1 entry where point1 = x and point2 = y. But I want unique combinations, meaning that if there's a entry with point1 = x and point2 = y, it shouldn't be possible to get an entry with point1 = y and point2 = x.

Is it possible to configure the table for this or do I have to enforce this through code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

2024-12-02 01:59:16

这个结构也许适合你?

正确

--
-- 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 ;

This structure should work for you maybe?

CORRECT

--
-- 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 ;
溺渁∝ 2024-12-02 01:59:16

我将通过结合

  1. (point1, point2) 上的唯一索引
  2. 来实现此目的,触发器强制执行 point1 <= point2 (即反转如果违反该条件则触发)。

I'd approach this with a combination of

  1. a unique index on (point1, point2)
  2. a trigger to enforce point1 <= point2 (i.e., reverse the two values in the trigger if they violate that condition).
等风来 2024-12-02 01:59:16

我建议搜索该组合,例如

SELECT id WHERE pointx = 'value' AND pointy = 'value'; 查找该组合。

$numrows = mysql_num_rows($result);

if($numrows !> 0){
//用这些点做任何事情。
}

I would suggest search for that combo like

SELECT id WHERE pointx = 'value' AND pointy = 'value'; look for that combo.

$numrows = mysql_num_rows($result);

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

和我恋爱吧 2024-12-02 01:59:16

此触发器将完成这项工作:

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,我将调用一个不存在的过程以使触发器失败并避免插入新记录。

This trigger will do the job:

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 ;

I just test if there's a combination of the values you're trying to insert by counting the number of records that are returned by the condition (p1 = new.p1 AND p2 = new.p2) OR (p1 = new.p2 AND p2 = new.p1), and if that number is different from 0 I call a non-existant procedure to make the trigger fail and avoid the insertion of the new record.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文