Cómo crear tablas temporales en SQL Server: paso a paso
Las tablas temporales (system-versioned) de SQL Server guardan automáticamente el historial de cada fila y te permiten consultar los datos tal como estaban en cualquier momento del pasado. Son perfectas para auditoría, análisis de cambios y para recuperar valores modificados por error, sin escribir triggers ni mantener tablas de historial a mano. Es una de las formas más sencillas de añadir trazabilidad y gobernanza a un modelo de datos existente.
Requisitos previos
- SQL Server 2016 o superior, o una base de datos en Azure SQL Database.
- SQL Server Management Studio (SSMS) o Azure Data Studio para ejecutar las consultas.
- Permisos para crear tablas en una base de datos de prueba (evita producción).
- Conocimientos básicos de T-SQL:
CREATE TABLE,INSERT,UPDATEySELECT.
Paso 1: Crear la tabla temporal
Una tabla temporal necesita tres cosas: una clave primaria, dos columnas datetime2 que marcan el inicio y el fin de validez de cada versión de la fila, y la cláusula PERIOD FOR SYSTEM_TIME. Las columnas de período las rellena el motor (fíjate en GENERATED ALWAYS AS ROW START/END), así que nunca les escribes valores. A diferencia de una solución con triggers, el versionado lo gestiona el propio SQL Server. Lo activamos con SYSTEM_VERSIONING = ON y damos un nombre a la tabla de historial.
CREATE TABLE dbo.Funcionario
(
FuncionarioID INT NOT NULL PRIMARY KEY CLUSTERED,
Nome NVARCHAR(100) NOT NULL,
Departamento NVARCHAR(50) NOT NULL,
Salario DECIMAL(10,2) NOT NULL,
ValidoDe DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidoAte DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidoDe, ValidoAte)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.FuncionarioHistorico));
SQL Server crea automáticamente la tabla dbo.FuncionarioHistorico con la misma estructura. Ahí se guardan, de forma transparente, las versiones antiguas de cada fila. Los valores de período se registran en UTC.
La tabla de historial solo crece. En escenarios reales, define una política de retención (HISTORY_RETENTION_PERIOD) para eliminar automáticamente las versiones antiguas y controlar el espacio ocupado.
Paso 2: Insertar y modificar datos
Fíjate en que no indicamos valores para las columnas de período: de eso se encarga el motor. Vamos a insertar un empleado y, más tarde, darle un aumento.
INSERT INTO dbo.Funcionario (FuncionarioID, Nome, Departamento, Salario)
VALUES (1, N'Ana Silva', N'Dados', 3000.00);
-- Some time later, Ana gets a raise:
UPDATE dbo.Funcionario
SET Salario = 3500.00
WHERE FuncionarioID = 1;
En el momento del UPDATE, la versión anterior (salario 3000) se copia a la tabla de historial con el intervalo de validez en el que estuvo activa, y la fila actual se queda con el valor nuevo.
Paso 3: Consultar el historial con FOR SYSTEM_TIME
Una consulta normal devuelve solo el estado actual. Para ver cómo estaban los datos en un instante concreto, usa FOR SYSTEM_TIME AS OF:
-- Replace with a real date/time between the insert and the raise
SELECT FuncionarioID, Nome, Salario, ValidoDe, ValidoAte
FROM dbo.Funcionario
FOR SYSTEM_TIME AS OF '2026-07-07 15:00:00'
WHERE FuncionarioID = 1;
SQL Server devuelve la versión que era válida en ese momento — aunque ya se haya sustituido. Para ver todas las versiones de una fila, actuales e históricas, de una sola vez, usa ALL:
SELECT FuncionarioID, Nome, Salario, ValidoDe, ValidoAte
FROM dbo.Funcionario
FOR SYSTEM_TIME ALL
WHERE FuncionarioID = 1
ORDER BY ValidoDe;
Paso 4: Desactivar el versionado de forma segura
No se puede eliminar ni cambiar la estructura de una tabla temporal directamente. Primero se desactiva el versionado; se elimina el vínculo con la tabla de historial, pero los datos permanecen intactos.
ALTER TABLE dbo.Funcionario SET (SYSTEM_VERSIONING = OFF);
-- You can now alter columns or drop tables if needed.
-- To re-enable, point again to the same history table.
Comprobar el resultado
Una consulta simple (SELECT * FROM dbo.Funcionario) debería mostrar solo la versión actual, con el salario 3500. Si la consulta con FOR SYSTEM_TIME ALL devuelve dos filas para FuncionarioID 1 — una con 3000 y otra con 3500 — el versionado funciona. En SSMS, la tabla aparece con un icono de reloj y, al expandirla, muestra debajo la tabla de historial asociada.
Conclusión
Con solo unas pocas líneas de T-SQL ya tienes un historial automático y a prueba de olvidos, listo para auditorías y para responder a la pregunta "¿cómo estaba esto antes?". El siguiente paso es explorar las variantes FROM ... TO, BETWEEN ... AND y CONTAINED IN para consultar intervalos de tiempo, y definir una política de retención adecuada. ¿Qué tabla de tu modelo se beneficiaría ya de guardar su propio historial?