【问题标题】:Is there such a thing as a reverse foreign key?有没有反向外键之类的东西?
【发布时间】:2011-09-23 10:27:04
【问题描述】:

在 MySQL 中,有没有办法指定 a.column 不能存在于 b.column 中 - 反向外键?

换句话说:

# Would not return any rows ever
SELECT * FROM a
INNER JOIN b ON a.column = b.column;

# Would fail
INSERT INTO a
SELECT * FROM b;

# Would not insert any rows
INSERT IGNORE INTO a
SELECT * FROM b;

【问题讨论】:

  • 您想要“可以在 A 或 B 中,但不能同时在两者中”?

标签: mysql foreign-keys theory


【解决方案1】:

不,没有这样的东西。

您需要在触发器中执行此操作:

DELIMITER $$

CREATE TRIGGER bi_a_each BEFORE INSERT ON a FOR EACH ROW
BEGIN
  DECLARE forbidden_key INTEGER;
  SELECT id INTO forbidden_key FROM b WHERE b.id = NEW.acolumn LIMIT 1;
  IF forbidden_key IS NOT NULL THEN 
    SELECT * FROM error_insertion_of_this_value_is_not_allowed;
  END IF;
END $$

DELIMITER ;

【讨论】:

    【解决方案2】:

    在某种程度上,如果你想“可以在 A 或 B,但不能同时在两者中”

    这是“超级键/子类型”模式

    创建一个有 2 列的新表 AB

    • SomeUniqueValue,PK
    • WhichChild char(1),仅限于 'a' 或 'b'

    两列也有唯一约束

    然后

    • 向表 A 和 B 添加一个 WhichChild 列。在 A 中,它始终为“a”。在 B 中,总是'b'
    • 两列上添加从 A 到 AB 和 B 到 AB 的外键

    现在,SomeUniqueValue 只能在 A 或 B 中。

    注意:在适当的 RDBMS 中,您可以根据需要使用检查约束或计算列将 WhoChild 限制为“a”或“b”。但是 MySQL 是有限的,所以你需要在 MySQL 中使用触发器。但是,这比为 A 中的每个插入测试表 B 等更简单

    【讨论】:

    • 非常有趣的方法!我假设必须使用 ON INSERT 触发器将 A 或 B 中的值放入 AB 中?
    • 您不必使用触发器来保证WhichChild 始终具有正确的字符。您可以对单行表使用外键约束。 (每个子类型表都有自己的单行表。)一种用法的代码:stackoverflow.com/questions/4969133/database-design-problem/…
    • @gbn:对。我在另一个 SO 问题中发布的代码是针对 PostgreSQL 的;它使用 CHECK 约束。
    【解决方案3】:

    尝试创建触发器并从中引发错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      相关资源
      最近更新 更多