web-dev-qa-db-fra.com

Exécution du travail de l'agent SQL Server à partir d'une procédure stockée et renvoi du résultat du travail

Nécessité d'avoir une procédure stockée qui appelle un travail d'agent SQL Server et indique si le travail a été exécuté avec succès ou non.

Jusqu'ici j'ai

CREATE PROCEDURE MonthlyData
AS
EXEC msdb.dbo.sp_start_job N'MonthlyData'

WAITFOR DELAY '000:04:00'

EXEC msdb.dbo.sp_help_jobhistory @job_name = 'MonthlyData'
GO

Qui commence le travail, quel est le meilleur moyen de revenir si le travail a réussi ou non?

Ok a effectué une modification et utilisé WAITFOR DELAY, car le travail est exécuté normalement entre 3 et 4 minutes, mais jamais plus de 4 minutes.

21
DtotheG

Vous pouvez exécuter la requête:

EXEC msdb.dbo.sp_help_jobhistory 
    @job_name = N'MonthlyData'

Cela retournera une colonne run_status. Les statuts sont:

 0 - Failed
 1 - Succeeded
 2 - Retry
 3 - Canceled         

Plus d'infos sur MSDN

EDIT: Vous voudrez peut-être interroger votre travail et vous assurer qu'il est exécuté. Vous pouvez obtenir ces informations à partir de la procédure sp_help_job. Lorsque cette procédure renvoie le statut 4, cela signifie que le travail est inactif . Il est alors sûr de vérifier son statut d'exécution.

Vous pouvez interroger en utilisant le code suivant:

DECLARE @job_status INT
SELECT @job_status = current_execution_status FROM OPENROWSET('SQLNCLI', 'Server=.;Trusted_Connection=yes;','exec msdb.dbo.sp_help_job @job_name = ''NightlyBackups''')

WHILE @job_status <> 4
BEGIN
    WAITFOR DELAY '00:00:03'
    SELECT @job_status = current_execution_status FROM OPENROWSET('SQLNCLI', 'Server=.;Trusted_Connection=yes;','exec msdb.dbo.sp_help_job @job_name = ''NightlyBackups''')
END

EXEC msdb.dbo.sp_help_jobhistory 
    @job_name = N'NightlyBackups' ;
GO

Ce code va vérifier l'état, attendre 3 secondes et réessayer. Une fois que nous avons obtenu le statut 4, nous savons que le travail est terminé et qu'il est prudent de vérifier l'historique.

19
Fedor Hajdu

Pour tous les gars qui sont non autorisés à utiliser la commande OPENROWSET, cela pourrait aider. J'ai trouvé le début de ma solution ici:

http://social.msdn.Microsoft.com/Forums/fr-89659729-fea8-4df0-8057-79e0a437b658/dynamically-checking-job-status-with-tsql

Cela repose sur le fait que certaines colonnes de la table msdb.dbo.sysjobactivity sont d'abord renseignées après la fin du travail, d'une manière ou d'une autre.

-- Start job
DECLARE @job_name NVARCHAR(MAX) = 'JobName'
EXEC msdb.dbo.sp_start_job @job_name = @job_name


-- Wait for job to finish
DECLARE @job_history_id AS INT = NULL

WHILE @time_constraint = @ok
BEGIN
    SELECT TOP 1 @job_history_id = activity.job_history_id
    FROM msdb.dbo.sysjobs jobs
    INNER JOIN msdb.dbo.sysjobactivity activity ON activity.job_id = jobs.job_id
    WHERE jobs.name = @job_name
    ORDER BY activity.start_execution_date DESC

    IF @job_history_id IS NULL
    BEGIN
        WAITFOR DELAY '00:00:10'
        CONTINUE
    END
    ELSE
        BREAK
END


-- Check exit code
SELECT history.run_status
FROM msdb.dbo.sysjobhistory history
WHERE history.instance_id = @job_history_id

Vous voudrez peut-être mettre quelques vérifications sur la durée d'exécution de la boucle WHILE. J'ai choisi de garder cette partie en dehors de l'exemple.

Instructions Microsoft relatives aux codes de sortie, etc. : http://technet.Microsoft.com/en-us/library/ms174997.aspx

20
lapponiandevil

Voici un script qui vérifiera le statut d’un travail et l’exécutera s’il n’est pas déjà en cours.

declare @xp_results table (
job_id                UNIQUEIDENTIFIER NOT NULL,
last_run_date         INT              NOT NULL,
last_run_time         INT              NOT NULL,
next_run_date         INT              NOT NULL,
next_run_time         INT              NOT NULL,
next_run_schedule_id  INT              NOT NULL,
requested_to_run      INT              NOT NULL, -- BOOL
request_source        INT              NOT NULL,
request_source_id     sysname          COLLATE database_default NULL,
running               INT              NOT NULL, -- BOOL
current_step          INT              NOT NULL,
current_retry_attempt INT              NOT NULL,
job_state             INT              NOT NULL)

DECLARE @job_id uniqueidentifier ;
select @job_id = job_id from msdb.dbo.sysjobs where name = 'Job1';
insert into @xp_results
EXEC master.dbo.xp_sqlagent_enum_jobs 1, sa, @job_id

select case when running = 1 then 'Currently Running' else '' end as running, 
case job_state 
    when 0 then 'Not Idle or Suspended'
    when 1 then 'Executing Job'
    when 2 then 'Waiting For Thread'
    when 3 then 'Between Retries'
    when 4 then 'Idle'
    when 5 then 'Suspended'
    when 6 then 'WaitingForStepToFinish'
    when 7 then 'PerformingCompletionActions'
end as job_state
from @xp_results

IF (select running from @xp_results) <> 1
    EXEC msdb.dbo.sp_start_job 'Job1'
0
Igor Krupitsky

Je suis peut-être un peu en retard mais j'ai trouvé que la requête suivante fonctionnait pour moi. Cela donnera l'heure d'exécution et l'heure de fin d'exécution. Vous pouvez également le modifier pour obtenir le statut.

SELECT 
    job.name, 
    job.job_id, 
    job.originating_server, 
    activity.run_requested_date, 
    activity.stop_execution_date, 
    DATEDIFF( SECOND, activity.run_requested_date, activity.stop_execution_date ) as Elapsed 
FROM msdb.dbo.sysjobs_view job 
JOIN msdb.dbo.sysjobactivity activity ON job.job_id = activity.job_id 
JOIN msdb.dbo.syssessions sess ON sess.session_id = activity.session_id 
JOIN 
( 
    SELECT 
    MAX( agent_start_date ) AS max_agent_start_date 
    FROM 
    msdb.dbo.syssessions 
) sess_max 
ON sess.agent_start_date = sess_max.max_agent_start_date 
WHERE run_requested_date IS NOT NULL 
--AND stop_execution_date IS NULL 
AND job.name = @JobName
0
Gericke