【问题标题】:Constraints for foreign keys like this in associative table?关联表中这样的外键约束?
【发布时间】:2016-02-04 07:53:57
【问题描述】:

有A、B、C三个表,表A、B的src列是外键。 Table 是 A.ID 和 B.ID 的关联表。

mysql 中是否有任何约束以确保插入到表 C 中的每一行都必须遵循约束:A.src 的 ID 等于 B.src

例如在下面的表C中,row 1 7是允许的,因为A.ID和B.ID的SRC都是35,但是row 2 7是非法的,因为A.ID的SRC是46但是B.ID 为 35。

Table A
ID  SRC
1   35
2   46
3   46

Table B
ID  SRC
6   46
7   35
8   46

Table C
A_ID    B_ID
1   7
3   6

是否可以设置任何约束或机制来确保插入到表 C 中的每一行都遵循常规?

谢谢。

【问题讨论】:

  • Oracle、MySQL 和 RDB,这是一个非常罕见的组合......你真的在使用所有这些产品吗?
  • 我认为这并不罕见,我现在使用mysql,之前使用过Oracle,我也有兴趣是否在其他Relation-Database中有约束。
  • 不要只在不直接涉及的情况下标记产品...标记您正在使用的 dbms 产品以面对问题。您可能已经注意到 MySQL 的约束处理与 Oracle 的有点不同...
  • 是的,你是对的,mysql是专注的,我知道dbms之间的约束是不同的。谢谢你的建议。
  • 我还是不明白,你说table c 必须遵循约束:A.src 等于 B.src 的 ID。 但对你来说也是说row 2 7 是非法的,因为A.ID 的SRC 是46,而B.ID 的SRC 是35。 如果你看到row 3 6 都具有相同的SRC,那就是意思是在table C 中应该有row 3 8row 2 6row 2 8,对吧?

标签: mysql sql oracle


【解决方案1】:

您可以在 Oracle 中使用物化视图执行此操作:

Oracle 设置

CREATE TABLE A (
  ID NUMBER PRIMARY KEY,
  SRC NUMBER
);

CREATE TABLE B (
  ID NUMBER PRIMARY KEY,
  SRC NUMBER
);

CREATE MATERIALIZED VIEW LOG ON A
   WITH SEQUENCE, ROWID(id, src)
   INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON B
   WITH SEQUENCE, ROWID(id, src)
   INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW AB_MV
   BUILD IMMEDIATE
   REFRESH FAST ON COMMIT
   AS SELECT a.id, b.id 
      FROM   a, b
      WHERE  a.src = b.src
      GROUP BY A.id, B.id;


ALTER TABLE AB_MV ADD CONSTRAINT AB_MV__A__B__PK PRIMARY KEY (A_ID, B_ID );

CREATE TABLE C (
  A_ID NUMBER REFERENCES A( ID ),
  B_ID NUMBER REFERENCES B( ID ),
  PRIMARY KEY ( A_ID, B_ID ),
  FOREIGN KEY ( A_ID, B_ID ) REFERENCES AB_MV ( A_ID, B_ID )
);

插入数据

INSERT INTO A
SELECT 1, 35 FROM DUAL UNION ALL
SELECT 2, 46 FROM DUAL UNION ALL
SELECT 3, 46 FROM DUAL;

INSERT INTO B
SELECT 7, 35 FROM DUAL UNION ALL
SELECT 6, 46 FROM DUAL UNION ALL
SELECT 8, 46 FROM DUAL;

SELECT * FROM AB_MV;
-- Will return zero rows as there has not been a commit.

COMMIT;

SELECT * FROM AB_MV;
-- Will return 5 rows.

INSERT INTO C VALUES ( 1, 7 );
-- 1 row inserted

INSERT INTO C VALUES ( 2, 7 );
-- Fails with ORA-02291: Integrity constraint violated - parent key not found.

您可能可以在 MySQL 中使用触发器来执行类似的操作来填充 AB_MV 表(使用 MERGE INTO 来强制唯一性) - 尽管从 AB 删除行的触发器可能很有趣,因为ID 对可以来自多个 SRC 值。

【讨论】:

    【解决方案2】:

    我不确定,但我试过了

    INSERT INTO table_c
    (SELECT
       a.ID,
       b.ID
     FROM
       table_a AS a INNER JOIN table_b AS b ON a.SRC = b.SRC
    );
    

    This 为我工作,将 ID 从 table_a 和 table_b 插入到 table_c

    【讨论】:

    • 虽然这会获取可接受的值并将它们插入表中,但它完全忽略了问题的重点,因为它没有强制 only 值与可接受的匹配允许在 ab 与相同的 src 两个表中配对。
    • @MT0 正如 MTO@所说,“它并不强制只允许与表 a 和 b 中具有相同 src 的可接受对匹配的值”。
    • @JTR 实际上,如果所有可用对都已签入,表 C 几乎没有意义,因为我可以通过 A join B 作为您的答案轻松获得它,对吧?
    • @jjs 是的,我是这么认为的。我的错,对不起,请忽略这个答案 XD
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 2011-02-24
    • 2020-03-17
    • 1970-01-01
    相关资源
    最近更新 更多