【问题标题】:Mysql : Association tableMysql:关联表
【发布时间】:2014-12-11 10:52:22
【问题描述】:

使用 mySQL,我有这些表:

Person
----------
id (PK)
name
...


Person_Association
----------
id_Person1  (FK Person.id)
id_Person2  (FK Person.id)

我希望每个 Person_Association 都是唯一的:如果 (#1, #2) 存在,则 (#1, #2) 和 (#2, #1) 都不能插入。

为此,我向 Person_Association 添加了一个字段和一个触发器,如下所示:

Person_Association
----------
id_Person1  (FK Person.id)
id_Person2  (FK Person.id)
unique_id   (PK)


CREATE TRIGGER `Person_Association_BINS` BEFORE INSERT ON `Person_Association` FOR EACH ROW
BEGIN
  IF (new.id_Person1 < new.id_Person2) THEN
    SET new.unique_id = CONCAT(new.id_Person1, '-', new.id_Person2);
  ELSE
    SET new.unique_id = CONCAT(new.id_Person2, '-', new.id_Person1);
  END IF;
END

它有效,但有更好的方法吗?

【问题讨论】:

    标签: mysql model-associations


    【解决方案1】:

    你最好扔掉触发器并在(id_Person1, id_Person2)上拥有一个唯一索引。
    其实你也可以扔掉不必要的unique_id,把(id_Person1, id_Person2)作为主键。

    然后你像这样插入:

    INSERT INTO your_table VALUES (LEAST($value1, $value2), GREATEST($value1, $value2));
    

    INSERT INTO your_table SELECT LEAST($value1, $value2), GREATEST($value1, $value2);
    

    编辑:如果你真的坚持“SQL 来确保(不是应用程序层)”,我会这样写(但仍然删除你的 unique_id 列并在(id_Person1, id_Person2) 上设置唯一索引):

    DELIMITER $$
    CREATE TRIGGER `Person_Association_BINS` BEFORE INSERT ON `Person_Association` FOR EACH ROW
    BEGIN
      IF EXISTS(SELECT 1 FROM `Person_Association` WHERE id_Person1 = LEAST(NEW.id_Person1, NEW.id_Person2) AND id_Person2 = GREATEST(NEW.id_Person1, NEW.id_Person2)) THEN
      SIGNAL SQLSTATE '23000' SET MESSAGE_TEXT='dup key error';
      END IF;
    END $$
    DELIMITER ;
    

    我仍然希望表上没有触发器(从数据库管理员的角度来看,它们不仅经常引起混乱,而且在执行管理员任务时也往往会妨碍)。因此,为了追求我的第一种解决方法,您还可以创建一个存储过程来为您执行此操作:

    CREATE PROCEDURE insert_p_a(IN p_id1 INT, IN p_id2 INT)
    INSERT INTO your_table SELECT LEAST(p_id1, p_id2), GREATEST(p_id1, p_id2);
    

    在您的应用程序层中,您只需这样做

    CALL insert_p_a($value1, $value2);
    
    • 阅读更多关于信号的信息here
    • here是我选择23000作为sqlstate的原因(其实没关系)

    【讨论】:

    • 实际上,我希望 SQL 来确保这一点(而不是应用层)。
    • @Nicolas 编辑了我的答案
    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 2021-09-23
    • 1970-01-01
    • 2021-11-06
    相关资源
    最近更新 更多