Scripts y Utilerías para SQL Server

Colección de scripts útiles para administración, monitoreo, respaldos y optimización.

Scripts para SQL Server

Organizados por categoría para que encuentres lo que necesitas.

🔧

Configuración de la Instancia

Administración

Muestra información detallada de la instancia de Base de Datos (versión, hardware, configuración)

DECLARE    @xp_msver table(    id                int
                             , name              sysname
                             , internal_value    int
                             , character_value   nvarchar(4000) );
     
    INSERT INTO @xp_msver                    
        EXEC    master.dbo.xp_msver ProcessorCount;
    INSERT INTO @xp_msver                    
        EXEC    master.dbo.xp_msver PhysicalMemory;
     
    SELECT    CONVERT(int, CONVERT(char, current_timestamp, 112)) AS CaptureDate
            , SERVERPROPERTY ('ServerName') AS [ServerName]
            , SERVERPROPERTY ('ComputerNamePhysicalNetBIOS') AS [ComputerNamePhysicalNetBIOS]
            , SERVERPROPERTY ('MachineName') AS [MachineName]
            , SERVERPROPERTY ('InstanceName') AS [InstanceName]
            , SERVERPROPERTY ('Edition') AS [SQL Server Edition]
            , SERVERPROPERTY ('ProductVersion') AS [ProductVersion]
            , SERVERPROPERTY ('ProductLevel') AS [ProductLevel]
            , SERVERPROPERTY ('IsClustered') AS [IsClustered]
            , SERVERPROPERTY ('IsIntegratedSecurityOnly') AS [IsIntegratedSecurityOnly]
            , SERVERPROPERTY ('IsSingleUser') AS [IsSingleUser]
            , SERVERPROPERTY ('LicenseType') AS [LicenseType]
            , SERVERPROPERTY ('NumLicenses') AS [NumLicenses]
            , SERVERPROPERTY ('ProcessID') AS [ProcessID]
            , CAST(xp1.ProcessorCount AS int) AS ProcessorCount
            , CAST(xp2.PhysicalMemory AS int) AS PhysicalMemory
            , dt.DefaultTraceEnabled
           --, df.DefaultTracePath
            , rde.RemoteDACEnabled
            , (    SELECT    create_date
                FROM    sys.databases
                WHERE    database_id = 2) AS SQLServerStartDate
            , (    SELECT    DATEDIFF(day, create_date, current_timestamp)
                FROM    sys.databases
                WHERE    database_id = 2) As DaysSinceSQLServerStart
    FROM    (SELECT    character_value AS ProcessorCount FROM @xp_msver WHERE name = 'ProcessorCount') xp1
            CROSS JOIN
             (SELECT    internal_value AS PhysicalMemory FROM @xp_msver WHERE name = 'PhysicalMemory') xp2
            CROSS JOIN
             (SELECT value_in_use AS DefaultTraceEnabled FROM sys.configurations WHERE name = 'default trace enabled') dt
            CROSS JOIN
            (SELECT value_in_use AS RemoteDACEnabled FROM sys.configurations WHERE name = 'remote admin connections') rde
           --CROSS JOIN
           --(SELECT NULL AS DefaultTracePath) df
           --(SELECT VALUE AS DefaultTracePath FROM fn_trace_getinfo(0) WHERE property = 2) df
🔧

Implementación de Configuraciones

Administración

Implementa Configuraciones de Instancia y Base de Datos (memoria, auditoría, seguridad)

Warning!! No ejecutar el script de corrido

Warning 2!! Los Valores deben ser modificados en base a sus ambientes y siempre implementar primero en Desarollo

/*CONFIGURACIONES A NIVEL INSTANCIA*/
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
--Max Server Memory & Min Server Memory
-- Validar
SELECT 
    name AS Configuracion,
    value_in_use AS ValorActual_MB
FROM 
    sys.configurations
WHERE 
    name IN ('min server memory (MB)', 'max server memory (MB)');
go
-- Modificar (ejemplo con 4096 MB como mínimo y 8192 MB como máximo)
EXEC sp_configure 'min server memory (MB)', 4096;
EXEC sp_configure 'max server memory (MB)', 8192;
RECONFIGURE;

--Optimize for Ad hoc Workloads
-- Validar
SELECT 
    name AS Configuracion,
    value_in_use AS ValorActual_MB
FROM 
    sys.configurations
WHERE 
    name IN ('optimize for ad hoc workloads');

-- Modificar
EXEC sp_configure 'optimize for ad hoc workloads', 1;
RECONFIGURE;


--Backup Compression Default
-- Validar
SELECT value FROM sys.configurations WHERE name = 'backup compression default';

-- Modificar
EXEC sp_configure 'backup compression default', 1;
RECONFIGURE;

--Login Audits: Success & Failed
-- Validar
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\Microsoft SQL Server\MSSQLSERVER\',
N'AuditLevel'

-- Modificar (2 = Success & Failed)
EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'AuditLevel', REG_DWORD, 2
GO
--REG_DWORD, 0 = None
--REG_DWORD, 1 = Successful logins only
--REG_DWORD, 2 = Failed logins only
--REG_DWORD, 3 = Both Failed and Successful logins

--Errorlog Recycling
-- Validar
declare @NumErrlog nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\Microsoft SQL Server\MSSQLSERVER\',
N'NumErrorLogs',
@NumErrlog OUTPUT
select @NumErrlog
-- Modificar
EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE',
    N'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer',
    N'NumErrorLogs', REG_DWORD, 99;

--Cross-database Ownership Chaining
-- Validar
EXEC sp_configure 'cross db ownership chaining';

-- Modificar
EXEC sp_configure 'cross db ownership chaining', 0;
RECONFIGURE;


/*CONFIGURACIONES A NIVEL DE BASE DE DATOS*/
-- Modificaciones a Base de Datos Model para futuras creaciones de Bases de Datos
--Auto Shrink Off
-- Validar
SELECT name, is_auto_shrink_on FROM sys.databases Where name='model';

-- Modificar
ALTER DATABASE model SET AUTO_SHRINK OFF;

--Auto create / Update Statistics On
-- Validar
SELECT name, is_auto_create_stats_on, is_auto_update_stats_on FROM sys.databases;

-- Modificar
ALTER DATABASE model SET AUTO_CREATE_STATISTICS ON;
ALTER DATABASE model SET AUTO_UPDATE_STATISTICS ON;

--Page Verify = CHECKSUM
-- Validar
SELECT name, page_verify_option_desc FROM sys.databases;

-- Modificar
ALTER DATABASE model SET PAGE_VERIFY CHECKSUM;


/*SEGURIDAD DE USUARIOS*/

--Enforce Password Policy & Password Expiration
-- Validar
SELECT name, is_policy_checked, is_expiration_checked FROM sys.sql_logins;

-- Modificar
ALTER LOGIN [usuario] WITH CHECK_POLICY = ON, CHECK_EXPIRATION = ON;

--Renombrar usuario SA y asignar contraseña
-- Validar
SELECT name FROM sys.sql_logins WHERE name LIKE '%sa%';

-- Modificar
ALTER LOGIN sa WITH NAME = [NuevoNombre], PASSWORD = 'ContraseñaSegura123!';
🔧

Valida Retención de Log

Administración

Muestra estado de bases de datos y si algún proceso está reteniendo el Log de Transacciones

--Valida si algún proceso impide el truncado del Log
Select name as base_datos, log_reuse_wait, log_reuse_wait_desc, recovery_model_desc as modo_recuperacion_log, page_verify_option_desc as page_verify_bbdd, user_access_desc as user_access, state_desc as estado_bbdd  
from sys.databases
🔧

Health Check

Administración

Recolecta información extensa del sistema (registro, servicios, IIS)

SET NOCOUNT ON 
 
--Inicialización de variables y Tablas Temporales
CREATE TABLE #Instance (value VARCHAR(50),data VARCHAR(50)) 
CREATE TABLE #AuditData (value VARCHAR(50),data VARCHAR(100)) 
CREATE TABLE #msver (indx INT, name VARCHAR(50), internal_value INT, character_value VARCHAR(255)) 
CREATE TABLE #WinverSP (value    VARCHAR (255),data VARCHAR(255)) 
 
DECLARE @Instance VARCHAR(50) 
DECLARE @InstanceLoc VARCHAR(50) 
DECLARE @RegKey VARCHAR(255) 
DECLARE @CPUCount INT 
DECLARE @CPUID INT 
DECLARE @AffinityMask INT 
DECLARE @CPUList VARCHAR(50) 
DECLARE @InstCPUCount INT 
DECLARE @sql VARCHAR(255) 
DECLARE @Database VARCHAR(50) 
DECLARE @WINVERSP VARCHAR(255) 
 
INSERT INTO #msver EXEC xp_msver  
 
--Obtener Versión y Nivel de Service Pack de Windows
SET @RegKey = 'SOFTWARE\Microsoft\Windows NT\CurrentVersion' 
INSERT INTO #WinverSP EXEC xp_regread 'HKEY_LOCAL_MACHINE',@regkey,'ProductName' 
INSERT INTO #WinverSP EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'CSDVersion' 
 
PRINT '' 
PRINT 'Windows Server version and Service pack values' 
SELECT CAST(value AS VARCHAR(50)) AS value,  
       CAST(data AS VARCHAR(50)) AS data  
  FROM #WinverSP 
 
--Obtener ubicación de la Instancia del Registro de Windows
SET @RegKey = 'SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' 
 
INSERT INTO #Instance EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, @@servicename 
 
SELECT @InstanceLoc=data FROM #Instance WHERE VALUE = @@servicename 
 
--Obtiene Información de Auditorías del registro de Windowsw y la inserta en #AuditData
 
SET @RegKey = 'SOFTWARE\Microsoft\Microsoft SQL Server\' + @InstanceLoc + '\Setup' 
 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'Edition' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'SqlCluster' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'SqlProgramDir' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'SQLDataRoot' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'SQLPath' 
 
SET @RegKey = 'SOFTWARE\Microsoft\Microsoft SQL Server\' + @InstanceLoc + '\MSSQLSERVER' 
 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'AuditLevel' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'LoginMode' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'DefaultData' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'DefaultLog' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'BackupDirectory' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'NumErrorLogs' 
 
SET @RegKey = 'SOFTWARE\Microsoft\Microsoft SQL Server\' + @InstanceLoc + '\SQLServerAgent' 
 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'RestartSQLServer' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'RestartServer' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'UseDatabaseMail' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'DatabaseMailProfile' 
 
SET @RegKey = 'SOFTWARE\Microsoft\Microsoft SQL Server\' + @InstanceLoc + '\MSSQLSERVER\SuperSocketNetLib\Tcp\IPAll' 
 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'TcpDynamicPorts' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE', @RegKey, 'TcpPort' 
INSERT INTO #AuditData EXEC xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\McAfee\VSCore\On Access Scanner\McShield\Configuration\Default', 'szExcludeExts' 
 
 
UPDATE #AuditData  
   SET value = 'Antivirusprofile' where  value = 'szExcludeExts' 
   
UPDATE #AuditData  
   SET data =   
      CASE  
         WHEN data = 0 THEN 'Configuración: no logins' 
         WHEN data = 1 THEN 'Configuración: only success login attempts' 
         WHEN data = 2 THEN 'Configuración: only failed login attempts' 
         WHEN data = 3 THEN 'Configuración: both success and failed login attempts' 
         ELSE data  
      END 
 WHERE value IN ('AuditLevel') 
 
UPDATE #AuditData  
   SET data =   
      CASE  
         WHEN data = 1 THEN 'Windows Authentication' 
         WHEN data = 2 THEN 'Mixed Mode Authentication' 
         ELSE data  
      END 
 WHERE value IN ('LoginMode') 
 
UPDATE #AuditData  
   SET data =   
      CASE  
         WHEN data = 0 THEN 'FALSE' 
         WHEN data = 1 THEN 'TRUE' 
         ELSE data  
      END 
 WHERE value IN ('RestartServer','RestartSQLServer','SqlCluster','UseDatabaseMail') 
 
--Mostrar Resultados
PRINT '' 
PRINT 'Muestra Nombre de la Instancia SQL' 
SELECT CAST(@@servicename AS VARCHAR(25)) AS instance 
 
PRINT '' 
PRINT 'Muestra la ubicación de la Instancia' 
SELECT CAST(value AS VARCHAR(25)) AS instance,  
       CAST(data AS VARCHAR(25)) AS location  
  FROM #Instance 
 
PRINT '' 
PRINT 'Muestra Información de la Instancia' 
SELECT CAST(name AS VARCHAR(25)) AS name,  
       CAST(character_value AS VARCHAR(50)) AS value  
  FROM #msver 
 WHERE name in ('productname','productversion','platform','filedescription') 
 
PRINT '' 
PRINT 'Muestra Información de Auditorías' 
SELECT CAST(value AS VARCHAR(25)) AS value,  
       CAST(data AS VARCHAR(100)) AS data  
  FROM #AuditData 
 ORDER BY value 
 
PRINT '' 
PRINT 'Muestra el Collation del Servidor' 
SELECT SERVERPROPERTY( 'Collation' ) AS Server_Default_Collation; 
 
PRINT '' 
PRINT 'Vaida Tamaños de Archivos de Bases de Datos de Sistema'  
 
DECLARE databases_cursor CURSOR FOR  
      SELECT name  
      FROM sysdatabases 
      WHERE name IN ('master','model','msdb','tempdb') 
      ORDER BY name 
 
OPEN databases_cursor 
FETCH NEXT FROM databases_cursor INTO @Database 
 
WHILE @@FETCH_STATUS = 0 
BEGIN 
       
      PRINT '   - ' + @Database 
      SET @sql = 'SELECT fileid, ' 
      SET @sql = @sql + 'CAST(name AS VARCHAR(25)) as name, ' 
      SET @sql = @sql + 'CAST(filename AS VARCHAR(75)) as filename, ' 
      SET @sql = @sql + '(size*8)/1024 as [size-mb], ' 
      SET @sql = @sql + 'maxsize as [max-8kb pages], growth ' 
      SET @sql = @sql + 'FROM ' + @Database + '..sysfiles ' 
      SET @sql = @sql + 'ORDER BY groupid DESC, name ASC ' 
 
      EXEC (@sql) 
 
      FETCH NEXT FROM databases_cursor INTO @Database 
    
END 
 
CLOSE databases_cursor 
DEALLOCATE databases_cursor 
 
PRINT '' 
PRINT 'Vaida Tamaños de Archivos de Bases de Datos de Usuario' 
 
DECLARE databases_cursor CURSOR FOR  
      SELECT name  
      FROM sysdatabases 
      WHERE name NOT IN ('master','model','msdb','questsoftware','litespeedlocal','tempdb') 
      ORDER BY name 
 
OPEN databases_cursor 
FETCH NEXT FROM databases_cursor INTO @Database 
 
IF @@FETCH_STATUS <> 0  
      PRINT '         Sin Bases de Datos de Usuario!!' 
 
WHILE @@FETCH_STATUS = 0 
BEGIN 
       
      PRINT '   - ' + @Database 
      SET @sql = 'SELECT fileid, ' 
      SET @sql = @sql + 'CAST(name AS VARCHAR(25)) as name, ' 
      SET @sql = @sql + 'CAST(filename AS VARCHAR(75)) as filename, ' 
      SET @sql = @sql + '(size*8)/1024 as [size-mb], ' 
      SET @sql = @sql + 'maxsize as [max-8kb pages], growth ' 
      SET @sql = @sql + 'FROM ' + @Database + '..sysfiles ' 
      SET @sql = @sql + 'ORDER BY groupid DESC, name ASC ' 
 
      EXEC (@sql) 
 
      FETCH NEXT FROM databases_cursor INTO @Database 
    
END 
 
CLOSE databases_cursor 
DEALLOCATE databases_cursor 
 
--------------------- 
PRINT '' 
PRINT 'Revisa si xp_cmdshell, SQL Mail o Database Mail están habilitados en la Configuración del Área Superficial' 
exec sp_configure 'show advanced options',1 
reconfigure with override 
 
create table #xp_cmd 
( 
name varchar(50), 
minvalue int, 
maxvalue int, 
config_value int, 
run_value int, 
) 
 
insert into #xp_cmd 
exec sp_configure 
 
select name,config_value from #xp_cmd where name in('xp_cmdshell','SQL Mail XPs','Database Mail XPs') 
 
exec sp_configure 'show advanced options',0 
reconfigure with override 
 
drop table #xp_cmd 
 
------------------ 
 
PRINT '' 
PRINT 'Revisa si hay grupos globales de usuarios' 
SELECT CAST(loginname AS VARCHAR(35)) AS loginname,  
       hasaccess,  
       isntname,  
       isntgroup,  
       sysadmin  
  FROM syslogins  
 WHERE name LIKE '%ds_s_amg_sqldba_l%' 
    OR name LIKE '%ds_wimmssqladmin_oa%' 
    OR name LIKE '%ds_wimmssqldba_ap%' 
    OR name LIKE '%ms sql admin%' 
    OR name LIKE '%mssqldba%' 
    OR sysadmin = 1 
    ORDER BY isntname, isntgroup, loginname 
     
PRINT '' 
PRINT 'Revisa si el grupo builtin\administrators se ha eliminado' 
SELECT CAST(loginname AS VARCHAR(35)) AS loginname,  
       hasaccess,  
       isntname,  
       isntgroup,  
       sysadmin  
  FROM syslogins  
 WHERE name LIKE '%administrators%' 
 
PRINT '' 
PRINT 'Revisa si el gupo NT AUTHORITY\SYSTEM se ha eliminado' 
SELECT CAST(loginname AS VARCHAR(35)) AS loginname,  
       hasaccess,  
       isntname,  
       isntgroup,  
       sysadmin  
  FROM syslogins  
 WHERE name LIKE '%SYSTEM%' 
 
PRINT '' 
PRINT 'Revisa si los roles dtsadmin & jobadmin fueron agregados (sql2000)' 
SELECT CAST(name AS VARCHAR(35)) AS name,  
       issqlrole  
  FROM msdb..sysusers  
 WHERE name LIKE 'dtsadminrole' 
    OR name LIKE 'jobadminrole' 
 
PRINT '' 
PRINT 'Valida Configuraciones de Memoria y CPU' 
SELECT CAST(description AS VARCHAR(50)) AS description,  
       CAST(value AS VARCHAR(50)) AS value 
  FROM sys.configurations 
 WHERE name IN ('awe enabled','max server memory (MB)','min server memory (MB)','priority boost') 
 ORDER BY name 
 
PRINT '' 
PRINT 'Valida CPU affinity' 
 
SELECT @CPUCount = internal_value  
  FROM #msver  
 WHERE NAME = 'processorcount' 
 
SELECT @AffinityMask = CAST(value as int)  
  FROM sys.configurations  
 WHERE name = 'affinity mask' 
 
SET @CPUID = 0 
SET @InstCPUCount = 0 
SET @CPUList = '' 
 
IF @AffinityMask = 0 
      BEGIN 
            SET @InstCPUCount = @CPUCount 
            SET @CPUList = 'No affinity set - all CPUs available to instance' 
      END 
ELSE 
      BEGIN 
            WHILE(@CPUID <= @CPUCount - 1) 
                  BEGIN 
                        IF(@AffinityMask & POWER(2, @CPUID)) > 0 
                              BEGIN 
                                    SET @CPUList = @CPUList + 'CPU' + CAST(@CPUID AS VARCHAR(2)) + ' ' 
                                    SET @InstCPUCount = @InstCPUCount + 1 
                              END 
                        SET @CPUID = @CPUID + 1 
                  END 
      END 
 
PRINT 'Total CPU Count            = ' + cast (@CPUCount as varchar(2)) 
PRINT 'Instance CPU Count         = ' + cast (@InstCPUCount as varchar(2)) 
PRINT 'CPUs Assigned to Instance  = ' + @CPUList 
 
 
 
PRINT '' 
PRINT 'Revisa la Coniguración de Operadores' 
SELECT id,  
       CAST(name AS VARCHAR(25)) AS name,  
       enabled,  
       CAST(email_address AS VARCHAR(100)) AS email_address,  
       CAST(pager_address AS VARCHAR(100)) AS pager_address  
  FROM msdb..sysoperators 
 
PRINT '' 
PRINT 'Valida Planes de Mantenimieto Calendarizados y Activos' 
SELECT CAST(j.name AS VARCHAR(50)) AS name,  
       j.date_created,  
       j.date_modified,  
       j.enabled,  
       j.notify_level_email,  
       CAST(o1.name AS VARCHAR(25)) AS email_operator,  
--       CAST(o1.email_address AS VARCHAR(50)) AS email_address,  
       j.notify_level_page,   
       CAST(o2.name AS VARCHAR(25)) AS pager_operator 
--       CAST(o2.pager_address AS VARCHAR(50)) AS pager_address 
  FROM msdb.dbo.sysjobs_view j 
  LEFT JOIN msdb..sysoperators o1  
    ON j.notify_email_operator_id = o1.id 
  LEFT JOIN msdb..sysoperators o2  
    ON j.notify_page_operator_id = o2.id 
 ORDER BY j.name 
 
PRINT '' 
PRINT 'Revisa si hay alertas configuradas' 
SELECT CAST(a.name AS VARCHAR(50)) AS name,  
       CAST(a.event_source AS VARCHAR(20)) AS event_source,  
       a.event_category_id,  
       a.event_id,  
       a.message_id,  
       a.severity,  
       a.enabled,  
       CAST(o1.name AS VARCHAR(25)) AS email_operator,  
--       CAST(o1.email_address AS VARCHAR(100)) AS email_addr,  
       CAST(o2.name AS VARCHAR(25)) AS pager_operator,  
--       CAST(o2.pager_address AS VARCHAR(100)) AS pager_addr, 
       CAST(database_name AS VARCHAR(25)) AS database_name 
  FROM msdb..sysalerts a 
  LEFT JOIN msdb..sysnotifications n1 on a.id = n1.alert_id and n1.notification_method=1 
  LEFT JOIN msdb..sysnotifications n2 on a.id = n2.alert_id and n2.notification_method=2 
  LEFT JOIN msdb..sysoperators o1 on o1.id = n1.operator_id 
  LEFT JOIN msdb..sysoperators o2 on o2.id = n2.operator_id 
 
PRINT '' 
PRINT 'Valida si database mail fue configurado - Enlista las Configuraciones' 
SELECT CAST(name AS VARCHAR(25)) AS account_name,  
       CAST(description AS VARCHAR(25)) AS description 
  FROM msdb.dbo.sysmail_profile 
 ORDER BY name 
 
SELECT CAST(a.name AS VARCHAR(25)) AS account_name,  
       CAST(a.description AS VARCHAR(25)) AS description, 
       CAST(a.email_address AS VARCHAR(50)) AS email_address, 
       CAST(a.display_name AS VARCHAR(25)) AS display_name, 
       CAST(a.replyto_address AS VARCHAR(25)) AS replyto_address, 
       CAST(s.servertype AS VARCHAR(10)) AS servertype, 
       CAST(s.servername AS VARCHAR(25)) AS servername, 
       s.port, 
       CAST(s.username AS VARCHAR(20)) AS username, 
       s.use_default_credentials, 
       s.enable_ssl 
  FROM msdb.dbo.sysmail_account a 
  JOIN msdb.dbo.sysmail_server s ON a.account_id = s.account_id 
 
--clean up 
DROP TABLE #Instance 
DROP TABLE #AuditData 
DROP TABLE #msver 
DROP TABLE #WinverSP 
 
 
--================================= Valida si hay Servicios de IIS en el Servidor ================================ 
PRINT '' 
PRINT 'Valida  Servicios de IIS en el Servidor' 
declare @cdt int 
create table #net_data 
(descriptions varchar(100)) 
 
insert into #net_data exec master..xp_cmdshell 'net start' 
select @cdt=count(*) from #net_data where descriptions like '%IIS%' 
if @cdt > 0   
print 'IIS Service Encontrado en el servidor ' 
else  
print 'NO se Encontro IIS Service intsalado en el servidor ' 
 
drop table #net_data 
 
--================================= Valida las Cuentas de Servicio para SQL Server ================================ 
PRINT '' 
PRINT 'Valida el processid de la instancia sql' 
 
create table #net_data1 
(descriptions varchar(200)) 
 
 
insert into #net_data1 exec master..xp_cmdshell 'sc qc MSSQLSERVER' 
insert into #net_data1 exec master..xp_cmdshell 'sc qc SQLSERVERAGENT' 
insert into #net_data1 exec master..xp_cmdshell 'sc qc msftesql' 
insert into #net_data1 exec master..xp_cmdshell 'sc qc sqlbrowser' 
select * from #net_data1 where descriptions like '%service_start_name%' 
drop table #net_data1 
 
 
--================================= Valida Linked servers ================================ 
PRINT '' 
PRINT 'Muestra detalles de los Linked Servers' 
 
SELECT ss.server_id  
          ,ss.name  
          ,'Server ' = Case ss.Server_id  
                            when 0 then 'Current Server'  
                            else 'Remote Server'  
                            end  
          ,ss.product  
          ,ss.provider  
          ,ss.catalog  
          ,'Local Login ' = case sl.uses_self_credential  
                            when 1 then 'Uses Self Credentials'  
                            else ssp.name  
                            end  
           ,'Remote Login Name' = sl.remote_name  
           ,'RPC Out Enabled'    = case ss.is_rpc_out_enabled  
                                   when 1 then 'True'  
                                   else 'False'  
                                   end  
           ,'Data Access Enabled' = case ss.is_data_access_enabled  
                                    when 1 then 'True'  
                                    else 'False'  
                                    end  
           ,ss.modify_date  
      FROM sys.Servers ss  
 LEFT JOIN sys.linked_logins sl  
        ON ss.server_id = sl.server_id  
 LEFT JOIN sys.server_principals ssp  
        ON ssp.principal_id = sl.local_principal_id 
💾

Backup History

Respaldo

Historial de respaldos con detalles de tamaño, compresión, cifrado y tipo de backup.

--Valida el historial de Respaldos Ejecutados
select a.backup_set_id, a.backup_set_uuid, a.media_set_id, a.name, a.database_name, b.physical_device_name as 'BackupPath',
Case a.type
When 'D' Then 'Database'
When 'L' Then 'Log'
End As backup_type, 
a.recovery_model, a.description, a.database_creation_date, a.backup_start_date, a.backup_finish_date, 
FORMAT((cast(a.backup_size as float)/1024)/1024, 'N2')  as backupSize, 
FORMAT((cast (a.compressed_backup_size as float)/1024)/1024, 'N2') as Compressed_BackupSize, 
a.user_name, a.server_name, a.software_vendor_id, c.software_name as 'BackedUp_By', a.machine_name, a.first_lsn, a.last_lsn, 
Case a.is_password_protected
When 0 Then 'NO'
When 1 Then 'YES'
End As Is_Password_Protected, 
Case a.is_damaged
When 0 Then 'NO'
When 1 Then 'YES'
End As Is_Damaged, 
Case a.has_incomplete_metadata
When 0 Then 'NO'
When 1 Then 'YES'
End As Has_Incomplete_Metadata, 
a.key_algorithm, a.encryptor_type, a.compression_algorithm
from msdb.dbo.backupset as a
Inner Join msdb.dbo.backupmediafamily as b
On a.media_set_id = b.media_set_id
Inner Join msdb.dbo.backupmediaset as c
On a.media_set_id = c.media_set_id
💾

Tomar Respaldo

Respaldo

Respaldo básico de una base de datos. Comando esencial para iniciar con backups.

--Backu Database
USE MyDatabase
GO
BACKUP DATABASE MyDatabase
TO DISK = 'D:\sql\BACKUPS\MyDatabase.bak'
💾

Monitor de Ejecucion de Respaldos y Restaurados

Respaldo

Monitoreo en tiempo real de procesos de backup y restore en ejecución.

--Monitorea el progreso de procesos de Respaldo o Restaurado
SELECT r.session_id, r.command,
       CONVERT(NUMERIC(6,2), r.percent_complete) AS [Percent Complete],
       CONVERT(VARCHAR(20), DATEADD(ms, r.estimated_completion_time, GETDATE()), 20) AS [ETA],
       CONVERT(NUMERIC(10,2), r.total_elapsed_time/1000.0/60.0) AS [Elapsed Min],
       SUBSTRING(t.text, r.statement_start_offset/2,
              CASE WHEN r.statement_end_offset = -1 THEN 1000
                   ELSE (r.statement_end_offset - r.statement_start_offset)/2 END) AS [Command]
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.command IN ('RESTORE DATABASE', 'BACKUP DATABASE')
📊

Monitor de Rendimiento

Monitoreo

Consultas por CPU, lecturas, bloqueos, sugerencias de índices

/*
  SCRIPT DE MONITOREO GRATUITO GM-TECH
  Versión: 1.0
  Descripción: Recolecta métricas clave de rendimiento en SQL Server.
  Instrucciones:
    1. Ejecutar con permisos de lectura en motor (view server state).
    2. Ejecutar en la base de datos master.
    3. Revisar los resultados que aparecen en varios conjuntos de resultados.
*/

-- 1. ESTADO DE ESPERA (WAIT STATS)
SELECT
  wait_type,
  SUM(wait_time_ms)      AS TotalWaitMs,
  SUM(max_wait_time_ms)  AS MaxWaitMs,
  SUM(signal_wait_time_ms) AS SignalWaitMs,
  SUM(waiting_tasks_count) AS WaitingTasks
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
  'CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK',
  'SLEEP_SYSTEMTASK','SQLTRACE_BUFFER_FLUSH','WAITFOR','LOGMGR_QUEUE',
  'CHECKPOINT_QUEUE','REQUEST_FOR_DEADLOCK_SEARCH','XE_TIMER_EVENT',
  'XE_DISPATCHER_WAIT_EVENT','FT_IFTS_SCHEDULER_IDLE_WAIT'
)
GROUP BY wait_type
ORDER BY TotalWaitMs DESC;


-- 2. TOP 10 CONSULTAS POR CPU
SELECT TOP 10
  qs.total_worker_time/1000 AS TotalCPUms,
  qs.total_elapsed_time/1000 AS TotalElapsedMs,
  qs.execution_count,
  qs.total_logical_reads,
  SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
      WHEN -1 THEN DATALENGTH(st.text)
      ELSE qs.statement_end_offset
     END - qs.statement_start_offset)/2)+1) AS QueryText,
  DB_NAME(st.dbid) AS DatabaseName
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY qs.total_worker_time DESC;


-- 3. TOP 10 CONSULTAS POR LECTURAS LÓGICAS
SELECT TOP 10
  qs.total_logical_reads AS TotalReads,
  qs.execution_count,
  qs.total_worker_time/1000 AS TotalCPUms,
  SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
      WHEN -1 THEN DATALENGTH(st.text)
      ELSE qs.statement_end_offset
     END - qs.statement_start_offset)/2)+1) AS QueryText,
  DB_NAME(st.dbid) AS DatabaseName
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY qs.total_logical_reads DESC;


-- 4. BLOQUEOS ACTUALES
SELECT
  blocking_session_id AS BlockingSPID,
  session_id           AS BlockedSPID,
  wait_type,
  wait_time,
  wait_resource,
  TEXT AS QueryText
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle)
WHERE blocking_session_id <> 0;


-- 5. USO DE ÍNDICES
SELECT
  OBJECT_NAME(s.object_id)        AS TableName,
  i.name                         AS IndexName,
  s.user_seeks,
  s.user_scans,
  s.user_lookups,
  s.user_updates
FROM sys.dm_db_index_usage_stats s
INNER JOIN sys.indexes i
  ON s.object_id = i.object_id
  AND s.index_id = i.index_id
WHERE database_id = DB_ID()
ORDER BY s.user_updates DESC;


-- 6. TAMAÑO DE BASES DE DATOS Y ARCHIVOS
SELECT
  DB_NAME(database_id) AS DatabaseName,
  SUM(size*8.0/1024)   AS SizeMB
FROM sys.master_files
GROUP BY database_id
ORDER BY SizeMB DESC;


-- 7. SUGERENCIAS DE ÍNDICES FALTANTES
SELECT
  mid.statement AS TableAndColumns,
  migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) 
    AS ImprovementMeasure,
  'CREATE INDEX IX_' + OBJECT_NAME(mid.object_id) + '_' + REPLACE(REPLACE(mid.equality_columns, ', ', '_'), '[', '') 
    + CASE WHEN mid.inequality_columns IS NOT NULL THEN '_' + REPLACE(REPLACE(mid.inequality_columns, ', ', '_'), '[', '') ELSE '' END
    + ' ON ' + mid.statement + 
      '(' + ISNULL(mid.equality_columns,'') 
      + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 
      + ISNULL(mid.inequality_columns,'') + ')' AS CreateIndexStatement,
  migs.*
FROM sys.dm_db_missing_index_group_stats migs
INNER JOIN sys.dm_db_missing_index_groups mig
  ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid
  ON mig.index_handle = mid.index_handle
ORDER BY ImprovementMeasure DESC;
📊

Monitor de Transacciones

Monitoreo

Muestra Información de Transacciones activas y su estado

--Monitor de Transacciones Activas
select transaction_begin_time,name,transaction_begin_time,
case when transaction_type = 1 then 'Read_Write_TX' else '' end  +
case when transaction_type = 2 then 'Read_Only_TX' else '' end +
case when transaction_type = 1 then 'System_TX' else '' end +
case when transaction_type = 1 then 'Distributed_TX' else '' end as transaction_type,
transaction_uow,
case when transaction_state = 0 then 'The transaction has not been completely initialized yet' else '' end +
case when transaction_state = 1 then 'The transaction has been initialized but has not started' else '' end +
case when transaction_state = 2 then 'The transaction is active' else '' end +
case when transaction_state = 3 then 'The transaction has ended' else '' end +
case when transaction_state = 4 then 'The commit process has been initiated on the distributed transaction' else '' end +
case when transaction_state = 5 then 'The transaction is in a prepared state and waiting resolution' else '' end +
case when transaction_state = 6 then 'The transaction has been committed' else '' end +
case when transaction_state = 7 then 'The transaction is being rolled back' else '' end +
case when transaction_state = 8 then 'The transaction has been rolled back' else '' end as transaction_state,
case when dtc_state = 1 then 'ACTIVE' else '' end +
case when dtc_state = 2 then 'PREPARED' else '' end +
case when dtc_state = 3 then 'COMMITTED' else '' end +
case when dtc_state = 4 then 'ABORTED' else '' end +
case when dtc_state = 5 then 'RECOVERED' else '' end as dtc_state
from sys.dm_tran_active_transactions
📊

Monitor de Jobs

Monitoreo

Script te permite ver las configuraciones del Agente de SQL Server así como el historial de ejecuciones de los jobs programados

--Job Monitor
SELECT DISTINCT substring(a.name,1,100) AS [Job Name],
 'Enabled'=case
 WHEN a.enabled = 0 THEN 'No'
 WHEN a.enabled = 1 THEN 'Yes'
 end,
 substring(b.name,1,30) AS [Name of the schedule],
 'Frequency of the schedule execution'=case
 WHEN b.freq_type = 1 THEN 'Once'
 WHEN b.freq_type = 4 THEN 'Daily'
 WHEN b.freq_type = 8 THEN 'Weekly'
 WHEN b.freq_type = 16 THEN 'Monthly'
 WHEN b.freq_type = 32 THEN 'Monthly relative'
 WHEN b.freq_type = 32 THEN 'Execute when SQL Server Agent starts'
 END,
 'Units for the freq_subday_interval'=case
 WHEN b.freq_subday_type = 1 THEN 'At the specified time'
 WHEN b.freq_subday_type = 2 THEN 'Seconds'
 WHEN b.freq_subday_type = 4 THEN 'Minutes'
 WHEN b.freq_subday_type = 8 THEN 'Hours'
 END,
 cast(cast(b.active_start_date as varchar(15)) as datetime) as active_start_date,
 cast(cast(b.active_end_date as varchar(15)) as datetime) as active_end_date,
 Stuff(Stuff(right('000000'+Cast(c.next_run_time as Varchar),6),3,0,':'),6,0,':') as Run_Time,
 convert(varchar(24),b.date_created) as Created_Date,
 
 'Status'=Case
 when e.run_status = 0 THEN 'Failed'
 when e.run_status = 1 THEN 'Succeeded'
 when e.run_status = 2 THEN 'Retry'
 when e.run_status = 3 THEN 'Canceled'
 END,
 e.run_duration, e.step_name as Last_Step_Name 


FROM msdb.dbo.sysjobs a
INNER JOIN msdb.dbo.sysJobschedules c ON a.job_id = c.job_id
INNER JOIN msdb.dbo.SysSchedules b on b.Schedule_id=c.Schedule_id
INNER JOIN msdb.dbo.sysjobhistory e On a.job_id = e.job_id
GO
SELECT [Name], [Date_Created], 'Job Enabled..?'=case
 WHEN enabled = 0 THEN 'No'
 WHEN enabled = 1 THEN 'Yes'
 end ,
 'notification Enabled..?'=case
 WHEN Notify_Level_Email = 0 THEN 'No'
 WHEN Notify_Level_Email = 1 THEN 'Yes'
 end
FROM MSDB.dbo.sysjobs
WHERE [Notify_Level_Email] = 0
AND [Enabled] = 1;
go
--Muestra los operadores habilitados en el Agente de SQL Server 
SELECT [ID], [Name], [Enabled]
FROM MSDB.dbo.sysoperators
WHERE [Enabled] = 1
ORDER BY [Name];
GO
--Obtiene información sobre las configuraciones de los procesos en el Agente de SQL Server

SELECT
 [sJOB].[job_id] AS [JobID]
 , [sJOB].[name] AS [JobName]
 , [sDBP].[name] AS [JobOwner]
 , [sCAT].[name] AS [JobCategory]
 , [sJOB].[description] AS [JobDescription]
 , CASE [sJOB].[enabled]
 WHEN 1 THEN 'Yes'
 WHEN 0 THEN 'No'
 END AS [IsEnabled]
 , [sJOB].[date_created] AS [JobCreatedOn]
 , [sJOB].[date_modified] AS [JobLastModifiedOn]
 , [sSVR].[name] AS [OriginatingServerName]
 , [sJSTP].[step_id] AS [JobStartStepNo]
 , [sJSTP].[step_name] AS [JobStartStepName]
 , CASE
 WHEN [sSCH].[schedule_uid] IS NULL THEN 'No'
 ELSE 'Yes'
 END AS [IsScheduled]
 , [sSCH].[schedule_uid] AS [JobScheduleID]
 , [sSCH].[name] AS [JobScheduleName]
 , CASE [sJOB].[delete_level]
 WHEN 0 THEN 'Never'
 WHEN 1 THEN 'On Success'
 WHEN 2 THEN 'On Failure'
 WHEN 3 THEN 'On Completion'
 END AS [JobDeletionCriterion]
FROM
 [msdb].[dbo].[sysjobs] AS [sJOB]
 LEFT JOIN [msdb].[sys].[servers] AS [sSVR]
 ON [sJOB].[originating_server_id] = [sSVR].[server_id]
 LEFT JOIN [msdb].[dbo].[syscategories] AS [sCAT]
 ON [sJOB].[category_id] = [sCAT].[category_id]
 LEFT JOIN [msdb].[dbo].[sysjobsteps] AS [sJSTP]
 ON [sJOB].[job_id] = [sJSTP].[job_id]
 AND [sJOB].[start_step_id] = [sJSTP].[step_id]
 LEFT JOIN [msdb].[sys].[database_principals] AS [sDBP]
 ON [sJOB].[owner_sid] = [sDBP].[sid]
 LEFT JOIN [msdb].[dbo].[sysjobschedules] AS [sJOBSCH]
 ON [sJOB].[job_id] = [sJOBSCH].[job_id]
 LEFT JOIN [msdb].[dbo].[sysschedules] AS [sSCH]
 ON [sJOBSCH].[schedule_id] = [sSCH].[schedule_id]
ORDER BY [JobName]
go
--Obtiene información sobre las calendarizaciones de procesos en el Agente de SQL Server

SELECT
 [schedule_uid] AS [ScheduleID]
 , [name] AS [ScheduleName]
 , CASE [enabled]
 WHEN 1 THEN 'Yes'
 WHEN 0 THEN 'No'
 END AS [IsEnabled]
 , CASE
 WHEN [freq_type] = 64 THEN 'Start automatically when SQL Server Agent starts'
 WHEN [freq_type] = 128 THEN 'Start whenever the CPUs become idle'
 WHEN [freq_type] IN (4,8,16,32) THEN 'Recurring'
 WHEN [freq_type] = 1 THEN 'One Time'
 END [ScheduleType]
 , CASE [freq_type]
 WHEN 1 THEN 'One Time'
 WHEN 4 THEN 'Daily'
 WHEN 8 THEN 'Weekly'
 WHEN 16 THEN 'Monthly'
 WHEN 32 THEN 'Monthly - Relative to Frequency Interval'
 WHEN 64 THEN 'Start automatically when SQL Server Agent starts'
 WHEN 128 THEN 'Start whenever the CPUs become idle'
 END [Occurrence]
 , CASE [freq_type]
 WHEN 4 THEN 'Occurs every ' + CAST([freq_interval] AS VARCHAR(3)) + ' day(s)'
 WHEN 8 THEN 'Occurs every ' + CAST([freq_recurrence_factor] AS VARCHAR(3))
 + ' week(s) on '
 + CASE WHEN [freq_interval] & 1 = 1 THEN 'Sunday' ELSE '' END
 + CASE WHEN [freq_interval] & 2 = 2 THEN ', Monday' ELSE '' END
 + CASE WHEN [freq_interval] & 4 = 4 THEN ', Tuesday' ELSE '' END
 + CASE WHEN [freq_interval] & 8 = 8 THEN ', Wednesday' ELSE '' END
 + CASE WHEN [freq_interval] & 16 = 16 THEN ', Thursday' ELSE '' END
 + CASE WHEN [freq_interval] & 32 = 32 THEN ', Friday' ELSE '' END
 + CASE WHEN [freq_interval] & 64 = 64 THEN ', Saturday' ELSE '' END
 WHEN 16 THEN 'Occurs on Day ' + CAST([freq_interval] AS VARCHAR(3))
 + ' of every '
 + CAST([freq_recurrence_factor] AS VARCHAR(3)) + ' month(s)'
 WHEN 32 THEN 'Occurs on '
 + CASE [freq_relative_interval]
 WHEN 1 THEN 'First'
 WHEN 2 THEN 'Second'
 WHEN 4 THEN 'Third'
 WHEN 8 THEN 'Fourth'
 WHEN 16 THEN 'Last'
 END
 + ' '
 + CASE [freq_interval]
 WHEN 1 THEN 'Sunday'
 WHEN 2 THEN 'Monday'
 WHEN 3 THEN 'Tuesday'
 WHEN 4 THEN 'Wednesday'
 WHEN 5 THEN 'Thursday'
 WHEN 6 THEN 'Friday'
 WHEN 7 THEN 'Saturday'
 WHEN 8 THEN 'Day'
 WHEN 9 THEN 'Weekday'
 WHEN 10 THEN 'Weekend day'
 END
 + ' of every ' + CAST([freq_recurrence_factor] AS VARCHAR(3))
 + ' month(s)'
 END AS [Recurrence]
 , CASE [freq_subday_type]
 WHEN 1 THEN 'Occurs once at '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_start_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 WHEN 2 THEN 'Occurs every '
 + CAST([freq_subday_interval] AS VARCHAR(3)) + ' Second(s) between '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_start_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 + ' & '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_end_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 WHEN 4 THEN 'Occurs every '
 + CAST([freq_subday_interval] AS VARCHAR(3)) + ' Minute(s) between '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_start_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 + ' & '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_end_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 WHEN 8 THEN 'Occurs every '
 + CAST([freq_subday_interval] AS VARCHAR(3)) + ' Hour(s) between '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_start_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 + ' & '
 + STUFF(
 STUFF(RIGHT('000000' + CAST([active_end_time] AS VARCHAR(6)), 6)
 , 3, 0, ':')
 , 6, 0, ':')
 END [Frequency]
 , STUFF(
 STUFF(CAST([active_start_date] AS VARCHAR(8)), 5, 0, '-')
 , 8, 0, '-') AS [ScheduleUsageStartDate]
 , STUFF(
 STUFF(CAST([active_end_date] AS VARCHAR(8)), 5, 0, '-')
 , 8, 0, '-') AS [ScheduleUsageEndDate]
 , [date_created] AS [ScheduleCreatedOn]
 , [date_modified] AS [ScheduleLastModifiedOn]
FROM [msdb].[dbo].[sysschedules]
ORDER BY [ScheduleName]
📊

Monitor de Utilización de Espacio en BDs

Monitoreo

Tamaño detallado de datos y logs, crecimiento configurado y porcentaje de uso.

--Ver Uso
declare @dbsize as  float(1),
		@logsize as float(1),
		@dbsize2 as  float(1),
		@logsize2 as float(1),  
		@Totalsize as float(1),
		@TotalFree as float(1),	
		@reservedpages as int,
		@percentageUsed as float(1),
		@percentageFree as float(1),
		@DataGrowth as float(1),
		@LogGrowth as float(1),
		@isPercentD as float(1),
		@isPercentL as float(1),
		@Max_SizeD as int,
		@Max_SizeL as int;

	select @Max_SizeD = max_size, @DataGrowth = growth, @isPercentD = is_percent_growth from sys.database_files where file_id = 1
	select @Max_SizeL = max_size, @LogGrowth = growth, @isPercentL = is_percent_growth from sys.database_files where file_id = 2

	select @dbsize = sum(convert(bigint,case when status & 64 = 0 then size else 0 end))
			, @logsize = sum(convert(bigint,case when status & 64 <> 0 then size else 0 end))
			from dbo.sysfiles

	select @reservedpages = sum(a.total_pages) from sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id
			left join sys.internal_tables it on p.object_id = it.object_id

	set @dbsize2 = @dbsize * 8192 / 1048576
	set @logsize2 = @logsize * 8192 / 1048576
	
	set @Totalsize = ((@dbsize + @logsize) * 8192 / 1048576)

	set @TotalFree =  case when @dbsize >= @reservedpages then
					((@dbsize - @reservedpages) * 8192 / 1048576) else 0 end

	set @percentageFree = ((@TotalFree*100)/@Totalsize)
	SET @percentageUsed = 100 - @percentageFree

		
	select database_Name = DB_NAME(),@dbsize2 as 'Tamaño_Datos(MBs)', @logsize2 as 'Tamaño_Log(MBs)', @Totalsize as 'Tamaño_total(MBs)', @TotalFree as 'Espacio_Libre', @percentageUsed as '%Total_Utilizado', @percentageFree as '%Total_Libre',@Max_SizeD as 'Data_Max_Size', @DataGrowth as 'Data_Growth', @isPercentD as 'Percent_Data_Growth', @Max_SizeL as 'Log_Max_Size', @LogGrowth as 'Log_Growth', @isPercentL as 'Percent_Log_Growth'
		
⚡

Valida Fragmentacion en indices

Índices

Detecta índices fragmentados a nivel tabla y base de datos y ejecuta comandos para reorganizar o regenerar.

--DETECTAR FRAGMENTACION EN UNA TABLA ESPECIFICA DE UNA BASE DE DATOS

SELECT a.index_id, name, avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(N'DB_Name'), OBJECT_ID(N'Esquema.tabla'), NULL, NULL, NULL) AS a
    JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id; 

--DETECTAR FRAGMENTACION EN TODAS LAS TABLAS DE LA BASE DE DATOS

SELECT a.index_id, c.name, b.name, avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(N'DB_Name'), NULL, NULL, NULL, NULL) AS a
    JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id
	JOIN sys.all_objects c ON a.object_id = c.object_id
Where a.avg_fragmentation_in_percent > 5 and a.avg_fragmentation_in_percent <= 30 --INDICES A REORGANIZAR
--where a.avg_fragmentation_in_percent > 30 --INDICES A REGENERAR


--REORGANIZAR INDICES DE UNA TABLA

-- Reorganize all indexes on the HumanResources.Employee table.
ALTER INDEX ALL ON esquema.tabla
REORGANIZE ; 
GO

--REORGANIZA UN INDICE DE UNA TABLA

-- Reorganize the IX_Employee_OrganizationalLevel_OrganizationalNode index on the HumanResources.Employee table. 

ALTER INDEX IndexName ON esquema.Tabla
REORGANIZE ; 
GO

--REGENERAR INDICES DE UNA TABLA

ALTER INDEX ALL ON esquema.tabla
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
              STATISTICS_NORECOMPUTE = ON);


--REGENERA UN INDICE DE UNA TABLA

GO
ALTER INDEX IndexName ON Scheme.Tabla
REBUILD;
GO
⚡

Calcula operación sobre Indices

Índices

Script que valida el nivel de fragmentación y Genera automáticamente los comandos REORGANIZE o REBUILD.

--Script para calcular operación sobre Indices
WITH INDICES (BD, INDICETIPO, FRAGMENTACION, INDICE, TABLA)
AS (
SELECT DBS.NAME BASEDEDATOS, PS.INDEX_TYPE_DESC, PS.AVG_FRAGMENTATION_IN_PERCENT, 
IND.NAME INDICE, TAB.NAME TABLA
FROM 
SYS.DM_DB_INDEX_PHYSICAL_STATS (DB_ID(), NULL, NULL,  NULL, NULL) PS
INNER JOIN SYS.DATABASES DBS
ON PS.DATABASE_ID = DBS.DATABASE_ID 
INNER JOIN SYS.INDEXES IND
ON PS.OBJECT_ID  = IND.OBJECT_ID 
INNER JOIN SYS.TABLES TAB 
ON TAB.OBJECT_ID = IND.OBJECT_ID 
WHERE IND.NAME IS  NOT NULL AND PS.INDEX_ID = IND.INDEX_ID
AND PS.AVG_FRAGMENTATION_IN_PERCENT  > 30)
SELECT DISTINCT  
      CASE
      WHEN FRAGMENTACION > 5 AND FRAGMENTACION <= 30 THEN  'ALTER INDEX ' + INDICE  + ' ON ' +  TABLA + ' REORGANIZE'     
      WHEN FRAGMENTACION > 30 THEN 'ALTER INDEX ' + INDICE + ' ON ' + TABLA + ' REBUILD'
      END QUERY, FRAGMENTACION, BD, INDICE, TABLA
FROM (SELECT FRAGMENTACION, INDICE, TABLA, BD FROM INDICES
      WHERE FRAGMENTACION > 5) A
ORDER BY FRAGMENTACION DESC 
⚡

Utilización de Indices

Índices

Valida si hay índices sin ser utilizados o sobreutilizados

--Utilización de índices
SELECT 
    OBJECT_NAME(i.object_id) AS table_name,
    i.name AS index_name,
    ius.user_seeks,
    ius.user_scans,
    ius.user_lookups,
    ius.user_updates
FROM sys.indexes i
JOIN sys.dm_db_index_usage_stats ius 
    ON i.object_id = ius.object_id AND i.index_id = ius.index_id
WHERE OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1
ORDER BY ius.user_scans DESC;
                                
📝

Consultas: Do VS Dont

Consultas

Buenas y malas prácticas en SQL: errores comunes y cómo corregirlos.

--1. Olvidar el WHERE en un DELETE o UPDATE
--ERROR: Se borran todos los empleados
DELETE FROM HumanResources.Employee;
GO
--SOLUCIÓN: Filtrar solo el empleado deseado
DELETE FROM HumanResources.Employee
WHERE BusinessEntityID = 42;
GO
--2. No usar alias al hacer JOINs
--ERROR: Confuso y difícil de leer
SELECT Person.FirstName, Sales.SalesOrderID
FROM Person.Person
JOIN Sales.SalesOrderHeader
ON Person.BusinessEntityID = Sales.CustomerID;
GO
--SOLUCIÓN: Uso claro de alias
SELECT P.FirstName, SO.SalesOrderID
FROM Person.Person AS P
JOIN Sales.SalesOrderHeader AS SO
ON P.BusinessEntityID = SO.CustomerID;
GO
--3. Confusión entre NULL y valores vacíos
--ERROR: No considera registros con valores NULL
SELECT *
FROM Person.Person
WHERE MiddleName = '';
GO
--SOLUCIÓN: Evaluar explícitamente los NULL
SELECT *
FROM Person.Person
WHERE MiddleName IS NULL;
GO
--4. Uso incorrecto de comillas y tipos de datos
--ERROR: Comparación entre texto y entero
SELECT *
FROM Production.Product
WHERE ProductID = '101'; -- '101' es cadena
GO
--SOLUCIÓN: Usar tipo de dato correcto (entero)
SELECT *
FROM Production.Product
WHERE ProductID = 101;
GO
--5. No agrupar correctamente al usar GROUP BY
--ERROR: Falla porque falta GROUP BY
SELECT SalesPersonID, COUNT(*)
FROM Sales.SalesOrderHeader;
GO
--SOLUCIÓN: Agregar GROUP BY
SELECT SalesPersonID, COUNT(*)
FROM Sales.SalesOrderHeader
GROUP BY SalesPersonID;
📝

Instrucciones básicas de SQL

Consultas

CREATE DATABASE, CREATE TABLE, INSERT, UPDATE, SELECT. Ejercicio completo para principiantes.

--Ejercicio de instrucciones básicas de SQL.sql
USE master;
GO

-- Crear base de datos
CREATE DATABASE TestData;
GO

USE TestData;
GO

-- Crear tabla
CREATE TABLE dbo.Products (
    ProductID int PRIMARY KEY NOT NULL,
    ProductName varchar(25) NOT NULL,
    Price money NULL,
    ProductDescription text NULL
);
GO

-- Insertar datos
INSERT dbo.Products VALUES (1, 'Clamp', 12.48, 'Workbench clamp');
INSERT dbo.Products VALUES (50, 'Screwdriver', 3.17, 'Flat head');
INSERT dbo.Products VALUES (75, 'Tire Bar', NULL, 'Tool for changing tires.');
GO

-- Actualizar datos
UPDATE dbo.Products SET ProductName = 'Flat Head Screwdriver' WHERE ProductID = 50;
GO

-- Consultar datos
SELECT ProductID, ProductName, Price FROM dbo.Products;
📝

Ejemplos de Consultas

Consultas

Joins, agregados, CTE, rankings y manejo de errores. Consultas avanzadas con ejemplos prácticos.

--Practicas de Consultas
--Relacionar Multiples Tablas con Join
--Uso de Multiples Joins, Concatenación de Campos, Filtro con Fechas
-- Relaciona Ventas, Clientes y Nombres de Personas
Select p.FirstName + ' ' + p.LastName As Cliente, 
	c.CustomerID,
	soh.SalesOrderID,
	soh.OrderDate,
	soh.TotalDue
From Sales.SalesOrderHeader as soh
Join Sales.Customer as c
	On soh.CustomerID = c.CustomerID
Join Person.Person as p
	On c.PersonID = p.BusinessEntityID
Where soh.OrderDate >= '2014-01-01';

--Metricas Agregadas con Group By y Having
--Funciones Agregadas, Agrupación Temporal, Filtros de Agregados (Having)
--Agrega el valor de las ventas por año
Select Year(soh.OrderDate) as Año,
	Count(*) as TotalOrdenes,
	Sum(soh.TotalDue) As TotalIngresos 
From Sales.SalesOrderHeader As soh
Group By YEAR(soh.OrderDate)
Having SUM(soh.TotalDue) > 100000;

--Orden y Jerarquía con funciones de Ventana Rank()
--Rank() para Clasificación, Orden con Order By Filtros con Between
-- Ranking por monto total de Compra
Select p.FirstName + ' ' + p.LastName as Cliente,
	soh.TotalDue, 
	RANK() Over (Order By soh.TotalDue DESC) as RangoCompra
From Sales.SalesOrderHeader as soh
Join Sales.Customer As c
	On soh.CustomerID = c.CustomerID
Join Person.Person As p
	On c.PersonID = p.BusinessEntityID
Where soh.OrderDate Between '2014-01-01' And '2014-12-31';

--Jerarquias con CTE y Niveles Organizacionales
--Uso de CTE, Función GetLevel(), Representación de Estructuras Jerárquircas
With Organigrama As (
	Select e.BusinessEntityID, e.OrganizationNode.GetLevel() as Nivel,
		p.FirstName + ' ' + p.LastName as Empleado
	From HumanResources.Employee as e
	Join Person.Person as p
		On e.BusinessEntityID = p.BusinessEntityID
)
Select * From Organigrama Where Nivel <= 3;

--Limpieza y Transformación de Datos
--Uso de ISNULL, Análisis de Atributos categóricos, Limpieza de valores nulos
Select p.EmailPromotion, COUNT(*) as TotalPersonas
From Person.Person as p
Where ISNULL(p.EmailPromotion, 0) >= 0
Group By p.EmailPromotion

--Consultas Dinámicas
Begin Try
	declare @Tabla NVARCHAR(128) = 'Person.Person';
	declare @SQL NVARCHAR(MAX);
	
	SET @SQL = N'Select * From ' + QUOTENAME(@Tabla);

	Exec sp_executesql @SQL;

End Try
Begin Catch
	select ERROR_MESSAGE() as ErrorSQL;
End Catch

--Uso de sp_readerrorlog para monitoreo
--Ideal para ver errores recientes en el servidor SQL
Exec sp_readerrorlog 0, 1, 'error';
                                
📬 ¿Te fue útil?

¿Encontraste estos scripts de utilidad?

Te gustaría que en un futuro subamos scripts más especializados? (administración avanzada, recuperación de desastres, auditoría de seguridad), contáctame ya sea por correo o por whatsapp y cuéntame qué te gustaría ver.

📌 Tu opinión cuenta: Los scripts que subamos en el futuro dependerán de lo que la comunidad nos pida.

⬅ Volver a MSSQL Server