Restricciones
## Objetivos de Aprendizaje
- Entender las restricciones de base de datos
- Usar PRIMARY KEY, FOREIGN KEY
- Implementar NOT NULL, UNIQUE
- Agregar restricciones CHECK
## ¿Qué Son las Restricciones?
Reglas aplicadas a los datos de la tabla:
```sql
CREATE TABLE employees (
employee_id INTEGER PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
salary DECIMAL CHECK (salary > 0)
);
```
## PRIMARY KEY
### Columna Única
```sql
CREATE TABLE employees (
employee_id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT
);
```
### Primary Key Compuesta
```sql
CREATE TABLE order_items (
order_id INTEGER,
product_id INTEGER,
quantity INTEGER,
PRIMARY KEY (order_id, product_id)
);
```
### Agregar a Tabla Existente
```sql
ALTER TABLE employees
ADD PRIMARY KEY (employee_id);
```
### AUTO_INCREMENT
```sql
-- MySQL
CREATE TABLE employees (
id INTEGER PRIMARY KEY AUTO_INCREMENT
);
-- PostgreSQL (SERIAL)
CREATE TABLE employees (
id SERIAL PRIMARY KEY
);
-- SQLite
CREATE TABLE employees (
id INTEGER PRIMARY KEY AUTOINCREMENT
);
-- SQL Server
CREATE TABLE employees (
id INTEGER IDENTITY(1,1) PRIMARY KEY
);
```
## FOREIGN KEY
### Sintaxis Básica
```sql
CREATE TABLE departments (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
first_name TEXT,
department_id INTEGER REFERENCES departments(id)
);
```
### Con ON DELETE/UPDATE
```sql
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
department_id INTEGER REFERENCES departments(id)
ON DELETE SET NULL
ON UPDATE CASCADE
);
```
### Opciones
| Opción | Descripción |
|--------|-------------|
| CASCADE | Eliminar/actualizar fila, filas relacionadas también se eliminan/actualizan |
| SET NULL | Establecer clave foránea a NULL |
| SET DEFAULT | Establecer clave foránea a valor por defecto |
| RESTRICT | Prevenir eliminación/actualización si existen filas relacionadas |
| NO ACTION | Igual que RESTRICT (verificar después de otras operaciones) |
### Foreign Key Compuesta
```sql
CREATE TABLE order_items (
order_id INTEGER,
product_id INTEGER,
FOREIGN KEY (order_id, product_id) REFERENCES orders(id, product_id)
);
```
## NOT NULL
### Nivel de Columna
```sql
CREATE TABLE employees (
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT NOT NULL
);
```
### Prevenir NULL en Existente
```sql
ALTER TABLE employees
ALTER COLUMN email SET NOT NULL;
```
## UNIQUE
### UNIQUE Una Columna
```sql
CREATE TABLE employees (
email TEXT UNIQUE
);
```
### Múltiples Columnas (Nivel de Fila)
```sql
CREATE TABLE department_leads (
department_id INTEGER,
leader_id INTEGER,
UNIQUE (department_id, leader_id)
);
```
### Restricción con Nombre
```sql
CREATE TABLE employees (
email TEXT CONSTRAINT uq_email UNIQUE
);
```
## Restricción CHECK
### CHECK Básico
```sql
CREATE TABLE employees (
salary DECIMAL CHECK (salary > 0),
age INTEGER CHECK (age >= 18)
);
```
### CHECK con Nombre
```sql
CREATE TABLE products (
price DECIMAL CONSTRAINT positive_price CHECK (price >= 0),
quantity INTEGER CONSTRAINT positive_qty CHECK (quantity >= 0)
);
```
### Múltiples Condiciones
```sql
CREATE TABLE reservations (
check_in DATE,
check_out DATE,
CHECK (check_out > check_in)
);
```
### Agregar CHECK a Existente
```sql
ALTER TABLE employees
ADD CONSTRAINT positive_salary CHECK (salary > 0);
```
## DEFAULT
### Valor por Defecto de Columna
```sql
CREATE TABLE employees (
created_at DATE DEFAULT CURRENT_DATE,
status TEXT DEFAULT 'active',
is_active BOOLEAN DEFAULT TRUE
);
```
### Secuencia como Valor por Defecto
```sql
-- PostgreSQL
CREATE TABLE employees (
id SERIAL PRIMARY KEY DEFAULT nextval('my_sequence')
);
```
### Expresión como Valor por Defecto
```sql
-- PostgreSQL
CREATE TABLE orders (
total DECIMAL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
## Gestión de Restricciones
### Ver Restricciones
```sql
-- MySQL
SELECT * FROM information_schema.table_constraints
WHERE table_name = 'employees';
-- PostgreSQL
SELECT * FROM information_schema.table_constraints
WHERE table_name = 'employees';
```
### Eliminar Restricción
```sql
-- MySQL
ALTER TABLE employees DROP INDEX uq_email;
-- PostgreSQL / SQL Server
ALTER TABLE employees DROP CONSTRAINT uq_email;
```
## Convenciones de Nombres
```sql
-- Nomenclatura consistente
PRIMARY KEY: pk_tablename
FOREIGN KEY: fk_tablename_columnname
UNIQUE: uq_tablename_columnname
CHECK: chk_tablename_condition
```
## Patrones Comunes
### Tabla de Usuarios
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE
);
```
### Tabla de Auditoría
```sql
CREATE TABLE audit_log (
id SERIAL PRIMARY KEY,
action TEXT NOT NULL,
table_name TEXT NOT NULL,
record_id INTEGER NOT NULL,
old_value TEXT,
new_value TEXT,
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
changed_by INTEGER REFERENCES users(id)
);
```
## Resumen
- **PRIMARY KEY**: Identifica exclusivamente cada fila (una por tabla)
- **FOREIGN KEY**: Enlaza a otra tabla (impone integridad referencial)
- **NOT NULL**: Previene valores NULL
- **UNIQUE**: No se permiten valores duplicados
- **CHECK**: Reglas de validación personalizadas
- **DEFAULT**: Valor cuando no se proporciona ninguno
- Las restricciones mantienen la integridad de datos a nivel de base de datos
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →