Category Archives: Scripts

This section will store simple scripts

Enforce Password Policies on SQL Logins

Make sure all SQL Logins have the “enforced password” setting check

/*
DESCRIPTION:
The following code Enables the CHECK POLICY ON on all logins who needs it, No need to run the output, it just does it.
 
CONFIGURATION
None

Author: Miguel Quintana

Compatibility list:
MSSQL2005
MSSQL2008

DOES NOT WORK
MSSQL2000
*/

DECLARE @LoginName sysname
DECLARE @SQL NVARCHAR(1000)

DECLARE DBLOGINS CURSOR FOR
    SELECT name  FROM master.sys.sql_logins
    WHERE is_policy_checked = 0

OPEN DBLOGINS

FETCH NEXT FROM DBLOGINS INTO @LoginName
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @SQL = 'ALTER LOGIN [' + @LoginName + '] WITH CHECK_EXPIRATION=OFF, CHECK_POLICY=ON;'
-- print @SQL
    EXEC sp_executesql @SQL
    PRINT 'Fixing Login for ['+@LoginName+']'
    FETCH NEXT FROM DBLOGINS INTO @LoginName
END

CLOSE DBLOGINS
DEALLOCATE DBLOGINS
PRINT 'Done'

Number of Logins and Sessions

.


/*

-- SQL Server 2008 and R2 Diagnostic Information Queries
-- Glenn Berry
-- June 2012
-- Last Modified: June 19, 2012
-- http://sqlserverperformance.wordpress.com/
-- http://sqlskills.com/blogs/glenn/
-- Twitter: GlennAlanBerry

DESCRIPTION:  List number of logins and their sessions

 
Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2008R2
MSSQL2012

DOES NOT WORK
MSSQL2000

Update Log:

*/

SELECT login_name, COUNT(session_id) AS [session_count]
FROM sys.dm_exec_sessions WITH (NOLOCK)
WHERE session_id > 50    -- filter out system SPIDs
GROUP BY login_name
ORDER BY COUNT(session_id) DESC OPTION (RECOMPILE);

.

CPU Usage

.



/*

 SQL Server 2008 and R2 Diagnostic Information Queries
 Glenn Berry
 June 2012
 Last Modified: June 19, 2012
 http://sqlserverperformance.wordpress.com/
 http://sqlskills.com/blogs/glenn/
 Twitter: GlennAlanBerry

DESCRIPTION:  List CPU usage for of all files for all databases

Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2008R2
MSSQL2012

DOES NOT WORK
MSSQL2000
 Get total buffer usage by database for current instance  (Query 18)
 This make take some time to run on a busy instance

Update Log:

*/

select
DB_NAME(database_id) AS [Database Name]
, COUNT(*) * 8/1024.0 AS [Cached Size (MB)]
from sys.dm_os_buffer_descriptors WITH (NOLOCK)
where database_id > 4 -- system databases
and database_id <> 32767 -- ResourceDB
group by DB_NAME(database_id)
order by [Cached Size (MB)] DESC OPTION (RECOMPILE);
 
/*
Tells you how much memory (in the buffer pool)
is being used by each database on the instance
*/

.

Location of Data files and Tlog

.


/*

-- SQL Server 2008 and R2 Diagnostic Information Queries
-- Glenn Berry
-- June 2012
-- Last Modified: June 19, 2012
-- http://sqlserverperformance.wordpress.com/
-- http://sqlskills.com/blogs/glenn/
-- Twitter: GlennAlanBerry


DESCRIPTION:  List location of all files for all databases

Look for tempDB and  Tlog sharing the same drives as a source of I/O contention issues


 
Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2008R2
MSSQL2012

DOES NOT WORK
MSSQL2000

Update Log:

*/

 

 

SELECT

DB_NAME([database_id])AS [Database Name]

,   [file_id]

, name

, physical_name

, type_desc

, state_desc

,  CONVERT( bigint, size/128.0) AS [Total Size in MB]
FROM sys.master_files WITH (NOLOCK)
WHERE [database_id] > 4
AND [database_id] <> 32767
OR [database_id] = 2
ORDER BY DB_NAME([database_id]) OPTION (RECOMPILE);

.

IO Usage by data file

.

/* SQL Server 2008 and R2 Diagnostic Information Queries
 Glenn Berry
 June 2012
 Last Modified: June 19, 2012
 

DESCRIPTION:  List IO usage for of all files for all databases

Look for tempDB and  Tlog sharing the same drives as a source of I/O contention issues and identify the busiest DB

Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2008R2
MSSQL2012

DOES NOT WORK
MSSQL2000

Update Log:

*/

--Calculates average stalls per read, per write, and per total input/output for each database file  
SELECT
DB_NAME(fs.database_id) AS [Database Name]
, mf.physical_name
, io_stall_read_ms
, num_of_reads
, CAST(io_stall_read_ms/(1.0 + num_of_reads) AS NUMERIC(10,1)) AS [avg_read_stall_ms]
, io_stall_write_ms
, num_of_writes
, CAST(io_stall_write_ms/(1.0+num_of_writes) AS NUMERIC(10,1)) AS [avg_write_stall_ms]
, io_stall_read_ms + io_stall_write_ms AS [io_stalls]
, num_of_reads + num_of_writes AS [total_io]
, CAST((io_stall_read_ms + io_stall_write_ms)/(1.0 + num_of_reads + num_of_writes) AS NUMERIC(10,1))
AS [avg_io_stall_ms]

FROM sys.dm_io_virtual_file_stats(null,null) AS fs
INNER JOIN sys.master_files AS mf WITH (NOLOCK)
ON fs.database_id = mf.database_id
AND fs.[file_id] = mf.[file_id]
ORDER BY avg_io_stall_ms DESC OPTION (RECOMPILE);

-- Helps you determine which database files on the entire instance have the most I/O bottlenecks
-- This can help you decide whether certain LUNs are overloaded and whether you might
-- want to move some files to a different location


.

Last Autogrowth Event

.


/*
DESCRIPTION:    Queries the default trace to find out last AUTOGROWTH event

The default trace should be enabled by, well, default

Check if it is enabled:  select status, path from sys.traces where is_default = 1

How far back does it report?

The default trace creates up-to 5 files, 20 mb in size. So depending on how busy the server is, it could be 20 mins or days



Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2008R2
MSSQL2012

DOES NOT WORK
MSSQL2000

Update Log:
 
*/

 
 
Use master
go
 
declare @curr_tracefilename varchar(500) ;  
declare @base_tracefilename varchar(500) ;  
declare @indx int ;
 
select @curr_tracefilename = path from sys.traces where is_default = 1 ;  
 
set @curr_tracefilename = reverse(@curr_tracefilename);
 
select @indx = patindex('%\%', @curr_tracefilename) ;
 
set @curr_tracefilename = reverse(@curr_tracefilename) ;
 
set @base_tracefilename = left( @curr_tracefilename,len(@curr_tracefilename) - @indx) + '\log.trc' ;  
 
 
select  
 loginname
 , spid
 --,convert(int, EventClass) as EventClass,  
,DatabaseName
,[Filename]
,Duration
, StartTime
, EndTime
, (IntegerData*8.0/1024) as ChangeInSize
, e.name
, RIGHT(@curr_tracefilename,@indx) as curr_tracefilename
 
from ::fn_trace_gettable(@base_tracefilename, default ) a
INNER JOIN sys.trace_events e    ON eventclass = trace_event_id

where  
            e.name = 'Log File Auto Grow'
        OR  e.name = 'Log File Auto Shrink'
        OR  e.name = 'Data File Auto Grow'
        OR  e.name = 'Data File Auto Shrink'
 
order by StartTime desc ;  
GO

.

Statistics last Updated

/*

-- SQL Server 2008 and R2 Diagnostic Information Queries
-- Glenn Berry
-- June 2012
-- Last Modified: June 19, 2012
-- http://sqlserverperformance.wordpress.com/
-- http://sqlskills.com/blogs/glenn/
-- Twitter: GlennAlanBerry

DESCRIPTION: Statistics last udpate

 


 
Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2008R2
MSSQL2012

DOES NOT WORK
MSSQL2000

Update Log:

*/

 

 

-- When were Statistics last updated on all indexes?  (Query 48)
SELECT o.name, i.name AS [Index Name],  
      STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date],
      s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id]
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE); 

SQL Job to delete old files

This scripts builds up on the idea of using ForFiles. See

http://www.cookingsql.com/2014/12/batch-file-to-remove-old-files/

/*
DESCRIPTION:
Creates a JOB to delete files of a certain age on a folder, based on EXTENSION
 
CONFIGURATION
Plenty
SET @days = 30   for the age of the file, in days
SET @NAME = 'IBM_Cleanup'  for the name of the job
SET @ext = 'txt'  for the extension of the files to delete.

The DEFAULT FOLDER is the location for your ERRORLOG folder, but it can be customized

After running the script, you still need to schedule the job

Author: Miguel Quintana

LIMITATION:
It does not do subfolders

Compatibility list:
MSSQL2005
MSSQL2008
MSSQL2000
*/

 

 
declare @cmd nvarchar (1000)
DECLARE @sqlerrorlog TABLE (logdate DATETIME, processinfo SYSNAME, logtext VARCHAR(MAX))
DECLARE @path VARCHAR(300)
DECLARE @LOG_FOLDER varchar(300)
DECLARE @days varchar(4)
DECLARE @NAME varchar(100)

DECLARE @ext varchar (4)


/*
This section sets the ErrorLog folder as destination to delete file.
If you would like to set your own path, comment out this section.
and use the  SET @LOG_FOLDER  section
 
 
*/
SET @days = 30
SET @NAME = 'IBM_Cleanup'
SET @ext = 'txt'


--/*
INSERT INTO @sqlerrorlog EXEC xp_readerrorlog 0, 1
SELECT @path=logtext FROM @sqlerrorlog WHERE logtext LIKE '%Logging SQL Server messages in file%'

SET @LOG_FOLDER= SUBSTRING(@path, CHARINDEX( '''', @path) + 1,LEN(@path)-CHARINDEX( '''', @path) - CHARINDEX( '\', REVERSE(@path)))
-- */
 
-- only use this line below if you do not want the errorlog as your default folder
-- SET @LOG_FOLDER = 'D:\folder_here'
 
 
/*  DO not change below this line */
 

set @cmd=N'cmd /q /c "For /F "tokens=1 delims=" %v In (''ForFiles /P "'+@LOG_FOLDER+'" /m *.'+@ext+' /d -'+@days+' 2^>^&1'') do if EXIST "'+@LOG_FOLDER+'"\%v echo del "'+@LOG_FOLDER+'"\%v& del "'+@LOG_FOLDER+'"\%v"' 

 
--print @cmd
 
USE [msdb]
 
 
/****** Object:  Job [IBM_CommandLog Cleanup]    Script Date: 04/02/2014 14:16:35 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [Database Maintenance]    Script Date: 04/02/2014 14:16:35 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'Database Maintenance' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'Database Maintenance'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
 
END
 
DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=@NAME,  
        @enabled=1,  
        @notify_level_eventlog=2,  
        @notify_level_email=0,  
        @notify_level_netsend=0,  
        @notify_level_page=0,  
        @delete_level=0,  
        @category_name=N'Database Maintenance',  
        @owner_login_name=N'sa', @job_id = @jobId OUTPUT
 
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [output_text]    Script Date: 04/02/2014 14:16:35 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'output_text',  
        @step_id=1,  
        @cmdexec_success_code=0,  
        @on_success_action=1,  
        @on_success_step_id=0,  
        @on_fail_action=2,  
        @on_fail_step_id=0,  
        @retry_attempts=0,  
        @retry_interval=0,  
        @os_run_priority=0, @subsystem=N'CmdExec',  
        @command=@cmd,
        @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
 
GO
 
 

Batch File to remove Old Files

This script uses ForFiles to remove old files based on age. However, you must have forfiles installed. Windows 2003 and above have it by default

 

The Syntax is: 

FORFILES -p "Path to the folder" -s -m *.txt -d   -c "cmd /c del @path"

 

Example:

REM  Delete all BAK files from folder C:\backup  that are 5 days or older

FORFILES -p "C:\backup" -s -m *.bak -d -5 -c "cmd /c del @path"

 

 

Want a job to do this automatically? See

http://www.cookingsql.com/2014/12/sql-job-to-delete-old-files/

VBScript to remove files based on age

Sometimes it's necessary to delete files based on age, and we can use a VB Script to do that:

'On Error Resume Next ' < -- Comment out for troubleshooting.

Const strPath = "C:\SQL_Backups\SOG-NADC-SP-DB1" ' Update this parent folder.
Const iDaysOld = 2   

' PURPOSE:	This script will delete all files recursively starting from
'			strPath older than 2 days and empty subfolders.
'			Very convenient for cleaning temp and log files.
' WARNING:	Please understand the risks of using this script.
' WARNING:	DO NOT MODIFY BELOW UNLESS YOU KNOW WHAT YOU ARE DOING.

Dim objFolder, objSubFolder, objFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.getFolder(strPath)

Call Search(objFolder)

Sub Search(objFolder)
	For Each objFile In objFolder.files
		If dateDiff("d",objFile.dateLastModified,Now) > iDaysOld Then objFile.Delete
	Next
	For Each objSubFolder In objFolder.SubFolders
		Search(objSubFolder)
	Next

End Sub

'  end of file