Getting SQL Server Activity Monitor's Output using t-SQL - sql-server

How to get the SQL Server Activity Monitor's output using T-SQL???

In order to get exactly same output as Activity Monitor; I have created a following script.
If you use this script, you don't need sp_who2 or activity monitor to run.
The script that I have created will display the following things:
[Session ID]
[User Process]
[Login]
[Blocked By]
[Head Blocker]
[DatabaseName]
[Task State]
[Command]
[statement_text] --It will display the statement which is being executed presently.
[command_text] ----- It will display the Stored Procedure's Name.
[Total CPU (ms)]
'Elapsed Time (in Sec)'
[Wait Time (ms)]
[Wait Type]
[Wait Resource]
[Memory Use (KB)]
[Host Name]
[Net Address]
[Workload Group]
[Application]
My Activity Monitor's Script is as follows:
/* ACTIVITY MONITOR'S OUTPUT along with statement_text and command_text */ /* Processes */
SELECT [Session ID] = s.session_id,
[User Process] = CONVERT(CHAR(1), s.is_user_process),
[Login] = s.login_name,
[Blocked By] = ISNULL(CONVERT (varchar, w.blocking_session_id), ''),
[Head Blocker] =
CASE
-- session has an active request, is blocked, but is blocking others or session is idle but has an open tran and is blocking others
WHEN r2.session_id IS NOT NULL AND (r.blocking_session_id = 0 OR r.session_id IS NULL) THEN '1'
-- session is either not blocking someone, or is blocking someone but is blocked by another party
ELSE ''
END,
[DatabaseName] = ISNULL(db_name(r.database_id), N''),
[Task State] = ISNULL(t.task_state, N''),
[Command] = ISNULL(r.command, N''),
[statement_text] = Substring(st.TEXT, (r.statement_start_offset / 2) + 1,
( ( CASE r.statement_end_offset WHEN - 1 THEN Datalength(st.TEXT)
ELSE r.statement_end_offset
END - r.statement_start_offset ) / 2 ) + 1), ----It will display the statement which is being executed presently.
[command_text] =Coalesce(Quotename(Db_name(st.dbid)) + N'.' + Quotename(Object_schema_name(st.objectid, st.dbid)) + N'.' + Quotename(Object_name(st.objectid, st.dbid)), ''), -- It will display the Stored Procedure's Name.
[Total CPU (ms)] = r.cpu_time,
r.total_elapsed_time / (1000.0) 'Elapsed Time (in Sec)',
[Wait Time (ms)] = ISNULL(w.wait_duration_ms, 0),
[Wait Type] = ISNULL(w.wait_type, N''),
[Wait Resource] = ISNULL(w.resource_description, N''),
[Total Physical I/O (MB)] = (s.reads + s.writes) * 8 / 1024,
[Memory Use (KB)] = s.memory_usage * 8192 / 1024,
--[Open Transactions Count] = ISNULL(r.open_transaction_count,0),
--[Login Time] = s.login_time,
--[Last Request Start Time] = s.last_request_start_time,
[Host Name] = ISNULL(s.host_name, N''),
[Net Address] = ISNULL(c.client_net_address, N''),
-- [Execution Context ID] = ISNULL(t.exec_context_id, 0),
-- [Request ID] = ISNULL(r.request_id, 0),
[Workload Group] = N'',
[Application] = ISNULL(s.program_name, N'')
FROM sys.dm_exec_sessions s
LEFT OUTER JOIN sys.dm_exec_connections c ON (s.session_id = c.session_id)
LEFT OUTER JOIN sys.dm_exec_requests r ON (s.session_id = r.session_id)
LEFT OUTER JOIN sys.dm_os_tasks t ON (r.session_id = t.session_id
AND r.request_id = t.request_id)
LEFT OUTER JOIN
( -- In some cases (e.g. parallel queries, also waiting for a worker), one thread can be flagged as
-- waiting for several different threads. This will cause that thread to show up in multiple rows
-- in our grid, which we don't want. Use ROW_NUMBER to select the longest wait for each thread,
-- and use it as representative of the other wait relationships this thread is involved in.
SELECT *,
ROW_NUMBER() OVER (PARTITION BY waiting_task_address
ORDER BY wait_duration_ms DESC) AS row_num
FROM sys.dm_os_waiting_tasks ) w ON (t.session_id = w.session_id)
AND w.row_num = 1
LEFT OUTER JOIN sys.dm_exec_requests r2 ON (r.session_id = r2.blocking_session_id) OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE s.session_Id > 50 -- Ignore system spids.
ORDER BY s.session_id --,[Total CPU (ms)] desc ;

Not exactly sure what you are looking for, but this should give you something similar what you see on the activity monitor (not completely but similar).
SELECT
P.spid,
RIGHT(CONVERT(VARCHAR, DATEADD(MS, DATEDIFF(MS, P.last_batch, GETDATE()), '1900-01-01'), 121), 12) AS [BATCH_DURATION],
P.program_name,
P.hostname AS HOST_NAME,
P.loginame AS LOGIN_NAME
FROM master.dbo.sysprocesses AS P
WHERE
P.spid > 50 AND
P.status NOT IN ('background', 'sleeping') AND
P.cmd NOT IN
(
'AWAITING COMMAND',
'MIRROR HANDLER',
'LAZY WRITER',
'CHECKPOINT SLEEP',
'RA MANAGER'
)
ORDER BY 2
The reason we are looking for SPID > 50 is because processes that has ID smaller than 50 belongs to internal operations. Anything greater than 50 should be for user actions.
Also, you can see all the blockings etc. on a db, you could try something like this.
SELECT
db.name AS DB_NAME,
tl.request_session_id AS REQUESTING_SESSION,
wt.blocking_session_id AS BLOCKING_SESSION,
OBJECT_NAME(p.OBJECT_ID) AS BLOCKED_OBJECT,
tl.resource_type AS RESOURCE_TYPE,
h1.TEXT AS REQUEST_QUERY,
h2.TEXT AS BLOCKING_QUERY,
tl.request_mode
FROM sys.dm_tran_locks AS tl
INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id
INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
You can possibly combine these to get what exactly you are looking for.
Hope this helps.

Related

Where to find date & time of currently running SQL agent job STEP?

I want to query a view or table for the currently running SQL agent job steps and when did they start.
I've tried queries below but it gives me JOB datetime rather then step datetime.
select top 100 * from msdb.dbo.sysjobsteps
select top 100 * from msdb.dbo.sysjobstepslogs
select top 100 * from msdb.dbo.sysjobhistory
exec master.dbo.xp_sqlagent_enum_jobs 1 , garbage -- gives me currently running job step
Screen Shot of desired values below from SQL Activity Monitor.
try the following
SELECT
ja.job_id as JobId,
j.name AS JobName,
ja.start_execution_date as StartDn,
ISNULL(last_executed_step_id,0)+1 AS CurrentStepId
FROM msdb.dbo.sysjobactivity ja
LEFT JOIN msdb.dbo.sysjobhistory jh ON ja.job_history_id = jh.instance_id
INNER JOIN msdb.dbo.sysjobs j ON ja.job_id = j.job_id
INNER JOIN msdb.dbo.sysjobsteps js ON ja.job_id = js.job_id AND ISNULL(ja.last_executed_step_id,0)+1 = js.step_id
INNER JOIN msdb.dbo.syssessions r ON r.session_id = ja.session_id
WHERE start_execution_date is not null
AND stop_execution_date is null;
You might check this article for further information
hope this will help you
/* Hank Freeman */
use master
go
SELECT
ja.job_id,
j.name AS job_name,
ja.start_execution_date,
--2019-06-10 18:54:31.000
getdate() as 'NOW',
'0'+Cast(Datepart(hh,(getdate() - ja.start_execution_date)) as char(2)) + ':' +
Cast(Datepart(n,(getdate() - ja.start_execution_date)) as char(2)) + ':' +
'0'+Cast(Datepart(ss,(getdate() - ja.start_execution_date)) as char(2)) as 'Duration',
Cast(DATEDIFF(n,ja.start_execution_date,getdate()) as char(5)) as 'Duration_Mins',
ISNULL(last_executed_step_id,0)+1 AS cur_exec_step_id,
Js.step_name
FROM msdb.dbo.sysjobactivity ja
LEFT JOIN msdb.dbo.sysjobhistory jh
ON ja.job_history_id = jh.instance_id
JOIN msdb.dbo.sysjobs j
ON ja.job_id = j.job_id
JOIN msdb.dbo.sysjobsteps js
ON ja.job_id = js.job_id
AND ISNULL(ja.last_executed_step_id,0)+1 = js.step_id
WHERE ja.session_id = (
SELECT TOP 1 session_id
FROM msdb.dbo.syssessions
ORDER BY session_id DESC
)
AND start_execution_date is not null
AND stop_execution_date is null
order by 2
;

SQL query to list head blockers

Is there a way to query a database either by sql query or C# to get me a list or datatable of head blockers currently locking up the database?
Use the following SQL, replacing 'MyDatabaseName' with either; the name of your database, or the value, NULL.
DECLARE
#Database NVARCHAR(MAX) = 'MyDatabaseName'
SELECT
s.login_name AS [Login]
, ISNULL(db_name(p.dbid), N'') AS [Database]
, ISNULL(t.task_state, N'') AS [Task State]
, ISNULL(r.command, N'') AS [Command]
, s.cpu_time AS [Total CPU (ms)]
, (s.reads + s.writes) * 8 / 1024 AS [Total Physical I/O (MB)]
, s.memory_usage * 8192 / 1024 AS [Memory Use (KB)]
FROM
sys.dm_exec_sessions AS s
LEFT OUTER JOIN sys.dm_exec_requests AS r ON (s.session_id = r.session_id)
LEFT OUTER JOIN sys.dm_os_tasks AS t ON (r.session_id = t.session_id AND r.request_id = t.request_id)
LEFT OUTER JOIN sys.dm_exec_requests AS r2 ON (s.session_id = r2.blocking_session_id)
LEFT OUTER JOIN sys.sysprocesses AS p ON (s.session_id = p.spid)
WHERE
r2.session_id IS NOT NULL
AND (r.blocking_session_id = 0 OR r.session_id IS NULL)
AND (#Database IS NULL OR ISNULL(db_name(p.dbid), N'') = #Database)
ORDER BY
s.cpu_time DESC
Note: A value of NULL will check all databases within that server.

View Truncated Tables from All Databases on SQL Server 2012

I'm working on a project that focuses on truncated tables in a server. The goal of the project is to record all truncated tables in the audit table. I've worked on a code below that works fine on a single database; however, I'm not able to run that code automatically on all databases. I've tried writing:
Cursor
Using Exec ('Use ' + #DatabaseName + ';') in the stored procedure.
Exec sp_MSforeachDB and the stored procedure.
Every single time I try to run the sproc for all databases it is executed on a database where the code exists. How can I execute it on all databases.
Main query:
DBCC TRACEON (2537) -- All Log Files
;WITH TranCte as ( SELECT
[Transaction Id]
,[Transaction Name]
,[Begin Time]
,SUSER_SNAME( [Transaction SID]) AS [User]
,[Operation] FROM fn_dblog (NULL, NULL) WHERE [Transaction Name] = 'TRUNCATE TABLE'),
ObjectCte AS
(SELECT
[Lock Information]
,[Transaction Name]
,[Transaction Id]
FROM fn_dblog (NULL, NULL)
WHERE [Transaction Id] IN (SELECT
[Transaction Id]
FROM fn_dblog(NULL, NULL)
WHERE [Transaction Name] = 'TRUNCATE TABLE' )
AND [Lock Information] LIKE '%SCH_M OBJECT%'),
ConvertStringToRows ( [Lock Information], starts, pos, [Transaction ID]) AS
(SELECT
[Lock Information]
,1
,CHARINDEX( ':', [Lock Information])
,[Transaction ID]
FROM ObjectCte UNION ALL SELECT
[Lock Information]
,pos + 1
,CHARINDEX( ':', [Lock Information], pos + 1)
,[Transaction ID]
FROM ConvertStringToRows
WHERE pos > 0 ),
ConvertStringToRowsDetails AS (SELECT
*
,RowN = ROW_NUMBER () OVER (PARTITION BY [Lock Information] , [Transaction ID] ORDER BY Starts , [Transaction ID] )
,ColumnType =
CASE ROW_NUMBER () OVER (PARTITION BY [Lock Information], [Transaction ID] ORDER BY Starts , [Transaction ID] )
WHEN 3 THEN 'Database'
WHEN 4 THEN 'Object'
END
,DetailsID = SUBSTRING ([Lock Information], starts, CASE
WHEN pos > 0 THEN pos - starts
ELSE LEN ([Lock Information])
END)
FROM ConvertStringToRows )
, CTE_Report
AS (SELECT
e.*
,ObjectID = ob .DetailsID
,DatabaseID = db .DetailsID
,o. [Lock Information]
,TableName = OBJECT_NAME (ob. DetailsID, db.DetailsID )
,[Database] = DB_NAME (db. DetailsID)
FROM TranCte e
JOIN ObjectCte o
ON e .[Transaction Id] = o .[Transaction Id]
JOIN ConvertStringToRowsDetails db
ON o .[Lock Information] = db .[Lock Information]
AND db .ColumnType = 'Database'
JOIN ConvertStringToRowsDetails ob
ON o .[Lock Information] = ob .[Lock Information]
AND ob .ColumnType = 'Object' )
SELECT * FROM CTE_Report
That code will reference the system tables for the database you're currently in every time, so will only show that database's data.
If you want to execute it across databases, you'll need to either put the code into each database and run it from there using one of the methods you've already tried, or create composite views and functions that aggregate the code from a specified list of databases, and read from them.
Or you could put all that code into dynamic SQL and EXEC it against a specified database inside your sproc. But I really wouldn't do that.
EDIT - Commenter is right. Ignore my earlier prejudice. Do the dynamic SQL thing. One of the very few SO questions where it's the right answer.

Query Results Differ From SSRS Results

I have a query that pulls accurate data when ran on SSMS, but when I create a report using SSRS with the exact same query, it misses out results that come from one of two temp tables I use.
DECLARE #from int --= #fromparameter
DECLARE #to int --= #toparameter
/*
For debug
*/
set #from = 0
set #to = 50
/*
================================================================================
Build a temp table with all accounts that have a move out date within params
================================================================================
*/
IF OBJECT_ID('tempdb.dbo.#tempProperty', 'U') is not null drop table #tempProperty
select
sa.spark_AccountNumber
,sa.spark_PropertyIdName
into
#tempProperty
from
SparkCRM_MSCRM.dbo.spark_account sa
where
sa.spark_AccountNumber IN (
select distinct
sa.spark_AccountNumber
--,sa.spark_TenantMoveinDate
--,sa.CreatedOn
--,DATEDIFF(day,sa.spark_TenantMoveinDate,sa.CreatedOn) as [Difference]
from
SparkCRM_MSCRM.dbo.spark_account sa
where
sa.spark_TenantMoveinDate BETWEEN dateadd(DAY,#from,getdate()) AND dateadd(DAY,#to,getdate())
)
/*
================================================================================
--create CTE with all accounts per property
================================================================================
*/
--;with RowRanked (AccountNumber,Name,Rowrank,MoveinDate,MoveOotDate,SProperty,PProperty)
--AS
--(
IF OBJECT_ID('tempdb.dbo.#temp', 'U') is not null drop table #temp
SELECT
sa.spark_AccountNumber [Account Number]
,sa.spark_name [Account Name]
,ROW_NUMBER() OVER(PARTITION BY sa.spark_PropertyIDName ORDER BY COALESCE (sa.spark_TenantMoveinDate, sa.spark_agreementdate) DESC) [rowRank]
,COALESCE (sa.spark_TenantMoveinDate, sa.spark_agreementdate) [Tenant Move In Date]
,sa.spark_TenantMoveoutDate [Tenant Move Out Date]
,sa.spark_PropertyIdName [Property ID]
,p.spark_name [Property Name]
into #temp
FROM
SparkCRM_MSCRM.dbo.spark_property p
LEFT JOIN
SparkCRM_MSCRM.dbo.spark_account sa
on sa.spark_PropertyId = p.spark_propertyId
WHERE
sa.spark_PropertyIdName IN (SELECT spark_PropertyIdName from #tempProperty)
--)
/*
================================================================================
build final dataset
================================================================================
*/
select distinct
sa.spark_AccountNumber [Account Number]
,sa.spark_name [Name]
,concat (
sa.spark_HouseNumber ,' ',
sa.spark_HouseName ,' ',
sa.spark_Address1 ,' ',
sa.spark_Address2 ,' ',
sa.spark_Address3 ,' ',
sa.spark_Address4 ,' ',
sa.spark_Postcode
) [Address]
,sa.spark_Email [Email]
,sa.spark_HomePhone [Landline]
,sa.spark_Mobile [Mobile Number]
,COALESCE(a3.Name,a2.Name,a1.Name) [Letting Agent Partner]
,sa.spark_tariffidName [Tariff]
,sa.spark_PPMTariffName [PPM Tariff]
,pm.Option_Label [Payment Method]
,sa.spark_Balance [Account Balance]
,sa.spark_IntendedMoveOut [Date of Likely Move Out]
,sa.spark_TenantMoveoutDate [Current Tenant Move Out Date]
,rr.[Account Number] [New Account Number]
,rr.[Tenant Move In Date] [New Account Move In Date]
,case
when pc.spark_CallDriver is not null
then 'Yes'
else
'No'
end [Arrangement to Pay]
,ds.Option_Label [Stops]
from
SparkCRM_MSCRM.dbo.spark_account sa
--inner join
-- DBS.dbo.Meter m
-- on m.cust_ref = sa.spark_AccountNumber collate DATABASE_default
-- and m.meter_status = 2
left join
SparkCRM_MSCRM.dbo.spark_property sp
on sp.spark_propertyid = sa.spark_propertyid
left join
SparkCRM_MSCRM.dbo.account a1 --branch
on sp.spark_PartnerId = a1.accountid
left join
SparkCRM_MSCRM.dbo.account a2 --brand
on a1.parentaccountid = a2.accountid
left join
SparkCRM_MSCRM.dbo.account a3 --partner
on a2.parentaccountid = a3.accountid
left join
SparkCRM_Custom.dbo.GetCRMOptions('spark_account', 'spark_paymentmethod') pm
ON pm.Option_Value = sa.spark_paymentmethod
left join
SparkCRM_Custom.dbo.GetCRMOptions('spark_account','spark_DebtorStatus') ds
on ds.Option_Value = sa.spark_DebtorStatus
left join
SparkCRM_MSCRM.dbo.PhoneCall pc
on pc.spark_Account = sa.spark_accountId
and pc.spark_CallDriver = 101
left join
#temp rr
on rr.[Property ID] = sa.spark_PropertyIdName
and rr.Rowrank = 1
where
coalesce(
sa.spark_IntendedMoveOut
,sa.spark_TenantMoveoutDate
)
BETWEEN
dateadd(DAY,#from,getdate()) AND dateadd(DAY,#to,getdate())
and
sa.spark_name not like '%occupier%'
This returns data when I run the query in SQL Server Management Studio, but copying it into SSRS Report Builder seems to remove any results from the #temp table. You'll notice that I was originally use a CTE for the second table, but I tried using a temp table instead in case it SSRS was struggling with CTEs.
Any help would be much appreciated!
You should avoid using #temp tables in Reporting Services, if for no other reason that it will cause all sorts of trouble if people try to run the report concurrently.
It would be better for you to instead create a Stored Procedure that your Report can call. This will allow you to apply indexes and another performance modifications as needed, and it will behave exactly the same as running the query stand-alone in SSMS

How can i link a sql server job name

to the SSRS report server process that uses it? the name looks like a guid, but i need to find the reporting services reports that use it.
thanks very much
Here's a query I blogged about a while back that does the join:
;WITH cte (job_id, job_name, execution_time, execution_order)
AS
(
SELECT DISTINCT j.job_id
,j.name
,CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/')
+ SPACE(1)
+ STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':'))
,ROW_NUMBER() OVER (PARTITION BY j.job_id ORDER BY CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/')
+ SPACE(1)
+ STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':')) DESC)
FROM msdb.dbo.sysjobs j
INNER JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
LEFT OUTER JOIN msdb.dbo.sysjobhistory jh ON j.job_id = jh.job_id
WHERE c.name ='Report Server'
)
SELECT
x.job_name
,c.name
,x.execution_time
,c.path
,su.description
,CONVERT(varchar(max), su.ExtensionSettings) as ExtensionSettings
,'EXEC msdb..sp_start_job ''' + x.job_name + '''' as SQLStatement
FROM cte x
INNER JOIN dbo.Schedule sc ON x.job_name = CONVERT(varchar(100), sc.ScheduleID)
INNER JOIN dbo.ReportSchedule rs ON sc.ScheduleID = rs.ScheduleID
INNER JOIN dbo.Subscriptions su ON rs.SubscriptionID = su.SubscriptionID
INNER JOIN dbo.Catalog c ON su.Report_OID = c.ItemID
WHERE execution_order = 1
ORDER BY 3, 2
There doesn't appear to be a straightforward method to find this out.
The following query lists the subscription IDs and the reports to which they link
select s.SubscriptionID, c.Path
from ReportServer.dbo.Subscriptions as s
JOIN ReportServer.dbo.Catalog as c
on ItemID = Report_OID
The subscription ID is then referenced inside the job step, in the following format.
exec ReportServer.dbo.AddEvent #EventType='TimedSubscription', #EventData='~subscriptionID~'
It should be possible to write a query to join it all together, but I don't have time right now. I will try and update the question later.

Resources