Notifications for SQL Job when a step fails - sql

Trying to find out if there is a way to setup email notifications when just 1 (or more) steps fail on a sql job. I have a job with 9 steps, but each step needs to be set to continue to next step even if it fails. So even when a step fails, because I need it to go to the next step its not set to "report failure". As SQL Server Agent does not have an option for "Report failure and go to next step" I am wondering if anyone has any workarounds for getting a notification

You can add an additional job step to query the msdb tables for steps that failed. After this, the sp_send_dbmail stored procedure can be used to send an email with the errors if any occurred. The run_date column of SYSJOBHISTORY is an int column, so the date will be along the format of YYYYMMDD. The filter below on the run_status column will apply to individual steps regardless of the overall job outcome, with 0 indicating a status of failed.
DECLARE #JobExecutionDate INT
--current date
SET #JobExecutionDate = CAST(CONVERT(VARCHAR(8),GETDATE(),112) AS INT)
--check if there were any errors first
IF EXISTS (SELECT h.instance_id
FROM MSDB.DBO.SYSJOBHISTORY h
INNER JOIN MSDB.DBO.SYSJOBS j ON h.job_id = j.job_id
INNER JOIN MSDB.DBO.SYSJOBSTEPS s ON j.job_id = s.job_id AND h.step_id = s.step_id
WHERE h.run_status = 0 AND h.run_date = #JobExecutionDate AND j.name = 'YourJobName')
BEGIN
DECLARE #Title VARCHAR(50)
SET #Title = CONCAT(CONVERT(VARCHAR(12), CAST(GETDATE() AS DATE), 109), ' Job Error Email')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Your Database Mail Profile',
#recipients = 'ExampleEmail#Domain.com',
#query = 'SELECT j.[name] AS JobName,
s.step_name AS StepName,
h.run_date AS RunDate,
h.run_time AS RunTime,
h.sql_severity As ErrorSeverity,
h.message AS ErrorMessage
FROM MSDB.DBO.SYSJOBHISTORY h
INNER JOIN MSDB.DBO.SYSJOBS j ON h.job_id = j.job_id
INNER JOIN MSDB.DBO.SYSJOBSTEPS s ON j.job_id = s.job_id AND h.step_id = s.step_id
WHERE h.run_status = 0 AND h.run_date = CAST(CONVERT(VARCHAR(8),GETDATE(),112) AS INT) AND j.name = ''YourJobName''
',
#query_result_no_padding = 1,
#subject = #Title ;
END

Related

Query takes too long because of <> in where clause

I'm building a script to send by email. I've a table with transactions and I want to send by email only when status is "failed" . The table has now ~ 50 millions of rows and it will keep increasing and I cannot archive it.
this is the query:
if exists (select top 1 1 from TicketTransactionDetails where ServiceStatus != 0)
begin
DECLARE #tableHTML NVARCHAR(MAX) ;
SET #tableHTML =
N'<H1>Transactions Status</H1>' +
N'<table border="1">' +
N'<tr><th>TransactionDate</th><th>NbOfRecords</th>' +
N'<th>ServiceStatus</th><th>StatusDescription</th><th>RunDate</th></tr>' +
CAST ( (select td = CAST(InsertDate as date), '',
td = COUNT(*),'',
td = ServiceStatus,'',
td = b.StatusDescription,'',
td = GETDATE()
from TicketTransactionDetails a
inner join ServiceStatuses b on a.ServiceStatus = b.StatusID
where ServiceStatus = 0
group by CAST(InsertDate as date),ServiceStatus,b.StatusDescription
order by CAST(InsertDate as date) desc
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
exec msdb.dbo.sp_send_dbmail
#profile_name = 'DB_Maintenance',
#recipients = 'a.a#a.a',
#subject = 'Tranzanctions with errors',
#body = #tableHTML,
#body_format = 'html';
end
What takes a lot to execute (~ 25sec) is:
select top 1 1 from TicketTransactionDetails where ServiceStatus != 0
Is there way to improve my query?
Many thanks in advance.
A couple of things you can do -
Firstly, check whether you have an index on the column ServiceStatus. If not then create it. That really ought to do it.
The other option, although risky is to add a (nolock) hint to your query. This will bypass any locks held on the table
select top 1 1 from TicketTransactionDetails (nolock) where ServiceStatus != 0
Use count instead, count perform much better than top
if exists (select count(1) from TicketTransactionDetails where ServiceStatus != 0)

SQL EXEC PROCEDURE: "Must declare the scalar variable "#p1"

I am getting the following error when I try to execute the stored procedure below:
Must declare the scalar variable "#p1"
I don't understand why or how to fix, any help would be appreciated. thanKs
Stored procedure:
USE [SERVER_NAME]
GO
/****** Object: StoredProcedure [dbo].[APP_jdtest_shp_0] Script Date: 16/12/2019 11:13:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[jdtest_shp_0]
#p1 nvarchar(100),
#n nvarchar(100)
AS
EXEC('
CREATE VIEW dbo.[' + #n + '] AS
SELECT
RTRIM([F].[F_CODE]) As F_UID ,
RTRIM([TP].[F_TP_NAME]) As F_TP_UID ,
RTRIM([NS].[F_CODE]) AS F_CODE,
RTRIM([NS].[SOME_DATE]) AS SOME_DATE,
RTRIM([NS].[ANOTHER_DATE]) AS ANOTHER_DATE,
RTRIM([NS].[SPD]) AS SPD,
RTRIM([NS].[LK_DATE]) AS LK_DATE,
RTRIM([NS].[RC_DATE]) AS RC_DATE,
RTRIM([NS].[RD_DATE]) AS RD_DATE,
RTRIM([NS].[OLD_UID]) AS OLD_UID,
RTRIM([NS].[VN]) AS VN,
RTRIM([NS].[R_I]) AS R_I,
RTRIM([NS].[WTU_UID]) AS WTU_UID,
RTRIM([NS].[D_LT]) AS D_LT,
RTRIM([PLT_UD].[PLT]) As L_A_PLT_UD_UID ,
RTRIM([RT].[RT_NAME]) As RT_UID ,
RTRIM([SS].[S_S_NAME]) As S_S_UID ,
RTRIM([NS].[S_DATE]) AS S_DATE,
RTRIM([SUR].[S_SUR_NAME]) As S_SUR_UID ,
RTRIM([NS].[S_TOL]) AS S_TOL,
RTRIM([LKP_AUTH].[AUTH_NAME]) As AUTH_UID ,
[NS].[S_G] AS S_G,
RTRIM([NS].[NS_UID]) AS NS_UID,
RTRIM([NSG_C].[C_NAME]) As C_UID ,
RTRIM([NS].[CLT]) AS CLT,
RTRIM([NS].[ONR_UID]) AS ONR_UID,
RTRIM([NC].[S_CLF_NAME]) As S_CLF_UID ,
RTRIM([NS].[XP]) AS XP,
RTRIM([NS].[CSTART_X]) AS CSTART_X,
RTRIM([NS].[CSTART_Y]) AS CSTART_Y,
RTRIM([NS].[CEND_X]) AS CEND_X,
RTRIM([NS].[CEND_Y]) AS CEND_Y
FROM NS
LEFT OUTER JOIN F ON NS.F_UID = F.F_UID
LEFT OUTER JOIN FT ON NS.F_TP_UID = FT.FT_UID
LEFT OUTER JOIN PLT_UD ON NS.L_A_PLT_UD_UID = SEC_PLT_UD.PLT_UD_UID
LEFT OUTER JOIN RT ON NS.RT_UID = RT.RT_UID
LEFT OUTER JOIN STT ON NS.S_S_UID = SS.S_S_UID
LEFT OUTER JOIN SUR ON NS.S_SUR_UID = SUR.S_SUR_UID
LEFT OUTER JOIN AUTH ON NS.AUTH_UID = AUTH.AUTH_UID
LEFT OUTER JOIN C ON NS.C_UID = C.C_UID
LEFT OUTER JOIN NSC ON NS.S_CLF_UID = NSC.S_CLF_UID
WHERE
([NS].[SHAPE_GEOMETRY].STIntersects(Geometry::STGeomFromText(' + '#p1' + ', 0).MakeValid())>0) AND
([NS].[S_G].STGeometryTP() = ''POINT'') '
)
EDIT: using sql server 2014. This is not my code, I am trying to fix a bug in someone else's code.
UPDATE: updated the 'execute command' section to show how the procedure is being executed
You need to use sp_executesql instead of EXEC() if you want to use parameters in your dynamic statement:
CREATE PROCEDURE [dbo].[123456]
#p1 nvarchar(100),
#n nvarchar(100)
AS
BEGIN
DECLARE #stm nvarchar(max)
DECLARE #err int
SET #stm =
N'CREATE VIEW dbo.' + QUOTENAME(#n) + N' AS ' +
N'SELECT
RTRIM([FEATURE].[FEATURE_CODE]) As FEATURE_UID ,
RTRIM([FEATURE_TYPE].[FEATURE_TYPE_NAME]) As FEATURE_TYPE_UID ,
RTRIM([NSG_STREETS].[FEATURE_CODE]) AS FEATURE_CODE,
RTRIM([NSG_STREETS].[START_DATE]) AS START_DATE,
RTRIM([NSG_STREETS].[END_DATE]) AS END_DATE,
RTRIM([NSG_STREETS].[SUSPEND_ACTIVITIES]) AS SUSPEND_ACTIVITIES,
RTRIM([NSG_STREETS].[RECORD_ENTRY_DATE]) AS RECORD_ENTRY_DATE,
RTRIM([NSG_STREETS].[RECORD_CHANGE_DATE]) AS RECORD_CHANGE_DATE,
RTRIM([NSG_STREETS].[RECORD_DELETE_DATE]) AS RECORD_DELETE_DATE,
RTRIM([NSG_STREETS].[OLD_SYSTEM_UID]) AS OLD_SYSTEM_UID,
RTRIM([NSG_STREETS].[VERSION_NUMBER]) AS VERSION_NUMBER,
RTRIM([NSG_STREETS].[RECORD_IDENTIFIER]) AS RECORD_IDENTIFIER,
RTRIM([NSG_STREETS].[WARD_UID]) AS WARD_UID,
RTRIM([NSG_STREETS].[DIGITAL_LENGTH]) AS DIGITAL_LENGTH,
RTRIM([SEC_USER].[USER_NAME]) As LAST_EDIT_USER_UID ,
RTRIM([LKP_RECORD_TYPE].[RECORD_TYPE_NAME]) As RECORD_TYPE_UID ,
RTRIM([LKP_STREET_STATE].[STREET_STATE_NAME]) As STREET_STATE_UID ,
RTRIM([NSG_STREETS].[STATE_DATE]) AS STATE_DATE,
RTRIM([LKP_STREET_SURFACE].[STREET_SURFACE_NAME]) As STREET_SURFACE_UID ,
RTRIM([NSG_STREETS].[STREET_TOLERANCE]) AS STREET_TOLERANCE,
RTRIM([LKP_AUTHORITY].[AUTHORITY_NAME]) As AUTHORITY_UID ,
[NSG_STREETS].[SHAPE_GEOGRAPHY] AS SHAPE_GEOGRAPHY,
RTRIM([NSG_STREETS].[NSG_STREETS_UID]) AS NSG_STREETS_UID,
RTRIM([NSG_COUNTY].[COUNTY_NAME]) As COUNTY_UID ,
RTRIM([NSG_STREETS].[CLASS_UID]) AS CLASS_UID,
RTRIM([NSG_STREETS].[OWNER_UID]) AS OWNER_UID,
RTRIM([NSG_STREET_CLASSIFICATION].[STREET_CLASSIFICATION_NAME]) As STREET_CLASSIFICATION_UID ,
RTRIM([NSG_STREETS].[EXPORT]) AS EXPORT,
RTRIM([NSG_STREETS].[CSTART_X]) AS CSTART_X,
RTRIM([NSG_STREETS].[CSTART_Y]) AS CSTART_Y,
RTRIM([NSG_STREETS].[CEND_X]) AS CEND_X,
RTRIM([NSG_STREETS].[CEND_Y]) AS CEND_Y FROM NSG_STREETS
LEFT OUTER JOIN FEATURE ON NSG_STREETS.FEATURE_UID = FEATURE.FEATURE_UID
LEFT OUTER JOIN FEATURE_TYPE ON NSG_STREETS.FEATURE_TYPE_UID = FEATURE_TYPE.FEATURE_TYPE_UID
LEFT OUTER JOIN SEC_USER ON NSG_STREETS.LAST_EDIT_USER_UID = SEC_USER.USER_UID
LEFT OUTER JOIN LKP_RECORD_TYPE ON NSG_STREETS.RECORD_TYPE_UID = LKP_RECORD_TYPE.RECORD_TYPE_UID
LEFT OUTER JOIN LKP_STREET_STATE ON NSG_STREETS.STREET_STATE_UID = LKP_STREET_STATE.STREET_STATE_UID
LEFT OUTER JOIN LKP_STREET_SURFACE ON NSG_STREETS.STREET_SURFACE_UID = LKP_STREET_SURFACE.STREET_SURFACE_UID
LEFT OUTER JOIN LKP_AUTHORITY ON NSG_STREETS.AUTHORITY_UID = LKP_AUTHORITY.AUTHORITY_UID
LEFT OUTER JOIN NSG_COUNTY ON NSG_STREETS.COUNTY_UID = NSG_COUNTY.COUNTY_UID
LEFT OUTER JOIN NSG_STREET_CLASSIFICATION ON NSG_STREETS.STREET_CLASSIFICATION_UID = NSG_STREET_CLASSIFICATION.STREET_CLASSIFICATION_UID
WHERE
([NSG_STREETS].[SHAPE_GEOMETRY].STIntersects(Geometry::STGeomFromText(#p1, 0).MakeValid())>0) AND
([NSG_STREETS].[SHAPE_GEOGRAPHY].STGeometryType() = ''POINT'') '
EXEC #err = sp_executesql #stm, N'#p1 nvarchar(100)', #p1
IF #err <> 0 BEGIN
PRINT 'Error'
RETURN #err
END
END

TempDB drive Full - Procedure needs much performance?

following situation: We have an azure server with db and the TempDB drive ran full. At this moment we could find a process with much resources need in activity monitor. The process was not killable cause the rollback couldn't be done cause of the full drive.
Now I have two questions:
Can the process be the cause of the huge tempdb files?
Can someone explain why the process needs so much resources?
Attach you find a screenshot of the activity monitor and the code of the procedure.
The procedure is started every 10 seconds with SQL Server agent. The loop inside the procedure is not that nice but we needed the statistics and it run well for the last 3 weeks.
CREATE PROCEDURE Log_Blocking_Processes
AS
BEGIN
IF OBJECT_ID('dbo.Log_Blocked_Processes', 'U') IS NULL
BEGIN
SELECT GETDATE() as Tag,
db.name DBName,
tl.request_session_id,
wt.blocking_session_id,
OBJECT_NAME(p.OBJECT_ID) BlockedObjectName,
tl.resource_type,
h1.TEXT AS RequestingText,
h2.TEXT AS BlockingText,
tl.request_mode,
er.transaction_id as Requesting_Transaction_ID,
tst.transaction_id as Blocking_Transaction_ID,
tat.name as Blocking_Transaction_Name,
er.wait_time/1000 as Wait_Time_SEC
INTO Log_Blocked_Processes
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
INNER JOIN sys.dm_exec_requests er ON er.session_id = tl.request_session_id AND er.blocking_session_id = wt.blocking_session_id AND er.blocking_session_id <> 0
INNER JOIN sys.dm_tran_session_transactions tst ON tst.session_id = wt.blocking_session_id
INNER JOIN sys.dm_tran_active_transactions tat ON tat.transaction_id = tst.transaction_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
WHERE db.database_id = DB_ID();
RETURN;
END;
DECLARE #DBName nvarchar(128),
#request_session_id int,
#blocking_session_id smallint,
#BlockedObjectName nvarchar(128),
#resource_type nvarchar(60),
#RequestingText nvarchar(MAX),
#BlockingText nvarchar(MAX),
#request_mode nvarchar(60),
#Requesting_Transaction_ID bigint,
#Blocking_Transaction_ID bigint,
#Blocking_Transaction_Name nvarchar(32),
#Wait_Time_SEC int,
#Tag DATE,
#Mycount int,
#LastInsertDay DATE,
#counter int = 1;
DECLARE blocked_processes_cursor CURSOR FOR
SELECT cast(GETDATE() as DATE) as Tag,
db.name DBName,
tl.request_session_id,
wt.blocking_session_id,
OBJECT_NAME(p.OBJECT_ID) BlockedObjectName,
tl.resource_type,
h1.TEXT AS RequestingText,
h2.TEXT AS BlockingText,
tl.request_mode,
er.transaction_id as Requesting_Transaction_ID,
tst.transaction_id as Blocking_Transaction_ID,
tat.name as Blocking_Transaction_Name,
er.wait_time/1000 as Wait_Time_SEC
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
INNER JOIN sys.dm_exec_requests er ON er.session_id = tl.request_session_id AND er.blocking_session_id = wt.blocking_session_id AND er.blocking_session_id <> 0
INNER JOIN sys.dm_tran_session_transactions tst ON tst.session_id = wt.blocking_session_id
INNER JOIN sys.dm_tran_active_transactions tat ON tat.transaction_id = tst.transaction_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
WHERE db.database_id = DB_ID();
WHILE #counter <= 4
BEGIN
OPEN blocked_processes_cursor
FETCH NEXT FROM blocked_processes_cursor INTO #Tag, #DBName, #request_session_id, #blocking_session_id, #BlockedObjectName, #resource_type, #RequestingText, #BlockingText, #request_mode, #Requesting_Transaction_ID, #Blocking_Transaction_ID, #Blocking_Transaction_Name, #Wait_Time_SEC;
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Mycount = count(*), #LastInsertDay = cast(max(Tag) as date) FROM Log_Blocked_Processes WHERE Requesting_Transaction_ID = #Requesting_Transaction_ID AND Blocking_Transaction_ID = #Blocking_Transaction_ID;
IF #Mycount > 0 AND #LastInsertDay = cast(getdate() as date)
BEGIN
UPDATE Log_Blocked_Processes
SET Wait_Time_SEC = #Wait_Time_SEC
WHERE Requesting_Transaction_ID = #Requesting_Transaction_ID
AND Blocking_Transaction_ID = #Blocking_Transaction_ID;
END;
ELSE
BEGIN
INSERT INTO [Log_Blocked_Processes]([Tag],[DBName],[request_session_id],[blocking_session_id],[BlockedObjectName],[resource_type],[RequestingText],[BlockingText],[request_mode],[Requesting_Transaction_ID],[Blocking_Transaction_ID],[Blocking_Transaction_Name],[Wait_Time_SEC])
VALUES(GETDATE(),#DBName,#request_session_id,#blocking_session_id,#BlockedObjectName,#resource_type,#RequestingText,#BlockingText,#request_mode,#Requesting_Transaction_ID,#Blocking_Transaction_ID,#Blocking_Transaction_Name,#Wait_Time_SEC)
END;
FETCH NEXT FROM blocked_processes_cursor INTO #Tag, #DBName, #request_session_id, #blocking_session_id, #BlockedObjectName, #resource_type, #RequestingText, #BlockingText, #request_mode, #Requesting_Transaction_ID, #Blocking_Transaction_ID, #Blocking_Transaction_Name, #Wait_Time_SEC;
END;
SET #counter = #counter + 1;
CLOSE blocked_processes_cursor;
WAITFOR DELAY '00:00:02';
END;
DEALLOCATE blocked_processes_cursor;
END;

Locking From Temp Table - SQL 2008 R2

I have just implemented a new database on our live environment, this database is fed information by a service brokers from our two transactional databases. When the messages come into the new database we have a series of stored procedures which manipulate the feed for each specific user.
I also have another set of stored procedures which re-manipulate the data by user instead of by vehicle, these are used by our maintenance screens to ensure we can change users visibility of the data.
The below stored procedure keeps locking up I have now amended this sp to update a temp table first and then just undertake one update against the main database, however this has not aided the situation, I have also amended so I can update in smaller batches and if this fails keep retrying until it is successful. This works 100% on our dev environment but on live it keeps locking. The throughput on the servicebrokers is not great enough to register the number of failures, I therefore believe I am locking myself within this sp?
I have included ---'THIS UPDATE KEEPS LOCKING' at the point of failure.
What could be causing this locking behavior?
USE [Isight]
GO
/** Object: StoredProcedure [dbo].[UserVisibilityForVehicles] Script Date: 07/18/2014 14:43:04 **/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UserVisibilityForVehicles]
-- Add the parameters for the stored procedure here
#Username VARCHAR(50)
WITH RECOMPILE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
PRINT 'UserVisibilityForVehicles Started'
-- Now Start to check security for user.
IF EXISTS ( SELECT ID FROM dbo.SecurityTable WHERE userid = #Username AND Deleted = 0)
BEGIN
CREATE TABLE #VehicleToUsers(ID BIGINT, NewRecord BIT DEFAULT(0))
CREATE CLUSTERED INDEX IDX_VehicleToUsers ON #VehicleToUsers(ID)
CREATE NonCLUSTERED INDEX IDX_NewRecord ON #VehicleToUsers(ID)
INSERT INTO #VehicleToUsers
( ID )
(
SELECT Distinct Veh.[ID]
FROM [iSight].[dbo].[Vehicle] Veh WITH (NOLOCK)
INNER JOIN SecurityTable WITH (NOLOCK) ON Veh.[System] = SecurityTable.[System]
WHERE SecurityType = 1 AND UserID = #Username AND SecurityTable.deleted = 0
)
INSERT INTO #VehicleToUsers
( ID )
(
SELECT DISTINCT Veh.[ID]
FROM [iSight].[dbo].[Vehicle] Veh WITH (NOLOCK)
INNER JOIN SecurityTable WITH (NOLOCK) ON Veh.[System] = SecurityTable.[System] AND Veh.CurrentSite = SecurityTable.[Site]
WHERE SecurityType = 2 AND UserID = #Username AND SecurityTable.deleted = 0
)
BEGIN
PRINT 'UserVisibilityForVehicles: ' + #Username
INSERT INTO #VehicleToUsers
( ID )
(
SELECT DISTINCT Vehicle.ID
FROM Manufacturer WITH (NOLOCK) INNER JOIN
ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement INNER JOIN
SecurityTable WITH (NOLOCK) ON Manufacturer.ManufacturerGroupID = SecurityTable.ManufacturerGroupID AND Vehicle.System = SecurityTable.System
WHERE (SecurityTable.SecurityType = 3) AND (SecurityTable.UserID = #Username) AND ManufacturerMake.Deleted = 0 AND ManufacturerAgreementSubcustomer.Deleted = 0 AND SecurityTable.deleted = 0
)
INSERT INTO #VehicleToUsers
( ID )
(
SELECT DISTINCT Vehicle.ID
FROM Manufacturer WITH (NOLOCK) INNER JOIN
ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement INNER JOIN
SecurityTable WITH (NOLOCK) ON Vehicle.System = SecurityTable.System AND Manufacturer.ID = SecurityTable.ManufacturerID
WHERE (SecurityTable.SecurityType = 4) AND (SecurityTable.UserID = #Username) AND ManufacturerMake.Deleted = 0 AND ManufacturerAgreementSubcustomer.Deleted = 0 AND SecurityTable.deleted = 0
)
INSERT INTO #VehicleToUsers
( ID )
(
SELECT DISTINCT Vehicle.ID
FROM Manufacturer WITH (NOLOCK) INNER JOIN
ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement INNER JOIN
SecurityTable WITH (NOLOCK) ON Vehicle.System = SecurityTable.System AND Manufacturer.ID = SecurityTable.ManufacturerID AND
ManufacturerAgreementSubcustomer.ID = SecurityTable.ManufacturerAgreementSub INNER JOIN
ManufacturerUserAgreementSubcustomer WITH (NOLOCK) ON
ManufacturerAgreementSubcustomer.ID = ManufacturerUserAgreementSubcustomer.ManufacturerAgreementSubcustomerID AND
SecurityTable.ManufacturerID = ManufacturerUserAgreementSubcustomer.ManufacturerID AND
SecurityTable.UserID = ManufacturerUserAgreementSubcustomer.UserName
WHERE (SecurityTable.SecurityType = 5) AND (SecurityTable.UserID = #Username) AND (ManufacturerMake.Deleted = 0) AND
(ManufacturerAgreementSubcustomer.Deleted = 0) AND (ManufacturerUserAgreementSubcustomer.Deleted = 0) AND SecurityTable.deleted = 0
)
INSERT INTO #VehicleToUsers
( ID )
(
SELECT DISTINCT Vehicle.ID
FROM Manufacturer WITH (NOLOCK) INNER JOIN
ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement AND
ManufacturerAgreementSubcustomer.Subcustomer = Vehicle.CurrentSubCustomer INNER JOIN
SecurityTable WITH (NOLOCK) ON Vehicle.System = SecurityTable.System AND Manufacturer.ID = SecurityTable.ManufacturerID AND
ManufacturerAgreementSubcustomer.ID = SecurityTable.ManufacturerAgreementSub INNER JOIN
ManufacturerUserAgreementSubcustomer WITH (NOLOCK) ON
ManufacturerAgreementSubcustomer.ID = ManufacturerUserAgreementSubcustomer.ManufacturerAgreementSubcustomerID AND
SecurityTable.UserID = ManufacturerUserAgreementSubcustomer.UserName AND
SecurityTable.ManufacturerID = ManufacturerUserAgreementSubcustomer.ManufacturerID
WHERE (SecurityTable.SecurityType = 6) AND (SecurityTable.UserID = #Username) AND (ManufacturerMake.Deleted = 0) AND
(ManufacturerAgreementSubcustomer.Deleted = 0) AND (ManufacturerUserAgreementSubcustomer.Deleted = 0) AND SecurityTable.deleted = 0
)
END
CREATE TABLE #VehicleToUserCopy(ID BIGINT, vehicleTableID BIGINT, Deleted BIT DEFAULT(1), UpdatedAt DATETIME DEFAULT (GETDATE()), UpdatedBy VARCHAR(50) DEFAULT('UserVisibilityForVehicles-Update'), NextToUpdate BIT DEFAULT(0))
CREATE CLUSTERED INDEX idx_ID ON #VehicleToUserCopy(ID)
CREATE NONCLUSTERED INDEX idx_VehicleTableID ON #VehicleToUserCopy(vehicleTableID)
CREATE NONCLUSTERED INDEX idx_NextToUpdate ON #VehicleToUserCopy(NextToUpdate)
INSERT INTO #VehicleToUserCopy
( ID ,
vehicleTableID ,
Deleted
)
(
SELECT ID, vehicleTableID, Deleted
FROM dbo.VehicleToUser WITH (nolock)
WHERE Username = #Username
)
PRINT 'Starting to do updates'
--Not required as default set to 1
----UPDATE VehicleToUser
----SET DELETED = 1
----,UpdatedAt = GETDATE()
----,UpdatedBy = 'UserVisibilityForVehicles'
----FROM dbo.VehicleToUser WITH (NOLOCK)
----LEFT JOIN #VehicleToUsers AS UsersVehicles ON VehicleToUser.VehicleTableID = UsersVehicles.ID
----WHERE UserName = #Username AND UsersVehicles.ID IS null
PRINT 'Starting to do updates - Set Deleted = 0'
SET LOCK_TIMEOUT 1000 -- set to second
DECLARE #Tries tinyint
UPDATE #VehicleToUserCopy
SET Deleted = 0
FROM #VehicleToUserCopy AS VehicleToUserCopy
inner JOIN #VehicleToUsers AS UsersVehicles ON VehicleToUserCopy.VehicleTableID = UsersVehicles.ID
INSERT INTO VehicleToUser(UserName, VehicleTableID, DELETED, UpdatedAt, UpdatedBy)
(
SELECT DISTINCT #Username, TempVehicle.ID, 0 , GETDATE(), 'UserVisibilityForVehicles-Insert'
FROM #VehicleToUsers AS TempVehicle
LEFT JOIN (
SELECT VehicleTableID
FROM #VehicleToUserCopy WITH (NOLOCK)
) AS [VehicleToUser] ON TempVehicle.ID = [VehicleToUser].VehicleTableID
WHERE [VehicleToUser].VehicleTableID IS null
)
DECLARE #ID bigint
SELECT #ID = ID FROM #VehicleToUserCopy
WHILE ##rowcount > 0
BEGIN
SET ROWCOUNT 1000
SELECT #Tries = 1
WHILE #Tries <= 3
BEGIN
BEGIN TRANSACTION
BEGIN TRY
UPDATE #VehicleToUserCopy SET NextToUpdate = 1
---'THIS UPDATE KEEPS LOCKING'
UPDATE dbo.VehicleToUser
SET Deleted = VehicleToUserCopy.Deleted
, UpdatedAt = GETDATE()
, UpdatedBy = VehicleToUserCopy.UpdatedBy
FROM VehicleToUser
inner JOIN #VehicleToUserCopy AS VehicleToUserCopy ON VehicleToUser.ID = VehicleToUserCopy.ID
WHERE VehicleToUserCopy.NextToUpdate = 1
PRINT 'WORKED'
DELETE FROM #VehicleToUserCopy WHERE NextToUpdate = 1
COMMIT
-- therefore we can leave our loop
BREAK
END TRY
BEGIN CATCH
ROLLBACK --always rollback
PRINT 'Rolled Back '
-- Now check for Blocking errors 1222 or Deadlocks 1205 and if its a deadlock wait for a while to see if that helps
SELECT ERROR_MESSAGE()
IF ERROR_NUMBER() = 1205 OR ERROR_NUMBER() = 1222
BEGIN
-- if its a deadlock wait 2 seconds then try again
IF ERROR_NUMBER() = 1205
BEGIN -- wait 2 seconds to see if that helps the deadlock
WAITFOR DELAY '00:00:02'
END
-- no need to wait for anything for BLOCKING ERRORS as our LOCK_TIMEOUT is going to wait for half a second anyway
-- and if it hasn't finished by then (500ms x 3 attempts = 1.5 seconds) there is no point waiting any longer
END
SELECT #Tries = #Tries + 1 -- increment and try again for 3 goes
-- we carry on until we reach our limit i.e 3 attempts
CONTINUE
END CATCH
END
SELECT #ID = ID FROM #VehicleToUserCopy
End
SET ROWCOUNT 0
DROP TABLE #VehicleToUsers
END
ELSE
BEGIN
DELETE FROM dbo.VehicleToUser WHERE username = #Username
DELETE FROM dbo.VehicleToUser_UserCurrentImageCount WHERE username = #Username
DELETE FROM dbo.VehicleToUser_UsersCurrentVehicles WHERE username = #Username
End
Try changing your update slightly. I have seen some inconsistent results when using an update like this and you update the base table. You should instead update the alias.
UPDATE v
SET Deleted = VCopy.Deleted
, UpdatedAt = GETDATE()
, UpdatedBy = VCopy.UpdatedBy
FROM VehicleToUser v
inner JOIN #VehicleToUserCopy AS VCopy ON v.ID = VCopy.ID
WHERE VCopy.NextToUpdate = 1

SQL Job Status

I am actually working on SP in SQL 2005. Using SP i am creating a job and am scheduling it for a particular time. These jobs take atleast 5 to 10 min to complete as the database is very huge. But I am not aware of how to check the status of the Job. I want to know if it has got completed successfully or was there any error in execution. On exception i also return proper error code. But i am not aware of where i can check for this error code.
This is what I could find, maybe it solves your problem:
SP to get the current job activiity.
exec msdb.dbo.sp_help_jobactivity #job_id = (your job_id here)
You can execute this SP and place the result in a temp table and get the required result from there.
Otherwise have a look at these tables:
msdb.dbo.sysjobactivity
msdb.dbo.sysjobhistory
Run the following to see the association between these tables.
exec sp_helptext sp_help_jobactivity
--Copy in Query analizer and format it properly so you can understand it easyly
--To execute your task(Job) using Query
exec msdb.dbo.sp_start_job #job_name ='Job Name',#server_name = server name
-- After executing query to check weateher it finished or not
Declare #JobId as varchar(36)
Select #JobId = job_id from sysjobs where name = 'Your Job Name'
Declare #JobStatus as int set #JobStatus = -1
While #JobStatus <= -1
Begin
--Provide TimeDelay according your Job
select #JobStatus = isnull(run_status ,-1)
from sysjobactivity JA,sysjobhistory JH
where JA.job_history_id = JH.instance_id and JA.job_id = #JobId
End
select #JobStatus
null = Running
1 = Fininshed successfully
0 = Finished with error
--Once your Job will fininsh you'll get result
I got a better code from here
Use msdb
go
select distinct j.Name as "Job Name", j.description as "Job Description", h.run_date as LastStatusDate,
case h.run_status
when 0 then 'Failed'
when 1 then 'Successful'
when 3 then 'Cancelled'
--when 4 then 'In Progress'
end as JobStatus
from sysJobHistory h, sysJobs j
where j.job_id = h.job_id and h.run_date =
(select max(hi.run_date) from sysJobHistory hi where h.job_id = hi.job_id)
order by 1