13

Я прочитал некоторые из Bill Karwin's ответов о single table inheritance и думаю, что этот подход будет хорошо для установки я рассматриваю:Как обеспечить ссылочную целостность в одиночном наследовании таблицы?

Playlist 
-------- 
id AUTO_INCREMENT 
title 

TeamPlaylist 
------------ 
id REFERENCES Playlist.id 
teamId REFERENCES Team.id 

UserPlaylist 
------------ 
id REFERENCES Playlist.id 
userId REFERENCES User.id 

PlaylistVideo 
------------- 
id 
playlistId REFERENCES Playlist.id 
videoId REFERENCES Video.id 

Все CASCADE опции устанавливаются в DELETE который будет корректно работать для того, когда Playlist является удалено, однако, что произойдет, если удаляется User или Team?

ie. Если удаляется User, строки в UserPlaylist будут удалены, но ссылочные строки в Playlist и PlaylistVideo останутся. Я думал об обеспечении этого как TRIGGER AFTER DELETE, но нет способа узнать, возник ли запрос на удаление, потому что был удален Playlist или если был удален User.

Каков наилучший способ обеспечения целостности в этой ситуации?

Edit (Прилагается ERD)

enter image description here

+1

Я не понимаю, как UserPlaylist может быть наследованием списка воспроизведения. Разве это не таблица отношений? – Sebas

+0

Я не понимаю ваш вопрос. UserPlaylist относится к списку воспроизведения только для того, что идентификатор поступает из Playlist.id. Вот еще несколько вопросов о наследовании одиночного стола - http://stackoverflow.com/a/3383320/47278 –

+0

- вся причина, по которой вы не хотите, чтобы пользователь был удален, чтобы вывести списки воспроизведения и списки воспроизведения в виде списка, потому что они также могли ссылаться другими учетными записями userplaylist или teamplaylist. – WebChemist

ответ

3

На мой взгляд, проблема заключается в том, что ваши User и Team таблицы являются те, которые должны иметь таблицу Supertype (например, Party), а не все таблицы списка воспроизведения.

Как вы указали, выполнение вашего «наследования таблиц» в плейлистах происходит со штрафами при попытке выяснить, что удалить. Все эти проблемы уходят, когда вы перемещаете наследование до уровня пользователя/команды.

Вы можете увидеть this answer for more detail about supertyping/subtyping.

Извините, что не поставлял код, так как я не знаю синтаксиса MySQL наизусть.

Основная концепция заключается в том, что таблица супертипов позволяет реализовать тип полиморфизма базы данных. Когда таблица, с которой вы работаете, должна ссылаться на любой из группы подтипов, вы просто заставляете FK указывать на супертип вместо этого, и это автоматически дает вам желаемый «только один из них за раз», деловое ограничение. Тип супер имеет отношение «один к нулю» или «один к одному» с каждой из таблиц подтипа, и каждая таблица подтипов использует то же значение в PK, что и PK из таблицы супертипов.

В вашей базе данных, имея только одну таблицу Playlist с FK до Party (PartyID), вы легко выполнили свое бизнес-правило на уровне базы данных без триггеров.

+0

Это хороший момент и хорошая идея. Однако в этой системе команда сильно отличается от Пользователя. например. Пользователь может войти в систему, команда не может. Это существующая система в производстве (в то время как плейлисты новы). Если бы я строил это с нуля, это, вероятно, было бы возможным. Но мне нужно подумать об этом, если бы было целесообразно перейти на эту настройку (т. Е. Команды и пользователи в настоящее время имеют перекрывающиеся идентификаторы). Но спасибо за предложение. –

+0

Вот что представляют собой таблицы подтипов: способы, которыми они отличаются. Реальная проблема в изменении - обновление идентификаторов для одного из наборов с ограничениями на удаление и воссоздание. Но я думаю, что это стоит того. :) – ErikE

+0

Спасибо, что выбрали мой ответ! Что заставило вас решить, что это был путь? – ErikE

4

ОК Я понимаю, что вы хотите здесь ... то, что вы хотите сделать, это выполнить запрос как

DELETE FROM playlist 
WHERE  id 
NOT IN  (
    SELECT id 
    FROM UserPlayList 
    UNION 
    SELECT id 
    FROM TeamPlayList 
) 

после того, как либо строка удалено от пользователей или команд

11

Что вы можете сделать, это реализовать триггеры в ваших таблицах Users и Team, которые выполняются Ют, когда строки удаляются либо:

Пользователь таблица:

DELIMITER $$ 
CREATE TRIGGER user_playlist_delete 
BEFORE DELETE ON User FOR EACH ROW 
BEGIN 
    DELETE a FROM Playlist a 
    INNER JOIN UserPlaylist b ON a.id = b.id AND b.userId = OLD.id; 
END$$ 
DELIMITER ; 

Team стол:

DELIMITER $$ 
CREATE TRIGGER team_playlist_delete 
BEFORE DELETE ON Team FOR EACH ROW 
BEGIN 
    DELETE a FROM Playlist a 
    INNER JOIN TeamPlaylist b ON a.id = b.id AND b.teamId = OLD.id; 
END$$ 
DELIMITER ; 

То, что эти триггеры будут делать это каждый раз, когда запись будет удалена из одного из этих таблиц операция DELETE будет автоматически выполняться в таблице Playlists с использованием id, который будет удален (через внутреннее соединение).

Я испытал это, и он отлично работает.

+0

блестящее решение. не тестировали его myslef, но выглядели солидно.+1 – techtheatre

+0

Хорошая идея Зейн. По какой-то причине я не думал о том, чтобы ввести триггер в таблицы User или Team - только таблицы UserPlaylist или TeamPlaylist. –

+0

Я не думаю, что это лучший способ решить проблему ... – ErikE

1

Ответ Zane Bien довольно очевиден. & superb.But. У меня есть идея сделать это без использования триггера, потому что триггер имеет много проблем.

Вы используете какой-либо язык программирования? Если да, то,

Использование одного transaction и сделать базу данных auto commit false

написать запрос на удаление для ссылочных строк в списке воспроизведения и PlaylistVideo. Вручную вы должны сначала написать этот запрос, используя этот идентификатор ссылки (с условием) и запустите его.

Теперь подготовьте другой запрос для своей основной задачи, то есть удалите пользователя, а строки в UserPlaylist будут удалены автоматически (из-за опции CASCADE DELETE).Теперь запустите свой второй запрос и commit.

В заключение сделайте свою транзакцию auto commit true.

Он работает успешно, надеется, что это поможет.

 Смежные вопросы

  • Нет связанных вопросов^_^