domingo, 9 de febrero de 2014

Usando cascadas en SQL Server

Nota: cuando hablamos de tabla padre y tabla hijo, nos referimos a una tabla (tabla hijo) que tiene una clave foránea (foreign key, en inglés) que hace referencia a otra tabla (tabla padre). Por tanto, utilizamos las expresiones padre e hijo para hablar de una relación de dependencia donde el hijo depende del padre.

Supongamos que tenemos una tabla padre y una tabla hijo, OrdenCompraCabecera y OrdenCompraDetalle, respectivamente. Si queremos borrar un registro de OrdenCompraCabecera nos encontramos con la situación de que primero debemos borrar los registros dependientes de OrdenCompraDetalle (SQL Server hace esto para evitar registros huérfanos, asegurando así una determinada integridad en los datos).

Para evitar esta "molestia" (¡una molestia necesaria!) podemos activar una cascada de las restricciones de referencia integral (de ahora en adelante le llamaremos solamente cascadas) en la tabla hijo para así, cuando hagamos un cambio en un registro padre, en los registros hijos se realizará una acción que determinemos.

Hagamos un ejemplo con nuestras tablas de OrdenCompraCabecera y OrdenCompraDetalle. Corre el siguiente script  que sirve para crear una base de datos -imagino que no tienes una base de datos como la que puse en el script :) - agregar las dos tablas ya mencionadas y agregarles datos:



 Entonces, tenemos una base de datos con al menos dos tablas y tenemos también la cascada activada en el campo OrdenCompraID de la tabla OrdenCompraDetalle. Utilizamos la configuración tal, de modo que cuando borremos el registro padre los registros hijos correspondientes sean también eliminados. Claro, esto no tiene por qué ser así, más adelante veremos que tenemos otras acciones disponibles además de borrar.

Si hacemos un SELECT en ambas tablas, OrdenCompraCabecera y OrdenCompraDetalle, veremos que tienen datos, en concreto, en la tabla padre, OrdenCompraID igual a "1" tiene dos registros hijos en la tabla detalle, mientras que el OrdenCompraID igual a "2" tiene un solo registro hijo en la tabla detalle.

Ahora puedes borrar cualquier registro en la tabla padre y sus respectivos registros en la tabla hijo serán borrados. Probemos esto con el siguiente script:

USE PruebaCascadaSeriesDeProgramacion;
DELETE OrdenCompraCabecera 
WHERE OrdenCompraID = 1;

Si vuelves a hacer un SELECT en ambas tablas, OrdenCompraCabecera y OrdenCompraDetalle, verás que todo registro relacionado con OrdenCompraID = 1 ha desaparecido de ambas tablas. Esto es porque activaste la cláusula ON DELETE de la cascada.

Otras opciones


Ya vimos un ejemplo de las cascadas por lo que asumo que tienes una idea general de su poder. Ahora hablaremos de otras opciones que tenemos a nuestra disposición con este tema, pero primero, toquemos algunos puntos clave de las cascadas:

- Esta debe ser activada en la tabla hijo (en la tabla que tiene la clave foránea).
- Esta debe ser activada en la columna de la clave foránea

Demos un vistazo general a las opciones que nos proveen las cascadas. Viendo la estructura general del script para crear una columna que posee clave foránea (solo coloco lo esencial, pero evidentemente que dicho código va dentro de un CREATE TABLE ):

<nombre_columna> <tipo_dato>  [ NULL | NOT NULL ] 
FOREIGN KEY REFERENCES <nombre_tabla_referencia>(<nombre_columna_referencia>)
 [ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] 
 [ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] 

Como podemos ver, las cascadas se dividen en dos cláusulas, ON DELETE y ON UPDATE, que se ejecutan cuando eliminamos o actualizamos (la columna de referencia) en la tabla padre, respectivamente, las cuales, a su vez, nos permiten realizar cuatro acciones: NO ACTION, CASCADE, SET NULL o SET DEFAULT. Hablemos ahora de las cuatro opciones que nos presentan. En el listado, hablaremos del caso ON DELETE, pero lo dicho es perfectamente aplicable para el caso ON UPDATE:

- NO ACTION: como su nombre lo indica, es simplemente no hacer nada ante el posible borrado de los registros padre, lo cual ocasionaría la presencia de registros huérfanos, lo que lanzaría un error en SQL Server y el borrado sería impedido. Esta es la acción por defecto.
- CASCADE: es la que vimos en el ejemplo, simplemente indica que el destino del registro padre es el mismo destino del registro hijo, es decir, si borramos el padre, también el hijo será borrado.
- SET NULL: vuelve nulo el valor de la columna de la clave foránea si el registro padre es borrado. Es claro que la columna de la clave foránea debe de aceptar valores nulos para que esta acción funcione.
- SET DEFAULT: actualiza el valor de la columna al valor por defecto especificado en dicha columna en caso de que el registro padre sea borrado.

Con el código presentado y la explicación dada, creo que eres capaz ahora de realizar tus propios ejemplos y hacer uso de esta poderosa herramienta de SQL Server. Intenta usar ON UPDATE SET NULL. Recuerda que se aprende a programar programando. Si tienes algún problema, no dudes en comentar.

Hasta la próxima :)

No hay comentarios:

Publicar un comentario