多个表使用多个联结表引用一个表

时间:2012-11-24 20:22:34

标签: mysql database file innodb junction

我有下表将存储文件(图像,PDF等)

CREATE TABLE `tbl_file` (
    `id` INT(10),
    `size` FLOAT,
    `name` VARCHAR(45),
    `type` VARCHAR(16),
    `content` BLOB,
    `date_time` TIMESTAMP,
    PRIMARY KEY (`id`) 
)

有许多表将有文件(tbl_order& tbl_payment),我想只使用一个表来存储文件(tbl_file)。但是,某些表可能每行有多个文件。

例如,一个订单(发票,采购订单,采购订单,合同)有多个文件,每笔付款可能有多个文件等。

所以我为每个可能有多个文件的表做了以下连接表(我没有包含外键代码)。

CREATE TABLE `tbl_order_file` (
    `order_id` INT(10),
    `file_id` INT(10),
    PRIMARY KEY (`order_id`, `file_id`),
)

CREATE TABLE `tbl_payment_file` (
    `payment_id` INT(10),
    `file_id` INT(10),
    PRIMARY KEY (`payment_id`, `file_id`),
)

这里的问题是,一个文件可以与两个表相关。也许这是一个优势,而不是一个问题,但我想知道是否有更好的方法来做到这一点或找到一种方法来限制文件,所以它只在一个表中引用。

我正在使用带有innodb引擎的MySQL。

2 个答案:

答案 0 :(得分:2)

声明约束以强制执行此操作的一种方法是确保将tbl_file中的每一行标记为文件类型,“O”或“P”(或将来的其他类型)。

CREATE TABLE `tbl_file` (
    `id` INT(10),
    `file_type` CHAR(1) NOT NULL,  -- must be 'O' or 'P'
    `size` FLOAT,
    `name` VARCHAR(45),
    `type` VARCHAR(16),
    `content` BLOB,
    `date_time` TIMESTAMP,
    PRIMARY KEY (`id`),
    UNIQUE KEY (`id`, `file_type`)
);

然后每个从属表强制其所有行标记相应的类型。因此,tbl_order_file中的一行可以引用tbl_file中仅具有相同file_type的 行:

CREATE TABLE `tbl_order_file` (
    `order_id` INT(10),
    `file_id` INT(10),
    `file_type` CHAR(1) NOT NULL, -- must be 'O'
    PRIMARY KEY (`order_id`, `file_id`),
    FOREIGN KEY (`file_id`, `file_type`) REFERENCES `tbl_file` (`id`, `file_type`)
);

同样对于tbl_payment_file:

CREATE TABLE `tbl_payment_file` (
    `payment_id` INT(10),
    `file_id` INT(10),
    `file_type` CHAR(1) NOT NULL, -- must be 'P'
    PRIMARY KEY (`payment_id`, `file_id`),
    FOREIGN KEY (`file_id`, `file_type`) REFERENCES `tbl_file` (`id`, `file_type`)
);

MySQL的一个难点特别是MySQL不支持CHECK约束以允许表定义限制file_type的值。您必须在触发器或应用程序代码中执行此操作。


重新评论:

  

假设我想在没有file_type的情况下使用我的解决方案,将来会出现什么问题?

好吧,正如您在原始问题中已经说过的那样,没有任何约束,没有什么能阻止文件表中的一行被多个联结表引用,并且您可能最终得到的数据对您的应用程序来说是异常的。

另一方面,如果给定文件同时涉及订单和付款,您可能希望允许这种灵活性。如果您无法维护多个引用,则必须制作此类文件的重复副本,以允许它们分为多个类别。

还有一个问题:这些解决方案都没有阻止您的应用在无子女的文件表中插入行;即没有来自任何联结表的引用的文件。

答案 1 :(得分:1)

首先:如果表之间存在多对一关系,则不要在order_id上创建主键。 我会将所有文件放入一个表(tbl_file)并向表中添加两个外键字段:order_idpayment_id,它们将引用{{1}中的相应条目}或payment表。

因此,一个条目(如果一个付款有多个文件)将显示如下:

order