#mysql #sql #database-design #foreign-keys
#mysql #sql #дизайн базы данных #внешние ключи
Вопрос:
У меня есть следующие таблицы:
TABLE country
(
country_id int not null,
name varchar(32) not null,
primary key (country_id),
unique key (name)
);
TABLE place
(
place_id int not null,
name varchar(32) not null,
country_id int not null,
primary key (place_id),
unique key (country_id, name)
);
TABLE image
(
image_id int not null,
title varchar(75) not null,
caption varchar(500) not null,
filename varchar(29) not null,
country_id int,
place_id int,
primary key (image_id),
unique key (filename)
);
Изображение может иметь страну (или нет) или место (или нет).
Допустим, у меня есть запись в country
таблице:
23 | Spain |
И места в place
таблице:
3 | Madrid | 23
6 | Barcelona | 23
Я хочу image
пометить страну Spain
и место Barcelona
В image
таблице я должен ввести country_id
и place_id
или просто place_id
, поскольку страна уже определена по place_id?
Комментарии:
1. Совет: рассмотрите возможность использования
VARCHAR(255)
в качестве поля строкового типа общего назначения по умолчанию и переопределяйте его более длинными или более короткими ограничениями, только если у вас есть веская причина. Многие установки MySQL будут автоматически усекать любые данные, которые не подходят, что приводит к потере данных, жалобам пользователей и другим серьезным проблемам. Имена и адреса электронной почты довольно часто на удивление длинные, поэтому важно учитывать их.
Ответ №1:
Полиморфные отношения нелегко моделировать в реляционной базе данных.
Здесь я бы предложил другой подход, который вы настроили: создайте две разные таблицы мостов для изображений — одну для стран, а другую для мест.
Это будет выглядеть так:
create table countries (
country_id int primary key,
...
);
create table places (
place_id int primary key,
...
);
create table images (
image_id int primary key,
...
);
create table image_countries (
image_id int references images(image_id),
country_id int references countries(country_id),
primary key (image_id, country_id)
);
create table image_places (
image_id int references images(image_id),
place_id int references places(place_id),
primary key (image_id, place_id)
);
Затем вы можете связать данное изображение с любым количеством мест и стран, сколько захотите. Если вместо этого вы хотите разрешить только одну страну и одно место для каждого изображения, вы можете изменить первичный ключ каждой таблицы мостов на just image_id
.
Ответ №2:
Измените свой умственный фокус. Сосредоточьтесь на «месте», связанном с изображением. Затем сделайте places
работу как для «Испании», так и для «Мадрида, Испания». Не пытайтесь перепрыгнуть мимо places
, чтобы добраться до countries
.
Итак, в places
, разрешите пустое name
с непустым country
для указания «Испания».
Я бы использовал стандартные 2-буквенные коды стран вместо 4-байтового INT. Тогда я бы либо отобразил «ES» с изображениями для Испании, либо создал таблицу поиска, подобную вашей текущей countries
.