Разработка базы данных - ссылка на таблицу несколько раз из нескольких таблиц - PullRequest
0 голосов
/ 06 сентября 2018

Привет, специалисты по проектированию баз данных 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 table
    • id_table1 автоинкрементный первичный ключ
    • id_image ссылка на внешний ключ image.id_image
    • данные данные таблицы1
  • table2 table
    • 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 должна быть удалена (других ссылок на это изображение нет)

Я уже пробовал несколько каскадного удаления, инвертируя внешние ключи (то есть таблицу image, содержащую внешние ключи id_table1 и id_table2), но если на изображение ссылаются в 2 других таблицах, удаляется одна ссылочная таблица. запись также удаляет изображение, которое я не хочу, чтобы это произошло.

Я также пытался определить триггеры, но этот подход более сложный, чем я думал: каждый раз, когда мне приходится проверять среди всех внешних ключей на id_image, чтобы увидеть, есть ли другая ссылка на изображение, которое нужно удалить. Этот образец содержит 2 внешних ключа, но в создаваемой мной базе данных будет более 10 ...

Я чувствую, что есть простое решение этой простой проблемы, кто-нибудь здесь, чтобы помочь мне?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Вчера я придумал лучший дизайн. Он по-прежнему использует триггеры (как сказал Tab Alleman ), но определить их гораздо проще:

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

Кроме того, table1 и table2 теперь ссылаются на запись image_proxy вместо записи image.

С этим дизайном триггеры теперь:

  • После удаления записей в table1, удалить соответствующие записи в image_proxy.
  • После удаления записей в table2, удалить соответствующие записи в image_proxy.
  • После удаления записей в image_proxy удалите записи в image, на которые больше нет ссылок в image_proxy.

Я не знаю, является ли этот дизайн лучшим для этой проблемы, и не является ли использование триггеров безопасным, поэтому я буду следить за этим сообщением, если есть какой-либо лучший ответ или соответствующий комментарий!

0 голосов
/ 06 сентября 2018

Сразу по первому требованию:

Если я удаляю строку table1 с id_table1 = 1, строка изображения с id_image = 1 должен быть удален (других ссылок на это изображение нет)

Я могу вам сказать, что вы можете сделать это только с ТРИГГЕРОМ. Причина в том, что вы хотите автоматически удалять из родительской таблицы при удалении строки из дочерней таблицы.

Обратное (удаление дочернего элемента при удалении родительского элемента) можно выполнить с помощью каскадных внешних ключей, но не этим.

Вам потребуется поместить триггеры в обе дочерние таблицы, чтобы обеспечить требуемую логику.

...