2

我有下表将存储文件(图像、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。

4

2 回答 2

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 的情况下使用我的解决方案,将来会出现什么问题?

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

另一方面,如果给定文件既涉及订单又涉及付款,您可能希望允许这种灵活性。如果您无法维护多个引用,则必须复制此类文件以允许它们属于多个类别。

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

于 2012-11-24T20:50:14.457 回答
1

首先:如果表之间存在多对一关系,则不要在order_id. 我会将所有文件放入一个表 ( tbl_file) 中并向表中添加两个外键字段:order_idand payment_id,这将引用paymentororder表中的相应条目。

所以一个条目(如果一笔付款有多个文件)看起来像:

id  payment_id  order_id    size    name        type        content     date_time
1   1           null        434     File.txt    text/plain  <blob>      24.11.2012
2   1           null        131     File2.txt   text/plain  <blob>      24.11.2012
于 2012-11-24T20:40:27.727 回答