Restricciones de columna — NOT NULL / UNIQUE / CHECK / PRIMARY KEY
Diseña tablas como app_member con PRIMARY KEY / NOT NULL / UNIQUE / CHECK, y luego experimenta cómo los INSERT que violan restricciones se rechazan con errores constraint failed — todo práctico en el navegador.
Qué son las restricciones de columna — bloquear datos incorrectos en la capa de BD
Una restricción de columna (una regla de entrada asociada a una columna) es una "condición sobre los valores que pueden ir a esta columna", escrita en CREATE TABLE.
Este artículo cubre las cuatro grandes — PRIMARY KEY (identifica una fila de forma única),
NOT NULL (prohíbe NULL), UNIQUE (prohíbe duplicados) y CHECK (prohíbe valores que no cumplen una condición).
A diferencia de los artículos anteriores, no se precarga ningún dato — en su lugar, tú construyes las tablas en los ejercicios y ejecutas INSERT que violan restricciones a propósito para experimentar los errores.
Los papeles de las cuatro restricciones de columnaCada restricción limita "qué valores pueden ir a la columna". Las sentencias INSERT / UPDATE que violan la restricción se rechazan con error, lo que evita que entren datos incorrectos en la tabla.
Declarar una tabla con restricciones
Las restricciones van después del tipo en una definición de columna.
La forma es nombre_columna tipo restriccion restriccion ... y puedes apilar varias restricciones en una sola columna.
Añadir PRIMARY KEY a una columna INTEGER la convierte en la clave primaria que identifica una fila de forma única.
NOT NULL prohíbe omitir el valor, UNIQUE prohíbe el mismo valor que otra fila y CHECK (expresion) prohíbe cualquier valor que no haga verdadera la expresión.
La tabla member siguiente hace que member_id sea la clave primaria, handle (un nombre de usuario) NOT NULL más UNIQUE, y añade un CHECK "no negativo" a age.
-- Ejemplo de definición de tabla con restricciones (solo léelo)CREATETABLEIFNOTEXISTS member ( member_id INTEGERPRIMARY KEY, -- clave primaria: única y no NULL handle TEXTNOT NULLUNIQUE, -- obligatorio y sin duplicados email TEXTUNIQUE, -- sin duplicados (se permite NULL) age INTEGERCHECK (age >=0) -- solo valores no negativos);-- Una fila que cumple todas las restricciones entra sin problemaINSERT INTO member (member_id, handle, email, age)VALUES (1, 'alice', 'alice@example.com', 30);
Imagina el requisito: "diseña una tabla member con restricciones para que no puedan entrar datos incorrectos". (Ejecútalo correctamente y aparecerá la explicación.)
① Empieza con DROP TABLE IF EXISTS app_member; para limpiar cualquier versión previa, y luego construye la tabla app_member. Columnas: member_id (entero, clave primaria), handle (texto, obligatorio y sin duplicados), email (texto, sin duplicados pero NULL permitido), age (entero, solo no negativo).
② Inserta con INSERT una fila que cumpla todas las restricciones (p. ej. member_id 1 / handle cadena ascii / email cadena ascii / age entero ≥ 0).
③ Ejecuta SELECT * FROM app_member; para confirmar que entró una fila.
Editor SQL
Ejecutar una consulta para ver el resultado
Esquema
Sin tablas
Las violaciones de restricciones lanzan errores — NOT NULL y UNIQUE
El trabajo de una restricción es rechazar escrituras que la violan.
Intentar poner NULL (u omitir el valor) en una columna NOT NULL lanza un error NOT NULL constraint failed, e insertar un valor que ya existe en una columna UNIQUE / PRIMARY KEY lanza un error UNIQUE constraint failed.
La fila del INSERT que dio error no entra en la tabla.
Flujo de un INSERT que viola una restricciónLas filas que cumplen las restricciones entran con normalidad; las filas que las violan se rechazan con error y nunca se añaden. Un error es la prueba de que "la restricción está funcionando".
-- Violación de NOT NULL: intenta poner NULL en handle (solo léelo)INSERT INTO member (member_id, handle, age) VALUES (2, NULL, 20);--> Error: NOT NULL constraint failed: member.handle-- Violación de UNIQUE: intenta insertar el mismo handle que una fila existente (solo léelo)INSERT INTO member (member_id, handle, age) VALUES (3, 'alice', 25);--> Error: UNIQUE constraint failed: member.handle
Imagina el requisito: "verifica el efecto de hacer obligatorio handle provocando un INSERT que lo viole". Este ejercicio tiene éxito si obtienes un error (prueba de que la restricción está bloqueando datos incorrectos correctamente).
① El DELETE FROM app_member; inicial vacía el app_member del Ejercicio 1 (para que volver a ejecutar dé el mismo resultado).
② Escribe un INSERT que ponga NULL en la columna NOT NULL handle a propósito (p. ej. member_id 1 / handle NULL / email NULL / age 20).
③ Ejecútalo y confirma que obtienes un error NOT NULL constraint failed: app_member.handle. Fíjate en que el mensaje de error incluye qué tabla y qué columna se violó.
Editor SQL
Ejecutar una consulta para ver el resultado
Esquema
Sin tablas
Imagina el requisito: "verifica el efecto de prohibir duplicados en handle provocando un INSERT que lo viole". Este ejercicio también tiene éxito si obtienes un error.
① El DELETE FROM app_member; inicial vacía el app_member del Ejercicio 1.
② Para la fila 1, escribe tu propio INSERT con handle puesto a 'alice' (p. ej. member_id 1 / handle 'alice' / email 'alice@example.com' / age 30).
③ Para la fila 2, escribe otro INSERT con el mismo handle de 'alice' (puedes cambiar member_id y email).
④ Ejecútalo y confirma que la fila 1 entra bien, mientras que la fila 2 lanza UNIQUE constraint failed: app_member.handle.
Editor SQL
Ejecutar una consulta para ver el resultado
Esquema
Sin tablas
Restricciones CHECK — expresa condiciones de valor como expresiones
CHECK (expresion) es una restricción que usa una expresión para describir qué valores pueden ir a la columna.
CHECK (age >= 0) rechaza edades negativas, CHECK (price > 0) rechaza precios de 0 o menos.
Un patrón frecuente es CHECK (status IN ('active','inactive')), que limita el conjunto de valores permitidos.
Si la expresión no evalúa a verdadero, el INSERT / UPDATE se rechaza con un error CHECK constraint failed.
Los ejercicios finales de este artículo usan CHECK (age >= 0) y CHECK (status IN (...)) para experimentar cómo CHECK rechaza las violaciones.
Cómo CHECK evalúa verdadero/falsoLa expresión CHECK se evalúa para cada fila INSERT. Verdadero → aceptada, en otro caso → rechazada como CHECK constraint failed.
-- Restringe el rango o el conjunto de valores con CHECK (solo léelo)CREATETABLEIFNOTEXISTS product ( product_id INTEGERPRIMARY KEY, price INTEGERCHECK (price >0),statusTEXTCHECK (statusIN ('active','inactive')));-- price <= 0 se rechaza con CHECK constraint failedINSERT INTO product (product_id, price, status) VALUES (1, -100, 'active');
Imagina el requisito: "verifica el efecto de añadir un CHECK no negativo a age provocando un INSERT que lo viole". Un error es la condición de éxito.
① El DELETE FROM app_member; inicial vacía el app_member del Ejercicio 1.
② Escribe tu propio INSERT que ponga un valor negativo (p. ej. -5) en age. Como handle es NOT NULL, dale un valor no NULL.
③ Ejecútalo y confirma que obtienes un error CHECK constraint failed: app_member.age. Opcionalmente, prueba a cambiar age a un valor no negativo y observa que entonces el INSERT tiene éxito.
Editor SQL
Ejecutar una consulta para ver el resultado
Esquema
Sin tablas
Imagina el requisito: "limita la columna status de un miembro a solo los dos valores 'active' / 'inactive'". Este es el ejercicio final del artículo — un error es la condición de éxito.
① Empieza con DROP TABLE IF EXISTS app_member_status; para limpiar cualquier versión previa, y luego construye la tabla app_member_status por tu cuenta. Dos columnas: member_id (entero, clave primaria) y status (texto, obligatorio y solo 'active' o 'inactive' permitidos).
② Como fila 1, INSERT uno de los valores permitidos ('active' o 'inactive').
③ Como fila 2, INSERT'banned', que no está en la lista permitida.
④ Ejecútalo y confirma que la fila 1 pasa y la fila 2 lanza CHECK constraint failed: app_member_status.status.
Editor SQL
Ejecutar una consulta para ver el resultado
Esquema
Sin tablas
QUIZ
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 1Sobre una columna declarada handle TEXT NOT NULL UNIQUE, ¿qué afirmación es correcta?
Pregunta 2¿Qué pasa cuando intentas INSERT un valor que ya existe en una columna UNIQUE?
Pregunta 3¿Qué restricción es mejor para expresar la regla de negocio "solo se permiten precios mayores que 0" en la definición de la tabla?