【问题标题】:How to enforce foreign key constraint from unrelated tables in Mysql?如何从 Mysql 中不相关的表中强制执行外键约束?
【发布时间】:2013-06-19 16:43:21
【问题描述】:

这是我的数据库结构。

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

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

我输入了以下数据

用户组

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

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

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

无效

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

如何防止插入此类数据?

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

我可以在数据库级别强制执行此操作吗,因为我也从后端进行了一些导入而不使用 PHP 前端。

【问题讨论】:

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


    【解决方案1】:

    使用识别关系,类似这样:

    请注意 UserGroup PK 如何从该“菱形”的顶部迁移到“两侧”并在“底部”合并。由于底部的一行只包含一个标识顶部的字段,因此不能与顶部的多行相关。

    如果您需要其他密钥用于其他目的和/或使上述密钥交替使用(即唯一约束),您仍然可以保留其他密钥...


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

    【讨论】:

      【解决方案2】:

      旁注:我相信您在问题中提供了太多细节,所以如果我误解了,我深表歉意。

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

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-07
        • 2022-01-08
        • 2012-04-04
        • 1970-01-01
        • 2013-11-22
        • 2019-01-09
        • 2011-10-29
        相关资源
        最近更新 更多