如何在Mysql中从不相关的表强制执行外键约束?

时间:2013-06-22 18:35:15

标签: mysql database-design foreign-key-relationship data-integrity

这是我的数据库结构。 enter image description here

这是我用来创建表格的脚本

use for_stkoverflow;

CREATE TABLE UserGroup (
    groupid MEDIUMINT NOT NULL AUTO_INCREMENT,
    groupname VARCHAR(100),
PRIMARY KEY (`groupid`)
);

CREATE TABLE User_det (
    Usrid MEDIUMINT NOT NULL AUTO_INCREMENT,
    usrname VARCHAR(255),
    groupid MEDIUMINT,
PRIMARY KEY (`Usrid`),
    Foreign Key (groupid)
        references UserGroup (groupid)
);

CREATE TABLE Accounts (
    acid MEDIUMINT NOT NULL AUTO_INCREMENT,
    groupid MEDIUMINT,
acname VARCHAR(255),
PRIMARY KEY (`acid`),
    Foreign Key (groupid)
        references UserGroup (groupid)
);

create table Ledger (
    ledgerid MEDIUMINT NOT NULL AUTO_INCREMENT,
ledgername VARCHAR(255),
    acid mediumint,
Usrid mediumint,
PRIMARY KEY (ledgerid),
    Foreign Key (acid)
        references Accounts (acid),
Foreign Key (Usrid)
        references User_det (Usrid)
);

我输入了以下数据

enter image description here

用户组

----------
- groupid groupname
--------------------
- 1   Group1
- 2   Group2

User_det

--------
- Usrid usrname groupid
-----------------------
- 1     User1       1
- 2     User2       2

帐户

--------
- acid groupid acname
---------------------
- 1      1      ac1
- 2      2      ac2

分类帐

--------
-ledgerid ledgername acid Usrid
--------------------------------
- 1         ledger1 1   1
- 2         ledger2 2   2
- 3         ledger3 1   2
- 4         ledger4 2   1

SELECT t1.ledgerid, t1.ledgername,t2.acname,t3.usrname
  FROM Ledger AS t1 
INNER JOIN Accounts AS t2 ON t1.acid = t2.acid
Inner join User_det AS t3 ON t1.Usrid = t3.Usrid;

当前的表结构允许插入违反数据库完整性的数据。

  

条目分类帐3无效   ----------------------------------因为acname ac1属于user2不属于的group1。入口分类帐4是

     

无效

因为acname ac2属于user1不属于的group2。

如何防止插入此类数据?

现在在应用程序中我正在通过PHP在BL层中进行此检查。

我是否可以在数据库级别强制执行此操作,因为我在不使用PHP前端的情况下从支持中进行了一些导入。

2 个答案:

答案 0 :(得分:2)

使用识别关系,类似于:

enter image description here

注意UserGroup PK如何从这个“菱形”的顶部向下移动,在“两侧”向下移动并在“底部”合并。由于底部的行只包含一个标识顶部的字段,因此它与顶部的多行无关。

如果您将其他密钥用于其他目的和/或使密钥高于备用密钥(即UNIQUE约束),您仍然可以保留其他密钥...


顺便说一下,使用命名更一致 - 我建议总是使用带有未缩写表名的单数和前缀PK字段......

答案 1 :(得分:0)

旁注:我相信你在问题中提供了太多细节,所以如果我误解了它,我会道歉。

考虑到您使用的mysql没有可用于强制执行所需约束的物化视图,我看到两个选项。
首先,您可以使用trigger [s]和具有唯一约束的新表来模仿物化视图(它将起作用,但通常很难实现 - 您必须确保正确处理3个表上的所有INSERT / UPDATE / DELETE通过相应的触发器) 另一种方法是通过在groupId LedgerUsers)和userId, groupId({{1} Accounts上添加acid,groupId和“额外”唯一约束来对您的架构进行非规范化}}),并更改Ledger中的FK,因此它不是userId中的Users,而是userId,groupId而不是acid,而是{{} 1}}。

我希望有所帮助。