Restricciones de SQL
A veces queremos asegurarnos que los datos mantienen coherencia. ¿Cómo lo hacemos?
A la hora de trabajar con nuestros datos hay veces que queremos mantener unas limitaciones a la hora de incorporarlos. Podemos hacerlo de distintas formas, seguramente la que se te habrá ocurrido es la de incorporar validaciones en tus modelos de datos. Si bien es una buena manera de mantener los errores en la capa de la aplicación, también es muy recomendable incorporar restricciones en la base de datos.
Estas restricciones, en caso de intentar romperlas, nos devolverá un error de SQL. Esto significa que, ya sea al intentar hacerlo desde nuestra aplicación o nosotros directamente desde la consola, no podemos tener datos inválidos almacenados.
Para que se utilizan las restricciones
Una cosa que a todo desarrollador debe quedar clara es que en cualquier momento vas a romper las cosas. Si bien los usuarios son los más propensos a romper nuestra aplicación de mil maneras inimaginables (o incluso alcanzando lo que llamamos casos extremos), nosotros también podemos romper la aplicación introduciendo algún bug crítico. Es por esto por lo que debemos poner también ciertas comprobaciones para nosotros, para cuando desarrollemos no hagamos algo fatal.
Al forzar la integridad de los datos desde nuestro sistema de base de datos, evitamos que al realizar las validaciones correspondientes en la lógica de la aplicación nos dejemos algo importante por el camino y guardemos datos inválidos.
En el post de las relaciones de bases de datos, comenté que los ORMs ayudan a realizar las relaciones. Pero ayudan con todo tipo de operaciones con la base de datos. Otra de las operaciones que nos permiten es justamente implementar constraints, o restricciones.
Asumamos que tenemos el siguiente caso, queremos forzar que tenemos un programa interno de gestión de descuentos y queremos forzar que no podamos aplicar el mismo descuento dos veces para el mismo producto.
product_id
es una clave foránea que vincula a una tabla de productos.Hemos agregado la instrucción CONSTRAINT
, lo que crea una clave única que restringe que la combinación de product_id
y descuento
sea única. Podemos probar esto intentando ejecutar el siguiente comando dos veces seguidas.
INSERT INTO descuentos (product_id, descuento) VALUES (1, 50)
La primera vez el comando funcionará, la segunda devolverá el siguiente error:
[23000][1062] Duplicate entry '1-50' for key 'descuentos.constraint_descuentos'
Esto nos indica que tenemos una entrada duplicada cuando tenemos una restricción única para esa combinación, por lo que no nos dejará crearla con esta combinación de valores. No obstante, si lo intentamos con otros valores sí nos dejará.
INSERT INTO descuentos (product_id, descuento) VALUES (1, 30)
Si volvemos a intentar lo mismo de ejecutar 2 veces esta instrucción no nos dejará con el mismo error. De esta manera hemos asegurado a nivel de base de datos que no tengamos descuentos del mismo valor duplicados.
Todo esto no quita que se deba realizar las validaciones a nivel de aplicación mediante validadores, ya que siempre es mejor manejar los errores a nivel de aplicación, pero esto nos permite que valores inválidos alcancen nuestra BBDD.