Sql server 数据库设计-从多个表多次引用一个表

Sql server 数据库设计-从多个表多次引用一个表,sql-server,database,database-design,triggers,foreign-keys,Sql Server,Database,Database Design,Triggers,Foreign Keys,嗨,stackoverflow数据库设计专家 我在数据库中遇到了一个设计问题,我在Stackoverflow中没有发现任何类似的问题,因此我提出了这个问题 我有一个图像表,包含图像数据和它的主键。在我的设计中,每个图像可以在多个表中多次引用 以下是数据库的表示形式: -------------------- ------------------------------------------- | image | | table1

嗨,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\u图像自动递增主键
    • 数据图像数据
  • 表1表
    • id\u表1自动递增主键
    • id\u image外键引用
      image.id\u image
    • 数据表1数据
  • 表2表
    • id_表2自动递增主键
    • id\u image外键引用
      image.id\u image
    • 数据表2数据
我希望我的数据库的行为如下:

  • 如果我删除带有
    id\u table1=1
    table1
    行,则必须删除带有
    id\u image=1
    的图像行(此图像没有其他引用)
  • 如果我随后删除了
    id\u table2=1
    table2
    行,则不应删除任何图像(因为
    id\u image=2
    table2
    行仍然引用了
    id\u table2=2
  • 如果我随后删除
    id\u table2=2
    table2
    行,则必须删除
    id\u image=2
    的图像行(此图像没有其他引用)
  • 如果我随后删除带有
    id\u table1=2
    table1
    行,则不应删除任何图像(因为带有
    id\u image=3
    的图像仍被带有
    id\u table2=3
    table2
    行引用)
  • 如果随后删除
    id\u table2=3
    table2
    行,则必须删除
    id\u image=3
    的图像行(此图像没有其他引用)
我已经尝试过一些级联删除,通过反转外键(即包含
id\u table1
id\u table2
外键的
image
表),但是如果一个图像在其他两个表中引用,删除一个引用的表项也会删除该图像,这是我不希望发生的

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

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


谢谢

由于您的第一个要求,请立即:

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

我可以告诉你,你只能用扳机来完成这项任务。原因是您希望在从子表中删除行时自动从父表中删除

相反(删除父项时删除子项)可以通过级联外键来完成,但不是这样


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

我昨天提出了一个更好的设计。它仍然使用触发器(as),但这些触发器的定义要简单得多:

 --------------------    ---------------------------
| 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\u proxy

  • id\u image\u代理自动递增主键
  • id\u image外键引用
    image.id\u image
另外,
table1
table2
现在引用的是
image\u proxy
条目,而不是
image
条目

使用这种设计,触发器现在是:

  • 删除
    表1中的条目后,删除
    图像\u代理中的相应条目
  • 删除
    表2中的条目后,删除
    image\u proxy
    中的相应条目
  • 删除
    image\u proxy
    中的条目后,删除
    image
    中不再引用的条目

我不知道这个设计是否最适合这个问题,也不知道触发器的使用是否安全,这就是为什么如果有更好的答案或相关评论,我会关注这篇文章的原因

是的,但是这种设计很难定义触发器,正如我在问题中所说的。我宁愿使用其他设计,但我想不出更好的设计…不幸的是,我没有告诉你触发器是一种选择。我告诉你,他们是你唯一的选择。当然,它们需要一些复杂的编码,但这是您需求的代价,抱歉。当其他两个表中都没有id时,您希望从映像中删除(通过触发器)。用他们的ID在他们和图像之间的联合做一个表格。我在写了我的答案后刚刚读了你的评论,我觉得我找到的解决方案接近你的建议!不需要代理列。(通常情况下,一个id_tableN映射到一个只映射回它的代理。请注意,表1和表2中不仅proxys是FKs,而且(idN,proxy)是FK。不需要代理。)(为什么要将它们放入?您认为每个表都需要代理吗?)删除它们给出了我的建议。FK表示,子程序值必须以PK或UNIQUE NOT NULL的形式出现在另一个特定位置。就这么回事。PS您有两个子类型的图像,1和2。googlere-sql/数据库子处理/继承。这是常见问题,尽管你问的是更新算法