Cómo crear tablas Ledger en Azure SQL: paso a paso
Las tablas Ledger de Azure SQL guardan un historial protegido criptográficamente de todos los cambios en los datos. Crear tablas Ledger en Azure SQL permite demostrar a un auditor que ningún registro fue manipulado, sin escribir una sola línea de código en la aplicación: el propio motor registra cada INSERT, UPDATE y DELETE.
Requisitos previos
- Una base de datos en Azure SQL Database (la funcionalidad también existe en SQL Server 2022 y posteriores).
- Permisos para crear tablas (por ejemplo, ser miembro de
db_owner). - SQL Server Management Studio (SSMS) o Azure Data Studio conectado a la base de datos.
- Conocimientos básicos de T-SQL.
Paso 1: Elegir el tipo de tabla Ledger
Existen dos tipos y la elección depende de lo que la tabla necesite hacer:
- Updatable ledger table — acepta INSERT, UPDATE y DELETE. Cada cambio queda registrado en una tabla de historial y visible en una vista Ledger.
- Append-only ledger table — solo acepta INSERT. Cualquier intento de UPDATE o DELETE es bloqueado por el motor. Ideal para logs de eventos o registros de accesos.
Para datos de negocio que cambian (pagos, contratos, saldos) use la versión actualizable. Para datos que nunca deberían cambiar, use append-only.
Paso 2: Crear una tabla Ledger actualizable
La creación es un CREATE TABLE normal con la cláusula LEDGER = ON. Conviene dar nombres explícitos a la tabla de historial y a la vista Ledger, para encontrarlas fácilmente después:
CREATE TABLE dbo.Pagamentos
(
PagamentoID INT IDENTITY(1,1) PRIMARY KEY,
Cliente NVARCHAR(100) NOT NULL,
Valor DECIMAL(10,2) NOT NULL,
Estado NVARCHAR(20) NOT NULL
)
WITH (
SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Pagamentos_History),
LEDGER = ON (LEDGER_VIEW = dbo.Pagamentos_Ledger)
);
El motor crea automáticamente columnas de sistema que identifican la transacción que insertó o eliminó cada versión de la fila.
Paso 3: Insertar y modificar datos
A partir de aquí trabaja con la tabla como con cualquier otra. No hace falta sintaxis especial:
INSERT INTO dbo.Pagamentos (Cliente, Valor, Estado)
VALUES (N'Ana Silva', 250.00, N'Pendente');
UPDATE dbo.Pagamentos
SET Estado = N'Pago'
WHERE Cliente = N'Ana Silva';
Paso 4: Consultar el historial en la vista Ledger
La vista Ledger muestra lo que ocurrió con cada fila a lo largo del tiempo. Un UPDATE aparece como un par de operaciones: la versión antigua se marca como DELETE y la nueva como INSERT.
SELECT Cliente,
Valor,
Estado,
ledger_transaction_id,
ledger_sequence_number,
ledger_operation_type_desc
FROM dbo.Pagamentos_Ledger
ORDER BY ledger_transaction_id, ledger_sequence_number;
Es ese par INSERT/DELETE lo que permite reconstruir el valor de cualquier fila en cualquier momento del pasado.
Paso 5: Descubrir quién ejecutó cada transacción
La vista de sistema sys.database_ledger_transactions guarda el autor y el momento de cada transacción registrada:
SELECT t.transaction_id,
t.principal_name,
t.commit_time
FROM sys.database_ledger_transactions AS t
ORDER BY t.commit_time DESC;
Al cruzar transaction_id con ledger_transaction_id de la vista Ledger, sabrá quién cambió qué y cuándo.
Paso 6: Crear una tabla append-only
Para registros que nunca deben modificarse, como un log de accesos:
CREATE TABLE dbo.Acessos
(
AcessoID INT IDENTITY(1,1) PRIMARY KEY,
Utilizador NVARCHAR(100) NOT NULL,
DataHora DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
)
WITH (LEDGER = ON (APPEND_ONLY = ON));
Verificar el resultado
Primero, confirme que las tablas se crearon con el tipo Ledger correcto:
SELECT name, ledger_type_desc
FROM sys.tables
WHERE ledger_type_desc IS NOT NULL;
Después, haga la prueba que realmente importa: intente modificar una fila de la tabla append-only.
UPDATE dbo.Acessos SET Utilizador = N'outro' WHERE AcessoID = 1;
El motor devuelve un error y la operación no se realiza — ni siquiera el administrador de la base de datos puede forzarla. En la tabla actualizable el UPDATE funciona, pero la versión anterior sigue visible en la vista dbo.Pagamentos_Ledger. Si ocurren ambas cosas, todo está correcto.
Conclusión
En pocos minutos ha conseguido, dentro de la base de datos, una garantía de integridad que antes exigía triggers, tablas de auditoría manuales y mucha confianza. El siguiente paso es automatizar la generación de digests hacia almacenamiento inmutable y luego usar los procedimientos de verificación del Ledger para demostrar, matemáticamente, que el historial no fue tocado. Un consejo final: una tabla Ledger no desaparece con un DROP TABLE — queda marcada como dropped y el historial se mantiene. ¿Cuál de sus tablas actuales ganaría más si pasara a append-only?