T-SQL: come possiamo eseguire in modo sequenziale tutti gli step in un Job?
Ecco un modo per gestire in maniera sequenziale la lavorazione di tutti gli step all’interno di un solo JOB.
1) Primo passo da fare è creare un Job con tutti gli step che dovranno essere lavorati e chiamarlo BONUS_TRACK.
2) Creiamo una Stored Procedure chiamata Run_wait_job_2.
CREATE PROCEDURE [dbo].[Run_Wait_Job_2] @Nome_Job AS SYSNAME, @Stato_Job AS INT OUTPUT AS --DECLARE @Nome_Job AS VARCHAR(50) --DECLARE @Stato_Job AS INT --SET @Nome_Job = 'PIPPO' --SET @Stato_Job = 0 ---((( Run_Wait_Job ---((( Run_Wait_Job ---((( Run_Wait_Job ---/// VARIABILI DI LAVORO DECLARE @Riga AS VARCHAR(255) DECLARE @RSql AS VARCHAR(1000) DECLARE @ERR AS INT DECLARE @RC AS INT DECLARE @Ind AS INT DECLARE @Ind_Mon AS INT DECLARE @NumRec AS INT DECLARE @Ret_Code AS INT DECLARE @Run_Job_Ini_D AS DATETIME DECLARE @Run_Job_Ini AS VARCHAR(20) DECLARE @Secs_Past AS INT DECLARE @Secs_Inter AS INT DECLARE @JOB_Secs_Min AS INT DECLARE @JOB_Secs_AVG AS INT DECLARE @JOB_Secs_Max AS INT DECLARE @Step_Ret_Code AS INT DECLARE @Time_Now AS DATETIME DECLARE @Secs_Inter_T AS VARCHAR(9) DECLARE @Secs_Inter_HH AS INT DECLARE @Secs_Inter_MM AS INT DECLARE @Secs_Inter_SS AS INT DECLARE @Fine_Wait AS INT DECLARE @Job_Status AS VARCHAR(40) --- cancello tabella temporanea se esiste IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'zz_Run_Wait_Job') DROP TABLE zz_Run_Wait_Job --- cancello tabella temporanea se esiste IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'zz_Run_Wait_Job_2') DROP TABLE zz_Run_Wait_Job_2 --- cancello tabella temporanea se esiste IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'zz_Run_Wait_Job_3') DROP TABLE zz_Run_Wait_Job_3 ---((( LANCIO JOB ESPORTAZIONE --- memorizzo ora inizio lancio SET @Run_Job_Ini_D = GETDATE() SET @Run_Job_Ini = CAST (DATEPART (YEAR, @Run_Job_Ini_D ) AS VARCHAR(9)) SET @Run_Job_Ini = @Run_Job_Ini + RIGHT('00' + CAST (DATEPART(MONTH, @Run_Job_Ini_D ) AS VARCHAR(9)), 2) SET @Run_Job_Ini = @Run_Job_Ini + RIGHT('00' + CAST (DATEPART(DAY, @Run_Job_Ini_D ) AS VARCHAR(9)), 2) SET @Run_Job_Ini = @Run_Job_Ini + RIGHT('00' + CAST (DATEPART(HOUR, @Run_Job_Ini_D ) AS VARCHAR(9)), 2) SET @Run_Job_Ini = @Run_Job_Ini + RIGHT('00' + CAST (DATEPART(MINUTE, @Run_Job_Ini_D ) AS VARCHAR(9)), 2) SET @Run_Job_Ini = @Run_Job_Ini + RIGHT('00' + CAST (DATEPART(SECOND, @Run_Job_Ini_D ) AS VARCHAR(9)), 2) ---/// PRINT '@Run_Job_Ini: ' + @Run_Job_Ini ---((( RUN! EXEC @Ret_Code = msdb.dbo.sp_start_job @job_name = @Nome_Job ---((( ROUTINE di controllo fine job ---((( ROUTINE di controllo fine job ---((( ROUTINE di controllo fine job SET @IND = 0 SET @Ind_Mon = 1 SET @Secs_Inter = 60 ---((( CREO E POPOLO temporanea steps History SELECT msdb.dbo.sysjobs.NAME AS Nome_Job, msdb.dbo.sysjobhistory.step_name AS Nome_Step, RIGHT('000000' + CAST(msdb.dbo.sysjobhistory.run_duration AS VARCHAR(22)), 6) AS Time_HMS INTO zz_Run_Wait_Job FROM msdb.dbo.sysjobs INNER JOIN msdb.dbo.sysjobhistory ON msdb.dbo.sysjobs.job_id = msdb.dbo.sysjobhistory.job_id WHERE msdb.dbo.sysjobhistory.step_name = '(Job outcome)' AND msdb.dbo.sysjobs.NAME = @Nome_Job ---((( ... affinamento SELECT Nome_Job, JOB_Secs = (CAST(LEFT(Time_HMS, 2) AS INT) * 3600 + CAST(SUBSTRING(Time_HMS, 3, 2) AS INT) * 60 + CAST(RIGHT(Time_HMS, 2) AS INT) ) INTO zz_Run_Wait_Job_3 FROM zz_Run_Wait_Job ---((( stats tempi run jobs SET @JOB_Secs_Min = (SELECT MIN(JOB_Secs) FROM zz_Run_Wait_Job_3) SET @JOB_Secs_AVG = (SELECT AVG(JOB_Secs) FROM zz_Run_Wait_Job_3) SET @JOB_Secs_Max = (SELECT MAX(JOB_Secs) FROM zz_Run_Wait_Job_3) --- monitoring PRINT CONVERT(VARCHAR(30), GETDATE(), 113) SET @Riga = 'Run_Wait_Job - ' + @Nome_Job + ' - Stats orginal' SET @Riga = @Riga + ' Min: ' + ISNULL(CAST(@JOB_Secs_Min AS VARCHAR(9)), '--') SET @Riga = @Riga + ' AVG: ' + ISNULL(CAST(@JOB_Secs_AVG AS VARCHAR(9)), '--') SET @Riga = @Riga + ' Max: ' + ISNULL(CAST(@JOB_Secs_Max AS VARCHAR(9)), '--') PRINT @Riga EXEC [FLUSSI].[dbo].[LogInsert2] 4, @Riga ---((( ritocco statistiche per margini sicurezza SET @JOB_Secs_Min = @JOB_Secs_Min - @JOB_Secs_Min / 10 SET @JOB_Secs_Max = @JOB_Secs_Max + @JOB_Secs_Max / 10 --- e correzione per valori anomali SET @JOB_Secs_Min = ISNULL(@JOB_Secs_Min, 30) SET @JOB_Secs_Max = ISNULL(@JOB_Secs_Max, 3600) SET @JOB_Secs_AVG = ISNULL(@JOB_Secs_AVG, 60) IF @JOB_Secs_Min < 30 SET @JOB_Secs_Min = 30 IF @JOB_Secs_Max <= @JOB_Secs_Min SET @JOB_Secs_Max = @JOB_Secs_Min * 10 IF @JOB_Secs_Max < 1000 SET @JOB_Secs_Max = 1000 IF @JOB_Secs_AVG < @JOB_Secs_Min SET @JOB_Secs_AVG = (@JOB_Secs_Min + @JOB_Secs_Max) / 2 --- monitoring PRINT CONVERT(VARCHAR(30), GETDATE(), 113) SET @Riga = 'Run_Wait_Job - ' + @Nome_Job + ' - Stats' SET @Riga = @Riga + ' Min: ' + CAST(@JOB_Secs_Min AS VARCHAR(9)) SET @Riga = @Riga + ' AVG: ' + CAST(@JOB_Secs_AVG AS VARCHAR(9)) SET @Riga = @Riga + ' Max: ' + CAST(@JOB_Secs_Max AS VARCHAR(9)) PRINT @Riga EXEC [FLUSSI].[dbo].[LogInsert2] 4, @Riga --- A questo punto abbiamo raccolto dalle statistiche --- di sistema i tempi di esecuzione del job in secondi. --- Li utilizzeremo per ridurre le query di stato del job. ---((( Settings per LOOP SET @Secs_Past = 0 SET @Step_Ret_Code = -1 SET @Secs_Inter_T = '000:00:01' SET @Fine_Wait = 0 ---((( INIZIO LOOP ---((( INIZIO LOOP ---((( INIZIO LOOP WHILE @Fine_Wait = 0 BEGIN --- ATTESA! IF @Fine_Wait = 0 WAITFOR DELAY @Secs_Inter_T --- Contaloop SET @IND = @IND + 1 --- Interrogo statistiche di sistema SET @Step_Ret_Code = (SELECT TOP 1 msdb.dbo.sysjobhistory.run_status FROM msdb.dbo.sysjobhistory INNER JOIN msdb.dbo.sysjobs ON msdb.dbo.sysjobhistory.job_id = msdb.dbo.sysjobs.job_id WHERE msdb.dbo.sysjobhistory.step_name = '(Job outcome)' AND msdb.dbo.sysjobs.name = @Nome_Job AND CAST(msdb.dbo.sysjobhistory.run_date AS VARCHAR(22)) + RIGHT('000000' + CAST(msdb.dbo.sysjobhistory.run_time AS VARCHAR(9)), 6) >= @Run_Job_Ini ORDER BY msdb.dbo.sysjobhistory.run_date DESC, msdb.dbo.sysjobhistory.run_time DESC) --- controllo null SET @Step_Ret_Code = ISNULL(@Step_Ret_Code, -1) SET @Time_Now = GETDATE() SET @Secs_Past = DATEDIFF( SECOND, @Run_Job_Ini_D, @Time_Now) IF @Secs_Past < @JOB_Secs_Min SET @Secs_Inter = @JOB_Secs_Min - @Secs_Past IF @Secs_Past >= @JOB_Secs_Min AND @Secs_Past < @JOB_Secs_AVG SET @Secs_Inter = (@JOB_Secs_AVG - @JOB_Secs_Min) / 10 IF @Secs_Past >= @JOB_Secs_AVG SET @Secs_Inter = (@JOB_Secs_Max - @JOB_Secs_AVG) / 10 IF @Secs_Inter < 30 SET @Secs_Inter = 30 IF @Secs_Inter > 60 SET @Secs_Inter = 60 ---((( CONVERSIONE FORMATO tempo --- da secondi (INT) --- a stringa 'HHH:MM:SS' --- le ore sono secondi / 3600 SET @Secs_Inter_HH = FLOOR (@Secs_Inter / 3600) --- i minuti sono i secondi rimanenti dalle ore / 60 SET @Secs_Inter_MM = FLOOR ((@Secs_Inter - (@Secs_Inter_HH * 3600))/60) --- I secondi sono il resto della divisione per 60 SET @Secs_Inter_SS = @Secs_Inter - (FLOOR (@Secs_Inter / 60) * 60) --- CONVERSIONE in STRINGA SET @Secs_Inter_T = RIGHT('000' + CAST(@Secs_Inter_HH AS VARCHAR(9)), 3) SET @Secs_Inter_T = @Secs_Inter_T + ':' + RIGHT('00' + CAST(@Secs_Inter_MM AS VARCHAR(9)), 2) SET @Secs_Inter_T = @Secs_Inter_T + ':' + RIGHT('00' + CAST(@Secs_Inter_SS AS VARCHAR(9)), 2) IF @Step_Ret_Code < 0 SET @Job_Status = 'In esecuzione' IF @Step_Ret_Code = 0 SET @Job_Status = 'Failed' IF @Step_Ret_Code = 1 SET @Job_Status = 'Succeeded' IF @Step_Ret_Code = 2 SET @Job_Status = 'Retray' IF @Step_Ret_Code = 3 SET @Job_Status = 'Canceled' IF @Step_Ret_Code = 4 SET @Job_Status = 'In progress' --- LOG & MONITOR IF @Ind >= @Ind_Mon BEGIN PRINT CONVERT(VARCHAR(30), GETDATE(), 120) SET @Riga = 'Run_Wait_Job - ' + @Nome_Job + ' - (' + CAST(@IND AS VARCHAR(9)) + ')' SET @Riga = @Riga + ' - secondi tot: ' + CAST(@Secs_Past AS VARCHAR(9)) SET @Riga = @Riga + ' - intervallo secs: ' + @Secs_Inter_T SET @Riga = @Riga + ' - JOB STATUS: ' + @Job_Status PRINT @Riga EXEC [FLUSSI].[dbo].[LogInsert2] 4, @Riga SET @Ind_Mon = @Ind_Mon * 2 END --- controllo per uscita dal loop IF @Step_Ret_Code >= 0 SET @Fine_Wait = 1 IF @Secs_Past > @JOB_Secs_Max SET @Fine_Wait = 1 END ---((( FINE LOOP --- monitoring timeout IF @Step_Ret_Code < 0 SET @Job_Status = @Job_Status + ' (Timeout scaduto)' ---PRINT @Riga ---EXEC [FLUSSI].[dbo].[LogInsert2] 4, @Riga --- valorizza parametro output SET @Stato_Job = @Step_Ret_Code --- cancello tabella temporanea se esiste IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'zz_Run_Wait_Job') DROP TABLE zz_Run_Wait_Job --- cancello tabella temporanea se esiste IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'zz_Run_Wait_Job_2') DROP TABLE zz_Run_Wait_Job_2 --- cancello tabella temporanea se esiste IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'zz_Run_Wait_Job_3') DROP TABLE zz_Run_Wait_Job_3 RETURN
3) In un nuovo JOB chiamato Lavora_Step inseriamo il seguente codice:
DECLARE @Stato_Job AS INT --- EXPORT_AM_CORP EXEC FLUSSI.dbo.Run_Wait_Job_2 'BONUS_TRACK', @Stato_Job OUTPUT --- Rilancia se job failed IF @Stato_Job = 0 EXEC FLUSSI.dbo.Run_Wait_Job_2 'BONUS_TRACK', @Stato_Job OUTPUT
Come potete vedere: Run_wait_Job_2 è il nome della Stored procedures, Bonus_Track è il nome del nostro Job iniziale (quello con tanti Step).
Ho inoltre inserito lo status dell’operazione per determinarne l’esito positivo o negativo.
Buon divertimento.
Se volete seguire i post di www.informarea.it potete iscrivervi al suo feed RSS.
Segui Informarea |