Cómo encriptar bases de datos MSSQL con TDE

SQL Server desde su versión 2008 tiene la funcionalidad TDE (Transparent Data Encryption) la cual permite encriptar toda la base de datos de forma transparente.

Esta funcionalidad hasta MSSQL 2019 solo estaba disponible en la edición Enterprise pero a partir de 2019 ya se puede usar en la Standard.

En el siguiente video te muestro paso a paso como se configura TDE y funciona como así también algunos tips que seria bueno considerar.

Para poder descargar el material que utilice en el video lo podes hacer desde el siguiente link

Material TDE

¿Es verdad que las variables tipo tabla están en memoria RAM?

¿Las variables tipo Tabla usan la TEMPDB?

Este post tiene como objetivo demostrar uno de los mitos que escucho muy frecuentemente entre programadores y DBA en donde afirman que las variables tipo tabla son mejores que las tablas temporales porque no usan la tempdb y se almacenan en memoria RAM.

Te dejo primero este video explicativo donde te cuento sobre este mito y demuestro que no es así, pero también te cuento como podes realmente usar variables tipo tabla que si residan en memoria RAM.

Link código de ejemplo

Ejemplo 1

En el primer ejemplo declaramos una variable tipo tabla y verificamos en la Tempdb si la usa o no.

USE ADVENTUREWORKS2019 
-------------------------------------------------
--   PRUEBA 1 
-------------------------------------------------
DECLARE @T AS TABLE ([NAME]  VARCHAR(255),
                     [OBJECT_ID] INT,
					 [SCHEMA_ID]  INT,
					 [TYPE_DESC] VARCHAR(255),
					 [CREATE_DATE] DATETIME
					 )
					 
INSERT INTO @T 
SELECT TOP 100 
       NAME,
       OBJECT_ID,
	   SCHEMA_ID,
	   TYPE_DESC,
	   CREATE_DATE
FROM SYS.OBJECTS 

-- MIRAMOS TEMPDB

SELECT
        NAME,
        PS.INDEX_ID,
        PS.ROW_COUNT,
		(PS.USED_PAGE_COUNT * 8.00)/1024.00 AS ESPACIO_MB,
	    CREATE_DATE,
        MODIFY_DATE
    FROM TEMPDB.SYS.OBJECTS AS SO
    JOIN TEMPDB.SYS.DM_DB_PARTITION_STATS PS ON SO.OBJECT_ID = PS.OBJECT_ID
    WHERE
        NAME LIKE N'#%'
        AND ROW_COUNT > 0
GO

La siguiente imagen muestra el resultado de nuestra prueba

Aquí podemos observar que la variable tipo tabla USA la tempdb.

Variables tipo tabla que si usan la memoria

Si deseamos usar variables tipo tabla que realmente usen la RAM y no la Tempdb debemos utilizar memory-optimized table type

Veamos un ejemplo:

USE AdventureWorks2019 
CREATE TYPE dbo.inMemoryTableType  
  AS TABLE 
  (
    [NAME]  VARCHAR(255) INDEX IX1,
    [OBJECT_ID] INT,
	[SCHEMA_ID]  INT,
	[TYPE_DESC] VARCHAR(255),
    [CREATE_DATE] DATETIME
  
  )
  WITH (MEMORY_OPTIMIZED = ON);  
GO
DECLARE @T AS  dbo.inMemoryTableType  
INSERT INTO @T
SELECT TOP 100
       O.NAME,
       O.OBJECT_ID,
	   O.SCHEMA_ID,
	   O.TYPE_DESC,
	   O.CREATE_DATE
FROM SYS.OBJECTS O 

-- MIRAMOS TEMPDB

SELECT
        NAME,
        PS.INDEX_ID,
        PS.ROW_COUNT,
		(PS.USED_PAGE_COUNT * 8.00)/1024.00 AS ESPACIO_MB,
	    CREATE_DATE,
        MODIFY_DATE
    FROM TEMPDB.SYS.OBJECTS AS SO
    JOIN TEMPDB.SYS.DM_DB_PARTITION_STATS PS ON SO.OBJECT_ID = PS.OBJECT_ID
    WHERE
        NAME LIKE N'#%'
        AND ROW_COUNT > 0

Conclusiones

Las variables tipo tabla usan la TEMPDB al igual que las tablas temporales, entonces ¿Cuál es la diferencia entre ambas? pues de funcionalidad , aquí les paso el siguiente cuadro.

Some feature differences between table variable and #temporary tables

Material charla tips de migraciones SQL Server

El pasado 1 de diciembre de 2021 en conjunto con el Grupo de Usuarios Microsoft Argentina (MUG) di una charla en donde te cuento en base a mi experiencia como deberías encarar un proyecto de migración de tu SQL Server ya sea hacia ambientes on-premise o la nube.

Comparto el video de la misma como así también la presentación y material

Presentación y ejemplos

Curso gratuito de consultas en TSQL de 0 a 100

Este es el contenido del curso online gratuito que estoy dando en conjunto con la gente de ITBA Computer Society en el cual en base a ejemplos prácticos enseñare el uso de TSQL para hacer consultas.

Para poder descargar el material del curso lo pueden hacer por medio del siguiente enlace de GitHUB

En este post dejare cada video de las 4 clases de 90 minutos cada una

Video Clase 1

Video Clase 2

Video clase 3

Video clase 4

Calculando acumulados en T-SQL

En algunas ocasiones tenemos la necesidad de armar consultas en T-SQL para retornar acumulados.

Imaginemos el siguiente resultado

Lo que nosotros tenemos es una tabla la cual contiene TRANID, PRODUCTID,TRANSACTIONDATE y QUANTITY y necesitamos calcular la columna total que como podemos observar hace un acumulado con la particularidad de poner en 0 de nuevo cada vez que cambia el código de producto.

En este tutorial te voy a mostrar las alternativas para poder resolver esto y cual es la mas eficiente de todas

Para poder ejecutar el código de ejemplo he utilizado la base de datos de ejemplos Adventureworks

Código de ejemplo utilizado en el video

USE ADVENTUREWORKS2019 
GO
-- PREPARAR DATOS DE PRUEBA
DROP TABLE IF EXISTS MOVIMIENTOS 
SELECT IDENTITY(INT, 1,1) AS TRANID
      ,[PRODUCTID]
      ,[TRANSACTIONDATE]
      ,[QUANTITY] * FLOOR(10 * RAND(CONVERT(VARBINARY, NEWID())))  AS QUANTITY
  INTO MOVIMIENTOS	
  FROM [ADVENTUREWORKS2019].[PRODUCTION].[TRANSACTIONHISTORY]
  CROSS JOIN (SELECT TOP 10 * FROM SYS.COLUMNS) AS C
  ORDER BY PRODUCTID,TRANID 

---------------------------------------
------    USANDO OVER
----------------------------------------
SELECT [TRANID]
      ,[PRODUCTID]
      ,[TRANSACTIONDATE]
      ,[QUANTITY]
	  , SUM(QUANTITY) 
	    OVER(PARTITION BY PRODUCTID ORDER BY TRANID) AS TOTAL  
  FROM DBO.MOVIMIENTOS 
  ORDER BY PRODUCTID,TRANID 

--------------------------------------
-- USANDO CURSORES Y TABLAS TEMPORALES
---------------------------------------

DECLARE @RESULT AS TABLE (TRANID INT,
                          PRODUCTID INT,
						  TRANSACTIONDATE DATETIME,
						  QUANTITY INT,
						  TOTAL INT
						  )
DECLARE
  @TRANID    AS INT,
  @PREVPRODUCTID AS INT,
  @PRODUCTID AS INT,
  @TRANSACTIONDATE   AS DATETIME,
  @QUANTITY  AS INT,
  @TOTAL  AS INT;

DECLARE C CURSOR FAST_FORWARD FOR
  SELECT TRANID,PRODUCTID,TRANSACTIONDATE,QUANTITY    
  FROM DBO.MOVIMIENTOS
  ORDER BY PRODUCTID,TRANID;
OPEN C
FETCH NEXT FROM C INTO @TRANID, @PRODUCTID, @TRANSACTIONDATE,@QUANTITY

SELECT @PREVPRODUCTID = @PRODUCTID , @TOTAL  = 0;

WHILE @@FETCH_STATUS = 0
BEGIN
  IF @PRODUCTID  <> @PREVPRODUCTID 
    SELECT @PREVPRODUCTID = @PRODUCTID , @TOTAL  = 0;
;

  SET @TOTAL = @TOTAL + @QUANTITY;
  INSERT INTO @RESULT 
  VALUES(@TRANID, @PRODUCTID, @TRANSACTIONDATE ,  @QUANTITY,@TOTAL);
 
  FETCH NEXT FROM C INTO @TRANID, @PRODUCTID, @TRANSACTIONDATE,@QUANTITY;
END

CLOSE C;
DEALLOCATE C;

SELECT * FROM @RESULT 
ORDER BY PRODUCTID,TRANID  

------------------------------------
-- USANDO SUBQUERY
-------------------------------------
SELECT T1.PRODUCTID , T1.TRANID, T1.QUANTITY ,
  SUM(T2.QUANTITY ) AS TOTAL
FROM DBO.MOVIMIENTOS AS T1
  JOIN DBO.MOVIMIENTOS AS T2
    ON T2.PRODUCTID  = T1.PRODUCTID 
   AND T2.TRANID <= T1.TRANID
GROUP BY T1.PRODUCTID , T1.TRANID, T1.QUANTITY
ORDER BY 1,2;