数据库设计 - 从多个表中多次引用表

问题描述 投票:0回答:2

您好stackoverflow数据库设计专家!

我在我的数据库中遇到了设计问题,我在Stackoverflow中没有发现任何类似的问题,因此这个问题。

我有一个图像表,包含图像数据和它的主键。在我的设计中,每个图像可以在多个表中多次引用。

以下是数据库的表示:

 --------------------    -------------------------------------------
| image              |  | table1                                    |
|--------------------|  |-------------------------------------------|
| id_image | data    |  | id_table1 | id_image | data               |
|----------|---------|  |-----------|----------|--------------------|
| 1        | Image 1 |  | 1         | 1        | References image 1 |
| 2        | Image 2 |  | 2         | 3        | References image 3 |
| 3        | Image 3 |   -------------------------------------------
 --------------------
 -------------------------------------------
| table2                                    |
|-------------------------------------------|
| id_table2 | id_image | data               |
|-----------|----------|--------------------|
| 1         | 2        | References image 2 |
| 2         | 2        | References image 2 |
| 3         | 3        | References image 3 |
 -------------------------------------------

这是表格详细信息:

  • 图像表 id_image自动递增的主键 数据图像数据
  • table1表 id_table1自动递增的主键 id_image外键引用image.id_image 数据表1数据
  • table2表 id_table2自动递增的主键 id_image外键引用image.id_image 数据表2数据

我希望我的数据库行为如下:

  • 如果我用table1删除id_table1 = 1行,则必须删除带有id_image = 1的图像行(没有其他对此图像的引用)
  • 如果我然后用table2删除id_table2 = 1行,则不应删除任何图像(因为带有id_image = 2的图像仍被table2行引用id_table2 = 2
  • 如果我然后用table2删除id_table2 = 2行,则必须删除带有id_image = 2的图像行(没有其他对此图像的引用)
  • 如果我然后用table1删除id_table1 = 2行,则不应删除任何图像(因为带有id_image = 3的图像仍被table2行引用id_table2 = 3
  • 如果我然后用table2删除id_table2 = 3行,则必须删除带有id_image = 3的图像行(没有其他对此图像的引用)

我已经尝试了一些级联删除,通过反转外键(即包含imageid_table1外键的id_table2表),但如果在其他2个表中引用了一个图像,删除一个引用的表条目也会删除图像,我这样做不想发生。

我也尝试定义触发器,但这种方法比我想象的更复杂:每次我必须检查id_image的所有外键,看看是否有另一个要删除的图像引用。这个示例包含2个外键,但在我设计的数据库中将有超过10个...

我觉得这个简单的问题有一个简单的解决方案,有人在这帮助我吗?

谢谢!

sql-server database database-design triggers foreign-keys
2个回答
0
投票

马上因为你的第一个要求:

如果我删除id_table1 = 1的table1行,则必须删除id_image = 1的图像行(没有其他对此图像的引用)

我可以告诉你,你只能用TRIGGER完成这个任务。原因是,当您从Child表中删除行时,您希望从Parent表中自动删除。

反向(删除父项时删除子项)可以使用级联外键完成,但不能这样做。

您需要在两个子表上放置触发器以强制执行所需的逻辑。


0
投票

我昨天想出了一个更好的设计。它仍然使用触发器(如Tab Alleman said),但定义更简单:

 --------------------    ---------------------------
| image              |  | image_proxy               |
|--------------------|  |---------------------------|
| id_image | data    |  | id_image_proxy | id_image |
|----------|---------|  |----------------|----------|
| 1        | Image 1 |  | 1              | 1        |
| 2        | Image 2 |  | 2              | 3        |
| 3        | Image 3 |  | 3              | 2        |
 --------------------   | 4              | 2        |
                        | 5              | 3        |
                         ---------------------------

 -------------------------------------------------
| table1                                          |
|-------------------------------------------------|
| id_table1 | id_image_proxy | data               |
|-----------|----------------|--------------------|
| 1         | 1              | References image 1 |
| 3         | 2              | References image 3 |
 -------------------------------------------------

 -------------------------------------------------
| table2                                          |
|-------------------------------------------------|
| id_table2 | id_image_proxy | data               |
|-----------|----------------|--------------------|
| 1         | 3              | References image 2 |
| 2         | 4              | References image 2 |
| 3         | 5              | References image 3 |
 -------------------------------------------------

正如您在上面的架构中所看到的,我引入了一个新表:image_proxy

  • id_image_proxy自动递增的主键
  • id_image外键引用image.id_image

此外,table1table2现在引用image_proxy条目而不是image条目。

通过这种设计,触发器现在是:

  • 删除table1中的条目后,删除image_proxy中的相应条目。
  • 删除table2中的条目后,删除image_proxy中的相应条目。
  • 删除image_proxy中的条目后,删除image中未在image_proxy中引用的条目。

我不知道这个设计是否是这个问题的最佳选择,也不知道触发器使用是否安全,这就是为什么如果有更好的答案或相关评论,我会留意这篇文章!

© www.soinside.com 2019 - 2024. All rights reserved.