¡¡Hola, chicos!!
A través de este post me gustaría mostrarles un recurso muy interesante y útil que son las Tablas Temporales. Como ya mencioné sobre ellos en el post. SQL Server 2016: lista de nuevas funciones y características, donde es posible recuperar datos de una tabla en cualquier momento. Esto significa que puedes “viajar en el tiempo”, visualizando cuáles eran los datos de una tabla determinada en una fecha y hora específicas, mediante consultas SQL simples.
Este recurso tiene un amplio abanico de posibilidades y usos, de los que puedo destacar el Dimensiones que cambian lentamente de BI, para implementar una dimensión cuya visión es la de una fecha determinada, y también para efectos de Auditoría, comparando el pasado con el presente. Todo ello sin tener que crear disparadores ni ningún control manual.
Cabe mencionar que esta característica está disponible en todas las ediciones de SQL Server, incluidas Web Edition y Express.
¿Cómo funcionan las tablas temporales?
Ver contenidoAl consultar los datos especificando la fecha deseada, se considerarán los registros de las 2 tablas, de forma transparente para usted, como lo demostraré a continuación en el siguiente tema.
Restricciones de una tabla temporal
Ver contenido- La tabla en cuestión debe tener una CLAVE PRIMARIA definida para poder utilizar la función de control de versiones. De lo contrario, verá un mensaje como este:
Mensaje 13553, Nivel 16, Estado 1, Línea 4
La tabla temporal versionada por el sistema 'dirceuresende.dbo.Table_Temporal' debe tener una clave principal definida. - Una vez que cree una tabla con esta característica habilitada, no podrá realizar la operación TRUNCATE TABLE en esta tabla, lo que generará el siguiente mensaje de error:
Mensaje 13545, Nivel 16, Estado 1, Línea 58
Error al truncar la tabla 'dirceuresende.dbo.Temporal_Table' porque no se admite la operación en tablas con versión del sistema. - Ya no podrás eliminar la tabla que tiene versiones activas. Para hacer esto, deberá detener el control de versiones y luego eliminar la tabla. De lo contrario, verá el siguiente mensaje de error:
Mensaje 13552, Nivel 16, Estado 1, Línea 58
La operación de eliminación de tabla falló en la tabla 'dirceuresende.dbo.Table_Temporal' porque no se admite la operación en tablas temporales con versión del sistema. - No se puede utilizar OLTP en memoria
- Los desencadenantes EN LUGAR DE no están permitidos. DESPUÉS de los activadores solo se permiten en la tabla actual (no se pueden crear en la tabla histórica).
- La tabla histórica no puede tener restricciones.
Mensaje 13564, Nivel 16, Estado 1, Línea 1
No se permite agregar la restricción CHECK a una tabla de historial temporal 'dirceuresende.dbo.Table_Temporal_Historico'.
Mensaje 1750, Nivel 16, Estado 0, Línea 1
No se pudo crear una restricción o un índice. Ver errores anteriores. - Los datos de la tabla histórica no se pueden modificar manualmente (ACTUALIZAR, ELIMINAR, INSERTAR, etc.)
Mensaje 13560, Nivel 16, Estado 1, Línea 1
No se pueden eliminar filas de una tabla de historial temporal 'dirceuresende.dbo.Table_Temporal_Historico'. - Las declaraciones INSERT y UPDATE no pueden hacer referencia a columnas del período SYSTEM_TIME
Mensaje 13537, Nivel 16, Estado 1, Línea 5
No se pueden actualizar las columnas GENERADAS SIEMPRE en la tabla 'dirceuresende.dbo.Table_Temporal'.
¿Qué tablas son temporales en mi base de datos?
Ver contenidoSELECT
A.[name],
A.[object_id],
A.temporal_type,
A.temporal_type_desc,
A.history_table_id,
B.[name]
FROM
sys.tables A
LEFT JOIN sys.tables B ON B.[object_id] = A.history_table_id
ORDER BY
A.temporal_type DESC
¿Cómo crear una Tabla Temporal (Versionada)?
Ver contenido- Dt_Inicio DATETIME2 GENERADA SIEMPRE COMO INICIO DE FILA
- Dt_Fim DATETIME2 GENERADO SIEMPRE COMO FINAL DE FILA
Y también se agregará la cláusula PERIOD FOR SYSTEM_TIME (Dt_Start, Dt_Fim) después de estas columnas y también la cláusula CON (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Table_Historico)) al final del comando CREATE para su tabla.
Ahora demostraré una CREATE TABLE completa para que sea más fácil entender cómo crear una tabla temporal:
USE [dirceuresende]
GO
CREATE TABLE dbo.Tabela_Temporal (
-- Dados normais da tabela
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
Ds_Nome VARCHAR(100) NOT NULL,
Dt_Nascimento DATETIME NOT NULL,
Nr_Telefone VARCHAR(15) NOT NULL,
Nr_CPF VARCHAR(14) NOT NULL,
-- Informações referentes ao versionamento (Temporal table)
Dt_Inicio DATETIME2(0) GENERATED ALWAYS AS ROW START,
Dt_Fim DATETIME2(0) GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (Dt_Inicio, Dt_Fim)
) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Tabela_Temporal_Historico))
Después de crear una tabla temporal (versionado del sistema), la pantalla del Explorador de objetos de SQL Server Management Studio mostrará la tabla de la siguiente manera:

¿Cómo convertir una tabla común a una tabla temporal?
Ver contenidoUSE [dirceuresende]
GO
-- Criação normal de uma tabela
CREATE TABLE dbo.Tabela_Comum (
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
Ds_Nome VARCHAR(100) NOT NULL,
Dt_Nascimento DATETIME NOT NULL,
Nr_Telefone VARCHAR(15) NOT NULL,
Nr_CPF VARCHAR(14) NOT NULL,
) WITH(DATA_COMPRESSION=PAGE)
-- Crio as colunas de metadados para controlar a validade dos registros
ALTER TABLE dbo.Tabela_Comum ADD
Dt_Inicio DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
Dt_Fim DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (Dt_Inicio, Dt_Fim)
-- Ativo o versionamento na tabela
ALTER TABLE dbo.Tabela_Comum SET (SYSTEM_VERSIONING=ON (HISTORY_TABLE = dbo.Tabela_Comum_Historico))
¿Qué pasa si la tabla ya tiene registros? Bueno, en este caso simplemente crea las columnas con una restricción para incluir un valor DEFAULT en las columnas que se crearán ahora y que no tienen ningún valor:
USE [dirceuresende]
GO
-- Criação normal de uma tabela
CREATE TABLE dbo.Tabela_Comum (
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
Ds_Nome VARCHAR(100) NOT NULL,
Dt_Nascimento DATETIME NOT NULL,
Nr_Telefone VARCHAR(15) NOT NULL,
Nr_CPF VARCHAR(14) NOT NULL,
) WITH(DATA_COMPRESSION=PAGE)
INSERT INTO dbo.Tabela_Comum
(
Ds_Nome,
Dt_Nascimento,
Nr_Telefone,
Nr_CPF
)
VALUES
(
'Dirceu Resende', -- Ds_Nome - varchar(100)
'1990-01-01', -- Dt_Nascimento - datetime
'2799999999', -- Nr_Telefone - varchar(15)
'11111111111' -- Nr_CPF - varchar(14)
)
-- Crio as colunas de metadados para controlar a validade dos registros
ALTER TABLE dbo.Tabela_Comum ADD
Dt_Inicio DATETIME2 GENERATED ALWAYS AS ROW START CONSTRAINT DF_Tabela_Comum_Dt_Inicio DEFAULT SYSUTCDATETIME() NOT NULL,
Dt_Fim DATETIME2 GENERATED ALWAYS AS ROW END CONSTRAINT DF_Tabela_Comum_Dt_Fim DEFAULT '9999-12-31 23:59:59.9999999' NOT NULL,
PERIOD FOR SYSTEM_TIME (Dt_Inicio, Dt_Fim)
-- Ativo o versionamento na tabela
ALTER TABLE dbo.Tabela_Comum SET (SYSTEM_VERSIONING=ON (HISTORY_TABLE = dbo.Tabela_Comum_Historico))
Con la consulta anterior crearás nuevas columnas con Dt_Start = fecha/hora actual y Dt_End = fecha máxima de datetime2, es decir, todos los registros de la tabla se considerarán registros actuales.
¿Cómo consultar datos de la Tabla Temporal?
Ver contenidoINSERT INTO dbo.Tabela_Temporal
(
Ds_Nome,
Dt_Nascimento,
Nr_Telefone,
Nr_CPF
)
VALUES
(
'Dirceu Resende', -- Ds_Nome - varchar(100)
'1900-05-28', -- Dt_Nascimento - datetime
'2799999999', -- Nr_Telefone - varchar(15)
'12345678909'
),
(
'Teste 2', -- Ds_Nome - varchar(100)
'1900-01-01', -- Dt_Nascimento - datetime
'27888888888', -- Nr_Telefone - varchar(15)
'11111111111'
)
UPDATE dbo.Tabela_Temporal
SET Ds_Nome = 'Teste'
WHERE Ds_Nome = 'Teste 2'
UPDATE dbo.Tabela_Temporal
SET Nr_CPF = '22222222222'
WHERE Ds_Nome = 'Dirceu Resende'
DELETE FROM dbo.Tabela_Temporal
WHERE Ds_Nome = 'Teste'
En los ejemplos anteriores, utilicé la cláusula COMO DE 'datos'. Existen 5 tipos de cláusulas para especificar el rango de fechas deseado:
- TODO: Devuelve todos los cambios realizados en la tabla
- A PARTIR DE: Función de punto en el tiempo, es decir, devuelve datos en una fecha y hora específicas
- DESDE
HASTA : Devuelve todos los registros cuyo campo Dt_Inicial < fecha de finalización ingresada y campo Dt_Final > fecha de inicio informada. - ENTRE
Y : Devuelve todos los registros cuyo campo Dt_Inicial <= fecha de finalización ingresada y campo Dt_Final > fecha de inicio informada. Esta cláusula es muy similar a la cláusula FROM... TO.. con la única diferencia de que la primera condición también considera registros con igualdad en la condición (<=), mientras que la cláusula FROM.. TO.. no (solo <) - CONTENIDO EN (
, : Devuelve todos los registros cuyo Dt_Inicial >= fecha inicial ingresada y campo Dt_Final <= fecha final ingresada.)
¿Cómo deshabilitar el control de versiones de una tabla temporal?
Ver contenidoALTER TABLE dbo.Tabela_Temporal SET (SYSTEM_VERSIONING = OFF);
ALTER TABLE dbo.Tabela_Temporal DROP PERIOD FOR SYSTEM_TIME;
ALTER TABLE dbo.Tabela_Temporal DROP COLUMN Dt_Inicio, Dt_Fim;
Si solo desea deshabilitar temporalmente la función de control de versiones, pero no desea eliminar la información, puede usar el siguiente comando:
ALTER TABLE dbo.Tabela_Temporal SET (SYSTEM_VERSIONING = OFF);
¿Mi tabla de historial crecerá para siempre?
Ver contenidoBase de datos SQL de Azure
ALTER DATABASE CURRENT SET TEMPORAL_HISTORY_RETENTION ON
GO
ALTER TABLE [dbo].[Tabela_Temporal] SET (SYSTEM_VERSIONING = ON (HISTORY_RETENTION_PERIOD = 30 DAYS))
GO
Servidor SQL (local)
ALTER TABLE dbo.Tabela_Temporal SET (SYSTEM_VERSIONING = OFF)
GO
DELETE FROM dbo.Tabela_Temporal_Historico
WHERE Dt_Fim <= DATEADD(DAY, -30, GETDATE())
ALTER TABLE dbo.Tabela_Temporal
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[Tabela_Temporal_Historico], DATA_CONSISTENCY_CHECK = ON))
¡Eso es todo, amigos!
¡Un fuerte abrazo y hasta luego!
Dirceu Resende
Arquitecto de Bases de Datos y BI · Microsoft MVP · MCSE, MCSA, MCT, MTA, MCP.








Comentários (0)
Carregando comentários…