SQL: Get last queries executed on a server

Use this to see what you or others were recently doing.


USE [master]
GO
SELECT [execquery].[last_execution_time],
[execsql].[text]  
FROM [sys].[dm_exec_query_stats] AS [execquery]
CROSS APPLY [sys].[dm_exec_sql_text]([execquery].[sql_handle]) AS [execsql]
WHERE [last_execution_time] > DATEADD(HOUR, -1, GETDATE())
AND [execsql].[text] LIKE '%execq%'
ORDER BY [execquery].[last_execution_time] DESC

 

SQL: Review Database File Growth

We can do this checking the default trace.


--
-- Review Database File Growth
--
DECLARE @trcfilename VARCHAR(1000);
SELECT @trcfilename = [path]
FROM [sys].[traces]
WHERE [is_default] = 1
SELECT [StartTime],
DB_NAME([databaseid]) AS [DatabaseName],
[Filename],
SUM(([IntegerData] * 8) / 1024) AS [Growth in MB],
([Duration] / 1000) AS [Duration in seconds],
RIGHT('0' + CAST(([Duration] / 1000) / 3600 AS VARCHAR), 2) + ':' + RIGHT('0'
+ CAST((([Duration] / 1000) / 60) % 60 AS VARCHAR),
2) + ':' + RIGHT('0'
+ CAST(([Duration] / 1000)
% 60 AS VARCHAR), 2) [TimeHHMMSS]
FROM ::
FN_TRACE_GETTABLE(@trcfilename, DEFAULT)
WHERE ([EventClass] = 92
OR [EventClass] = 93
)
--AND StartTime >= DATEADD(WEEK, -1,GETDATE())
GROUP BY [StartTime],
[Databaseid],
[Filename],
[IntegerData],
[Duration]
ORDER BY [StartTime]

SQL: Does Trim eliminate CRLF?

What will LTRIM and RTRIM do with CR LF or CRLF?


IF OBJECT_ID('tempdb.dbo.[#testtable]') IS NOT NULL
DROP TABLE [#testtable]

CREATE TABLE [#testtable] ([TestCRLF] VARCHAR(50))

INSERT INTO [#testtable]
([TestCRLF]
)
VALUES ('ThereIsNoSpace' + CHAR(13) + CHAR(10)
)
INSERT INTO [#testtable]
([TestCRLF]
)
VALUES ('ThereIsNoSpace' + CHAR(13)
)
INSERT INTO [#testtable]
([TestCRLF]
)
VALUES ('ThereIsNoSpace' + CHAR(10)
)

SELECT [TestCRLF] + 'Z' AS NoPostProcessing
FROM [#testtable]

SELECT LTRIM(RTRIM([TestCRLF])) + 'Z' AS Trims
FROM [#testtable]

SELECT RTRIM(REPLACE(REPLACE(REPLACE(REPLACE([TestCRLF], CHAR(13) + CHAR(10), ' '), CHAR(10) + CHAR(13), ' '), CHAR(13), ' '),
CHAR(10), ' ')) + 'Z' ReplaceAndTrim
FROM [#testtable]

Here’s what the output looks like:

Of course if we output to text the Z character would be in the next line. Since we are trying to clean up data with spaces or CRLF this shows a good demonstration of the problem.

(Thanks to Chris Trump!)

SQL: Find database users who don’t have a login

Find users who don’t have a login. These are real orphans. We find by name because they might be out of sync by id. We assume that’s already been checked.
One caution is some users may have login access via an Active Directory group. Do not run the DROP statements without testing the impact.

SELECT  [sp].[name] AS [LoginName],
        [dp].[name] AS [UserName],
        [dp].[principal_id],
        [dp].[type],
        [dp].[type_desc],
        [dp].[default_schema_name],
        [dp].[create_date],
        [dp].[modify_date],
        [dp].[owning_principal_id],
        [dp].[sid],
        [dp].[is_fixed_role],
        [dp].[sid],
   --     'DROP SCHEMA [' + QUOTENAME([dp].[name]) + '];' + CHAR(10) +
        'DROP USER ' + QUOTENAME([dp].[name]) + ';'
FROM    [sys].[database_principals] [dp]
LEFT OUTER JOIN [sys].[server_principals] [sp]
ON      [sp].[sid] = [dp].[sid]							-- sid could be incorrectly mismatched 
        AND CHARINDEX([dp].[name], [sp].[name]) > 0		-- here we are trying to match by login NAME which makes sense. Occasionally users are created without domain so catch those too.
WHERE   [dp].[type] IN ('U', 'G')
        AND [dp].[principal_id] <> 1
        AND [sp].[name] IS NULL
ORDER BY [UserName]

SQL: Audit to find identical schedules on multiple jobs

At one point it surprised me to see a SQL Agent job schedule in more than one job. A lot of things can cause this, especially if you script and clone jobs.

Here’s the audit you can use to find the jobs which share the exact same schedule. If you change it in one place, ooops, it changes everywhere!


/*
Audit to find identical schedules on multiple jobs
*/

SELECT  [j].[name] [JobName],
        [s].[name] [DupScheduleName],
		[sjs].[schedule_id]
FROM    [msdb].[dbo].[sysjobschedules] [sjs]
JOIN    [msdb].[dbo].[sysschedules] [s]
ON      [s].[schedule_id] = [sjs].[schedule_id]
JOIN    [msdb].[dbo].[sysjobs] [j]
ON      [j].[job_id] = [sjs].[job_id]
WHERE   [sjs].[schedule_id] IN (SELECT   [sjs].[schedule_id]
                               FROM     [msdb].[dbo].[sysjobschedules] [sjs]
                               JOIN     [msdb].[dbo].[sysschedules] [s]
                               ON       [s].[schedule_id] = [sjs].[schedule_id]
                               GROUP BY [sjs].[schedule_id]
                               HAVING   COUNT(*) > 1)
 

After you find them, you will have to drop the dups and recreate using a different name. Possibly just recreating and getting a new schedule_id would work as well.

SQL: Start in single user mode and run commands.

Change the SQL server service for SQL Server 2012 2014 to this
adding -m to the startup parameters.

Before you do that you really want to

  • Get everyone off the server.
  • Disable SQL Agent service changing to manual
  • Close any SSMS object explorer windows you or other administrators have open.
    • Remember it’s single user mode.
  • Stop the services, for SQL and any others which may automatically reconnect once SQL is back up.
  • Possibly leave SSMS open with a query window with the commands you want to run in single user mode.

Click and restart the SQL service. After it has restarted [re-]open a SSMS query window and run the commands.

Once done

  • Stop SQL Service
  • Change the properties removing the -m from the startup parameters
  • Change SQL Agent to autostart and or whatever else you had to change to aget SQL into single user mode.

SQL: Msg 2555 Cannot move all contents of file “tempdev8” to other places to complete the emptyfile operation.

SQL Server 2014. Suddenly we can’t seem to remove extra tempdb files (which were added after we reduced CPU).

I’m getting this error:

DBCC SHRINKFILE: Page 9:505072 could not be moved because it is a work table page.
Msg 2555, Level 16, State 1, Line 94
Cannot move all contents of file "tempdev8" to other places to complete the emptyfile operation.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Msg 5042, Level 16, State 1, Line 95
The file 'tempdev8' cannot be removed because it is not empty.

Since it was a test server I could try to bounce the server. But even on restart it still occurred. The only fix was to put SQL into single user mode and run the following.

USE [tempdb]
GO
CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC FREEPROCCACHE
GO
DBCC FREESYSTEMCACHE ('ALL');
GO
DBCC FREESESSIONCACHE;
GO
DBCC SHRINKFILE ('tempdev8' , emptyfile)
GO
ALTER DATABASE [tempdb] REMOVE FILE [tempdev8]
GO

 

SQL: Read from the registry

Now that you have your SQL Agent accounts set up to use DatabaseMail let’s check the registry.

--
-- We have to know the output values to prevent return nothing
--
DECLARE @nvcREG_SZ NVARCHAR(4000),
    @nREG_DWORD INT,
    @vbREG_BINARY VARBINARY

EXEC [master].[dbo].[xp_instance_regread]
    N'HKEY_LOCAL_MACHINE',
    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
    N'UseDatabaseMail',
    @nREG_DWORD OUTPUT
SELECT  @nREG_DWORD AS [UseDatabaseMail]

EXEC [master].[dbo].[xp_instance_regread]
    N'HKEY_LOCAL_MACHINE',
    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
    N'DatabaseMailProfile',
    @nvcREG_SZ OUTPUT
SELECT  @nvcREG_SZ AS [DatabaseMailProfile]

The nice thing about xp_instance_regread is it will figure out what instance of SQL you are running and so e.g.

 N'HKEY_LOCAL_MACHINE',
 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent' 

becomes

 N'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.MSSQLSERVER\SQLServerAgent'

SQL ERROR: ‘JOBID’ scripting variable not defined.

I often run scripts, especially SQL Agent job scripts using SQLCMD. Moving to SQL 2014 I ran into this error: ‘JOBID’ scripting variable not defined.

I see it is because I also use a token variable in the last job step. A quick solution for me was to add the -x parameter to SQLCMD ( -x (disable variable substitution) ) as suggested as one of the workarounds here.

 

SQL Server: List Service Accounts’ Owners

Here’s a couple of ways to get it via code.

/*

http://sqlandme.com/2013/08/20/sql-service-get-sql-server-service-account-using-t-sql/
*/
DECLARE @DBEngineLogin VARCHAR(100)
DECLARE @AgentLogin VARCHAR(100)

EXECUTE [master].[dbo].[xp_instance_regread]
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SYSTEM\CurrentControlSet\Services\MSSQLServer',
@value_name = N'ObjectName',
@value = @DBEngineLogin OUTPUT

EXECUTE [master].[dbo].[xp_instance_regread]
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SYSTEM\CurrentControlSet\Services\SQLServerAgent',
@value_name = N'ObjectName',
@value = @AgentLogin OUTPUT

SELECT [DBEngineLogin] = @DBEngineLogin,
[AgentLogin] = @AgentLogin
GO

SELECT [servicename],
[service_account]
FROM [sys].[dm_server_services]
GO