Pregunta

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

Ahora tengo una tabla DEPENDENCIAS adicional. Cada registro en la tabla de dependencias son dos archivos, lo que especifica que el primer archivo depende del segundo. Nuevamente, estas son claves foráneas, la primera se establece en CASCADA (por lo tanto, si elimino una entrada de archivo, este registro se elimina), pero la segunda se establece en RESTRICT (por lo que no se me permite eliminar una entrada de archivo si otros archivos dependen en eso). Nuevamente, todo parece estar bien.

¡Desafortunadamente parece que ya no puedo eliminar un proyecto con una sola declaración de eliminación de SQL! La eliminación intenta eliminar en cascada los archivos, pero si alguno de estos aparece en la tabla DEPENDENCIAS, la clave externa RESTRICT 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, de modo que no se infrinja ninguna de las restricciones de los registros de dependencia, y eliminar los registros de archivos de uno en uno antes de intentar eliminar el proyecto.

¿Hay alguna forma de configurar el esquema de mi base de datos para que una sola eliminación de SQL de la tabla de proyectos en cascada 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?

¿Fue útil?

Solución

No puede controlar el orden de eliminación a través de una clave foránea en cascada, pero puede diseñar un disparador en PROJECTS para eliminar filas en FILES que pertenecen a este proyecto y también se enumeran en <= > como dependiente de otro DEPENDENCIES. Conviértalo en un disparador BEFORE DELETE, para que se ejecute antes de los efectos en cascada.

Algo como esto:

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

Entonces, cuando elimina un proyecto, esto elimina todos los " child " archivos de un proyecto que dependen de otros archivos, y esto elimina en cascada las filas en <=> para que todos los archivos restantes estén libres de dependencias. Su eliminación del proyecto ahora puede en cascada para eliminar estos archivos.

No he probado esto y mi sintaxis de Firebird puede estar oxidada, pero tal vez te ayude a comenzar.

¡Obviamente, pruebe esto en una copia de sus datos, no en los datos en vivo!

Otros consejos

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

Quizás eso sea solo una cosa de Oracle.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top