(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo enmascarar datos sensibles en Azure SQL (Data Masking)

João Barros 05 de July de 2026 4 min de lectura

Proteger datos personales como emails y numeros de tarjeta es un requisito basico de gobernanza de datos, y no siempre obliga a reescribir la aplicacion. Dynamic Data Masking en Azure SQL oculta columnas sensibles en los resultados de las consultas y muestra los valores reales solo a quien tiene permiso. Asi, un analista solo ve aXXX@XXXX.com mientras los datos de la tabla permanecen intactos.

Requisitos previos

  • Una base de datos en Azure SQL Database (o SQL Server 2022) donde tengas permisos de administrador.
  • Una herramienta de consulta como SQL Server Management Studio (SSMS) o Azure Data Studio.
  • Conocimientos basicos de T-SQL (CREATE TABLE, SELECT, ALTER TABLE).

Paso 1: Crear una tabla de ejemplo

Empecemos con una tabla de clientes que contiene datos sensibles. Ejecuta el siguiente script para crearla e insertar algunos registros:

CREATE TABLE dbo.Clientes (
    ClienteID   INT IDENTITY PRIMARY KEY,
    Nome        NVARCHAR(100),
    Email       NVARCHAR(100),
    Telemovel   VARCHAR(20),
    Cartao      VARCHAR(19)
);

INSERT INTO dbo.Clientes (Nome, Email, Telemovel, Cartao)
VALUES
 (N'Ana Silva',   'ana.silva@email.pt',   '912345678', '4111111111111111'),
 (N'Bruno Costa', 'bruno.costa@email.pt', '936000111', '5500005555555559');

Paso 2: Aplicar mascaras a las columnas sensibles

Una mascara se define por columna con la clausula ADD MASKED WITH (FUNCTION = '...'). Cada funcion oculta los datos de una forma distinta. Vamos a enmascarar el email, el telefono y la tarjeta:

-- email(): mostra a 1.a letra e o dominio -> aXXX@XXXX.com
ALTER TABLE dbo.Clientes
    ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()');

-- partial(): mostra apenas os ultimos 3 digitos -> XXXXXX678
ALTER TABLE dbo.Clientes
    ALTER COLUMN Telemovel ADD MASKED WITH (FUNCTION = 'partial(0,"XXXXXX",3)');

-- default(): esconde o valor por completo -> XXXX
ALTER TABLE dbo.Clientes
    ALTER COLUMN Cartao ADD MASKED WITH (FUNCTION = 'default()');

La funcion partial(prefijo, relleno, sufijo) es la mas flexible: el primer numero indica cuantos caracteres iniciales conservar, el texto entre comillas es el relleno visible y el ultimo numero cuantos caracteres finales conservar. Por su parte, default() aplica la mascara predeterminada del tipo — XXXX para texto, 0 para numeros y una fecha fija para fechas.

Paso 3: Crear un usuario para probar

Las mascaras no se aplican a los administradores (miembros de db_owner), por lo que no veras ningun efecto con tu propia cuenta. Para comprobarlo, crea un usuario sin privilegios y concedele solo permiso de lectura:

CREATE USER analista WITHOUT LOGIN;
GRANT SELECT ON dbo.Clientes TO analista;

Paso 4: Confirmar la mascara con EXECUTE AS

Puedes suplantar temporalmente a ese usuario para ver los datos exactamente como los veria el, sin cambiar de sesion:

EXECUTE AS USER = 'analista';
SELECT Nome, Email, Telemovel, Cartao FROM dbo.Clientes;
REVERT;

El resultado muestra los emails como aXXX@XXXX.com, el telefono terminando en sus ultimos digitos y la tarjeta totalmente oculta. Los datos en la base de datos siguen intactos: solo cambia la presentacion.

Paso 5: Conceder excepciones con UNMASK

Si un perfil concreto necesita ver los valores reales (por ejemplo, atencion al cliente), concedele el permiso UNMASK. Desde SQL Server 2022 y en Azure SQL puedes hacerlo tambien a nivel de columna:

-- Acesso total aos valores reais
GRANT UNMASK TO analista;

-- Ou apenas a uma coluna (granular, SQL Server 2022 / Azure SQL)
GRANT UNMASK ON dbo.Clientes(Email) TO analista;

Para retirar la excepcion mas adelante, usa REVOKE UNMASK .... Concede siempre el minimo que cada perfil necesita.

Verificar el resultado

Para listar todas las columnas enmascaradas y la funcion aplicada, consulta la vista de sistema sys.masked_columns:

SELECT t.name AS Tabela, c.name AS Coluna, c.masking_function AS Mascara
FROM sys.masked_columns AS c
JOIN sys.tables AS t ON c.object_id = t.object_id
WHERE c.is_masked = 1;

Deberias ver las tres columnas con su funcion de mascara. Si vuelves a ejecutar el SELECT con EXECUTE AS despues del GRANT UNMASK, los valores aparecen ahora sin mascara.

Conclusion

Con solo unas pocas lineas de T-SQL has protegido datos sensibles sin tocar la aplicacion ni duplicar tablas. El siguiente paso es definir tu estrategia de excepciones: quien necesita realmente UNMASK y en que columnas. Recuerda que el enmascaramiento es una capa de presentacion, no seguridad absoluta: combinalo siempre con control de accesos y, cuando sea posible, cifrado. Que columnas de tu base de datos merecen una mascara hoy?