2008-12-09 1 views
2

Я работаю над базой данных, которая отслеживает файлы и зависимости в проектах. Вкратце, у меня есть две основные таблицы; в таблице PROJECTS перечислены имена проектов и другие свойства, в таблице FILES перечислены файлы. Каждая запись файла указывает на проект в качестве внешнего ключа, установленного в CASCADE, поэтому, если я удалю запись проекта из базы данных, все записи файлов также исчезнут. Все идет нормально.Конфликт требований внешнего ключа CASCADE и RESTRICT?

Теперь у меня есть дополнительная таблица DEPENDENCIES. Каждая запись в таблице зависимостей - это два файла, указав, что первый файл зависит от второго. Опять же, это внешние ключи, первый из которых установлен в CASCADE (поэтому, если я удалю запись файла, эта запись будет удалена), а вторая установлена ​​в RESTRICT (поэтому мне не разрешено удалять запись файла, если любые другие файлы зависят в теме). Опять же, все кажется хорошим.

К сожалению, похоже, что я больше не могу удалить проект с помощью одного заявления на удаление SQL! Удаление пытается каскадно удалить файлы, но если они есть в таблице DEPENDENCIES, внешний ключ RESTRICT предотвращает удаление (даже если эта запись в таблице зависимостей будет удалена, потому что другой столбец CASCADE). Единственное обходное решение, которое у меня есть, - это вычислить точный порядок удаления файлов, чтобы ни одно из ограничений записи зависимостей не было нарушено, и удалите записи файлов по одному, прежде чем пытаться удалить проект.

Есть ли способ настроить мою схему базы данных, чтобы один SQL-удалять из таблицы проектов правильно каскадировал другую? Я использую Firebird 2.1, но я не знаю, имеет ли это какое-либо значение - похоже, должен быть способ сделать эту работу?

ответ

4

Вы не можете контролировать порядок удаления через каскадный внешний ключ, но вы можете быть в состоянии спроектировать триггер PROJECTS для удаления строк в FILES, которые принадлежат к этому проекту и также перечислены в DEPENDENCIES в зависимости от других FILES. Сделайте это триггером BEFORE DELETE, чтобы он выполнялся до каскадных эффектов.

Что-то вроде этого:

CREATE TRIGGER Del_Child_Files FOR PROJECTS 
BEFORE INSERT 
AS BEGIN 
    FOR SELECT F.FILE_ID FROM FILES F JOIN DEPENDENCIES D 
     ON F.FILE_ID = D.CHILD_ID 
    WHERE F.PROJECT_ID = OLD.PROJECT_ID 
    INTO :file_id 
    DO 
    DELETE FROM FILES WHERE FILE_ID = :file_id; 
    DONE 
END 

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

Я не тестировал это, и мой синтаксис Firebird может быть ржавым, но, возможно, это поможет вам начать.

Очевидно, пожалуйста, проверьте это на копии ваших данных, а не на живых данных!

+0

Мне определенно нравится идея сделать это в триггере, а не в коде приложения. Я отдам это и посмотрю, что это будет ответом для меня :) – Chris 2008-12-09 20:07:50

0

Поддерживает ли система отложенные ограничения, в которых проверка ограничения может быть отложена до точки фиксации?

Возможно, это просто вещь Oracle.

+0

Firebird не поддерживает отложенные ограничения. – 2008-12-09 19:25:22

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

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