CREATE TABLE y restricciones: expresar reglas desde el esquema
Una tabla no es solo una lista de columnas. También debe expresar cómo se identifica cada fila, qué relaciones son válidas y qué valores puede aceptar.
Las restricciones son reglas que la tabla hace cumplir. Protegen el modelo incluso cuando los datos llegan desde aplicaciones, importaciones o scripts diferentes.
Elementos principales
IDENTITY: generar un valor numérico
IDENTITY solicita a SQL Server un número para cada fila nueva. El primer argumento establece el valor inicial y el segundo, el incremento.
Id BIGINT IDENTITY(1, 1) NOT NULL
PRIMARY KEY: identificar cada fila
PRIMARY KEY exige que la columna o combinación de columnas sea única y no admita NULL. Una tabla solo puede tener una llave primaria.
CONSTRAINT PK_Tabla
PRIMARY KEY (Id)
FOREIGN KEY: exigir una referencia válida
FOREIGN KEY relaciona columnas de la tabla actual con una llave candidata de otra tabla y rechaza referencias hacia filas inexistentes.
CONSTRAINT FK_Tabla_Relacion
FOREIGN KEY (IdRelacionado)
REFERENCES dbo.TablaRelacionada (IdRelacionado)
Una llave candidata es una columna o combinación de columnas capaz de identificar una fila mediante una restricción primaria o única.
UNIQUE: impedir combinaciones repetidas
UNIQUE exige que no se repita la combinación de valores indicada. Puede expresar una regla distinta de la llave primaria, como impedir que un cliente marque dos veces el mismo producto.
CONSTRAINT UQ_Tabla_Columnas
UNIQUE (Columna1, Columna2)
CHECK: validar una condición
CHECK acepta la fila cuando su condición no es falsa. Por ello debemos considerar expresamente qué ocurre con NULL y combinarlo con nulabilidad cuando la regla exige un valor.
CONSTRAINT CK_Tabla_Regla
CHECK (Condicion)
DEFAULT: proporcionar un valor al omitir la columna
DEFAULT aporta un valor cuando un INSERT no incluye la columna. No sustituye un NULL enviado de forma explícita.
CONSTRAINT DF_Tabla_Columna
DEFAULT Expresion
El ejemplo utiliza SYSDATETIME() como valor predeterminado de registro. La función obtiene la fecha y hora actuales del servidor y devuelve un valor compatible con DATETIME2.
Ejemplo: tabla con reglas explícitas
CREATE TABLE dbo.ProductoFavorito
(
IdFavorito BIGINT IDENTITY(1, 1) NOT NULL,
IdCliente INT NOT NULL,
IdProducto INT NOT NULL,
Prioridad TINYINT NOT NULL
CONSTRAINT DF_ProductoFavorito_Prioridad DEFAULT 1,
FechaRegistro DATETIME2(0) NOT NULL
CONSTRAINT DF_ProductoFavorito_Fecha DEFAULT SYSDATETIME(),
CONSTRAINT PK_ProductoFavorito
PRIMARY KEY (IdFavorito),
CONSTRAINT UQ_ProductoFavorito_ClienteProducto
UNIQUE (IdCliente, IdProducto),
CONSTRAINT CK_ProductoFavorito_Prioridad
CHECK (Prioridad BETWEEN 1 AND 5),
CONSTRAINT FK_ProductoFavorito_Cliente
FOREIGN KEY (IdCliente)
REFERENCES dbo.Cliente (IdCliente),
CONSTRAINT FK_ProductoFavorito_Producto
FOREIGN KEY (IdProducto)
REFERENCES dbo.Producto (IdProducto)
);
La llave primaria identifica cada fila de forma única. La restricción única impide repetir una combinación de valores. Las llaves foráneas exigen que una referencia apunte a una fila existente; en este caso, a clientes y productos válidos.
IDENTITY no reemplaza una llave
IDENTITY genera un número, pero no crea automáticamente una restricción PRIMARY KEY ni garantiza por sí solo que el valor represente la regla de negocio.
Los saltos en una columna IDENTITY son normales. No debemos prometer una secuencia sin huecos ni utilizarla como número legal o consecutivo documental sin diseñar ese requisito de forma específica.
Valores predeterminados
DEFAULT se utiliza cuando la columna se omite en el INSERT. No reemplaza automáticamente un NULL enviado de forma explícita.
Nombrar las restricciones facilita encontrarlas y modificarlas posteriormente. Los nombres deberían seguir una convención consistente dentro de la base.
Elegir tipos y nulabilidad
El tipo debe representar rango, precisión y longitud reales. NOT NULL expresa que una fila válida siempre necesita ese dato; permitir nulos por comodidad traslada ambigüedad a todas las consultas posteriores.
Un texto tampoco debería recibir una longitud máxima por costumbre. La elección afecta almacenamiento, índices, validación e integración con otros sistemas.
Qué conviene comprobar
Antes de crear revisamos nombres, esquema, intercalación, crecimiento esperado, claves de negocio y patrones de consulta. La intercalación define cómo se compara y ordena el texto. Una clave de negocio identifica una entidad mediante datos del dominio, como un número oficial, y no solo mediante un identificador interno. Las restricciones deben corresponder con reglas verdaderas, no con coincidencias temporales de los datos actuales.
Una llave foránea protege la integridad referencial: evita referencias hacia filas inexistentes. No crea necesariamente el índice más conveniente en las columnas hijas; un índice organiza valores para facilitar el acceso a las filas. Debemos evaluar los accesos y eliminaciones esperados.