¿Conflicto CASCADE y RESTRICT los requisitos de la clave extranjera?

votos
2

Estoy trabajando en una base de datos que rastrea archivos y dependencias en proyectos. En resumen, tengo dos tablas principales; la tabla PROYECTOS enumera los nombres de los proyectos y otras propiedades, la tabla ARCHIVOS enumera los archivos. Cada entrada de archivo apunta a un proyecto como una clave foránea establecida en CASCADE, de modo que si elimino un registro de proyecto de la base de datos, también desaparecerán todos los registros de archivo. Hasta aquí todo bien.

Ahora tengo una tabla de DEPENDENCIAS adicionales. Cada registro en la tabla de dependencia es de dos archivos, especificando que el primer archivo depende del segundo. De nuevo, estas son claves foráneas, la primera se establece en CASCADE (por lo que si elimino una entrada de archivo, este registro se elimina), pero la segunda se establece en RESTRICT (por lo que no puedo eliminar una entrada de archivo si dependen otros archivos) en eso). De nuevo, todo parece bueno.

Desafortunadamente, parece que ya no puedo eliminar un proyecto con una única declaración de eliminación de SQL. La eliminación intenta eliminar en cascada los archivos, pero si alguno de ellos aparece en la tabla DEPENDENCIAS, la clave externa RESTRINGIR impide la eliminación (aunque ese registro en la tabla de dependencias se eliminará porque la otra columna es CASCADE). La única solución que tengo es calcular un orden exacto para eliminar los archivos para que no se violen las restricciones de registro de dependencia, y eliminar los registros de archivo de uno en uno antes de intentar eliminar el proyecto.

¿Hay alguna manera de configurar mi esquema de base de datos para que una única eliminación de SQL de la tabla de proyectos se conecte correctamente a las otras eliminaciones? Estoy usando Firebird 2.1, pero no sé si eso hace alguna diferencia, parece que debería haber una manera de hacer que esto funcione.

Publicado el 09/12/2008 a las 19:51
fuente por usuario
En otros idiomas...                            


2 respuestas

votos
4

No puede controlar el orden de eliminación mediante una clave externa en cascada, pero puede diseñar un activador PROJECTSpara eliminar filas FILESque pertenecen a este proyecto y también se enumeran DEPENDENCIEScomo dependientes de otro FILES. Haz que sea un BEFORE DELETEdisparador, por lo que debe ejecutarse antes de los efectos de cascada.

Algo como esto:

CREATE TRIGGER Del_Child_Files FOR PROJECTS
BEFORE INSERT IGNORE 
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

Por lo tanto, cuando elimina un proyecto, esto elimina todos los archivos "secundarios" de un proyecto que dependen de otros archivos, y esto conecta en cascada para eliminar filas, de DEPENDENCIESmodo que todos los archivos restantes están libres de dependencias. Su eliminación del proyecto puede ahora en cascada para eliminar estos archivos.

No he probado esto y mi sintaxis de Firebird puede estar oxidada, pero quizás te ayude a empezar.

Obviamente, prueba esto en una copia de tus datos, ¡no en los datos en vivo!

Respondida el 09/12/2008 a las 20:24
fuente por usuario

votos
0

¿Admite el sistema restricciones diferidas, en las que la verificación de restricciones puede diferirse hasta un punto de confirmación?

Tal vez eso solo sea una cosa de Oracle.

Respondida el 09/12/2008 a las 20:11
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more