Projets SQL Server Agent échouent lorsque les tâches contiennent les étapes de travail qui utilisent des jetons après avoir installé SQL Server 2005 Service Pack 1

Traductions disponibles Traductions disponibles
Numéro d'article: 915845 - Voir les produits auxquels s'applique cet article
Bogue #: 426808 (SQLBUDT)
Agrandir tout | Réduire tout

Symptômes

Après avoir installé Microsoft SQL Server 2005 Service Pack 1 (SP1), vous rencontrer le problème suivant :
  • Projets SQL Server Agent échouent lorsque les tâches contiennent des étapes de travail qui utilisent les jetons.
  • Vous recevez le message d'erreur suivantes :
    L'étape de travail contient plusieurs jetons. Pour SQL Server 2005 Service Pack 1 ou versions ultérieures, toutes les étapes de travail avec jetons doivent être mis à jour avec une macro avant du travail permettre l'exécution.
note Ce problème se produit avec les versions 2046 ou version ultérieures de version de SQL Server 2005.

Cause

Dans SQL Server 2005 SP1, la syntaxe SQL Server Agent travail étape jeton a été modifié. À présent, vous devez inclure une macro d'échappement avec tous les jetons qui sont utilisés dans les étapes de travail. Si vous n'incluez pas une macro d'échappement, ces étapes de travail va échouer. Le tableau suivant répertorie les macros d'échappement.
Réduire ce tableauAgrandir ce tableau
Fermez la macroDescription
$ (ESCAPE_SQUOTE (TokenName))Cette macro escapes apostrophes (') dans la chaîne de jeton de remplacement. La macro remplace une apostrophe par deux apostrophes.
$ (ESCAPE_DQUOTE (TokenName))Cette macro escapes guillemets ('') dans la chaîne de jeton de remplacement. La macro remplace un guillemet par deux guillemets.
$ (ESCAPE_RBRACKET (TokenName))Cette macro escapes droit entre crochets (]) dans la chaîne de jeton de remplacement. La macro remplace un crochet droit avec deux crochets droite.
$ (ESCAPE_NONE (TokenName))La macro remplace un jeton sans évitement tout caractère présent dans la chaîne. Cette macro est fournie pour prendre en charge en amont compatible dans des environnements où chaînes de remplacement jeton sont attendues uniquement des utilisateurs approuvés.
Par exemple, une étape de travail peut contenir l'instruction Transact-SQL suivante qui utilise le jeton A-DBN :
CREATE DATABASE [$(A-DBN)]
dans cet exemple, vous devez mettre à jour la syntaxe de jeton vers la syntaxe suivante : précédent comportement de SQL Server 2005, macros d'échappement n'étaient pas requis diffère de
CREATE DATABASE [$(ESCAPE_RBRACKET(A-DBN))]
cette modification.

Résolution

Pour résoudre ce problème, mettez à jour soit tout ou uniquement les tâches spécifiques qui utilisent des jetons de la nouvelle syntaxe jeton. Pour cela, utilisez la sp_AddEscapeNoneToJobStepTokens procédure stockée. Vous pouvez créer cette procédure stockée en utilisant le script Transact-SQL suivant.

note Assurez-vous que la version de SQL Server 2005 SP1 que vous installez est version 2046 ou une version ultérieure. En outre, vous devez être un membre du rôle de serveur fixe sysadmin pour exécuter le script.
      -- This script is used to automatically edit SQL Agent job steps so that
-- unescaped tokens are prefaced with the ESCAPE_NONE syntax that was added in
-- SQL Server 2005 SP1.

if (@@microsoftversion < 0x90007FE)
BEGIN
    RAISERROR('This script should only be run on at least SQL Server 2005 SP1.', 20, 127) WITH LOG
    return
END

use msdb
go

if exists (select * from sys.objects where name = N'fn_PrefaceTokensWithEscapeNone' and type = 'FN')
    drop function fn_PrefaceTokensWithEscapeNone
go

-- This function manipulates @commands so that all bare tokens
-- are prefaced with ESCAPE_NONE.
create function fn_PrefaceTokensWithEscapeNone(@commands nvarchar(max)) RETURNS nvarchar(max)
AS
BEGIN
    if (@commands IS NULL)
    BEGIN
        return @commands
    END

    -- In order to let this script run under SQLCMD mode, we define
    -- the special "$(" variable start string by concatenation so that
    -- sqlcmd mode does not think that we are defining one of its variables.
    declare @strVariableStart nchar(2)
    select @strVariableStart = N'$' + N'('

    declare @idxTokenStart int
    select @idxTokenStart = CHARINDEX(@strVariableStart, @commands)
    while (@idxTokenStart != 0 and @idxTokenStart is not null)
    BEGIN
        declare @idxCloseParen int
        select @idxCloseParen = CHARINDEX(N')', SUBSTRING(@commands, @idxTokenStart, LEN(@commands)))
        -- Error checking. If there is no close parenthesis, return.
        if (0 = @idxCloseParen)
        BEGIN
            return @commands
        END

        -- Deduce the token variable.
        declare @tokenLen int
        select @tokenLen = @idxCloseParen - LEN(@strVariableStart) - 1
        declare @token nvarchar(max)
        select @token = SUBSTRING(@commands, @idxTokenStart + LEN(@strVariableStart), @tokenLen)

        -- Verify if @token contains a mis-matched number of open and
        -- close parens. This behavior could happen if invalid syntax is
        -- in a comment block. If so, skip to the next token.
        declare @idx int
        declare @cOpenParens int
        declare @cCloseParens int

        select @cOpenParens = 0
        select @idx = CHARINDEX(N'(', @token);
        while (@idx != 0)
        BEGIN
            select @cOpenParens = @cOpenParens + 1
            select @idx = CHARINDEX(N'(', @token, @idx + 1);
        END

        select @cCloseParens = 0
        select @idx = CHARINDEX(N')', @token);
        while (@idx != 0)
        BEGIN
            select @cCloseParens = @cCloseParens + 1
            select @idx = CHARINDEX(N')', @token, @idx + 1);
        END

        -- Special case for the WMI token.
        if (N'WMI(' = SUBSTRING(@token, 1, LEN(N'WMI(')))
        BEGIN
                select @cOpenParens = @cOpenParens - 1
        END

        if ((@cOpenParens = @cCloseParens) and
            (N'ESCAPE_NONE(' != SUBSTRING(@token, 1, LEN(N'ESCAPE_NONE('))) and
            (N'ESCAPE_SQUOTE(' != SUBSTRING(@token, 1, LEN(N'ESCAPE_SQUOTE('))) and
            (N'ESCAPE_DQUOTE(' != SUBSTRING(@token, 1, LEN(N'ESCAPE_DQUOTE('))) and
            (N'ESCAPE_RBRACKET(' != SUBSTRING(@token, 1, LEN(N'ESCAPE_RBRACKET('))))
        BEGIN
            select @commands = STUFF(@commands, @idxTokenStart + LEN(@strVariableStart), @tokenLen, N'ESCAPE_NONE(' + @token + N')')
        END
        select @idxTokenStart = CHARINDEX(@strVariableStart, @commands, @idxTokenStart + 1)
    END

    return @commands

END
go

if exists (select * from sys.objects where name = N'sp_AddEscapeNoneToJobStepTokens' and type = 'P')
    drop procedure sp_AddEscapeNoneToJobStepTokens
go

-- This procedure allows you to update jobs so that bare tokens
-- are prefaced with ESCAPE_NONE. By default, all jobs are updated.
-- You can optionally specify @job_name, @job_id, or @owner_name
-- to limit the jobs that will be affected.
CREATE PROCEDURE sp_AddEscapeNoneToJobStepTokens
(
    @job_name nvarchar(128) = null,
    @job_id uniqueidentifier = null,
    @owner_name nvarchar(256) = null
)
AS


  -- Find the jobs to update. These jobs must match all of the input
  -- criteria, unless all of the inputs are null. In this case, 
  -- examine all jobs.  The jobs must also be jobs created locally,
  -- such as sysjobs.originating_server_id = 0. These jobs should not be a job that we run
  -- because another server told us to.  Furthermore, if the job
  -- is local but it is meant to be run on a target server, we send an
  -- update for the job.
  declare @jobsToUpdate TABLE (job_id uniqueidentifier not null)
  
  insert into @jobsToUpdate
      select job_id
      from sysjobs
      where originating_server_id = 0 -- local jobs
      and ((COALESCE(@job_name, sysjobs.name) = sysjobs.name) and
           (COALESCE(@job_id, sysjobs.job_id) = sysjobs.job_id) and
           (COALESCE(@owner_name, suser_sname(sysjobs.owner_sid)) = suser_sname(sysjobs.owner_sid)))
  
  -- Now find the job steps to update, creating the new command by using
  -- fn_PrefaceTokensWithEscapeNone.
  declare @jobStepsToUpdate TABLE (job_id uniqueidentifier not null, 
                                   step_id int not null, 
                                   command_old nvarchar(max) null, 
                                   command_new nvarchar(max) null,
                                   output_file_old nvarchar(max) null, 
                                   output_file_new nvarchar(max) null)
  
  insert into @jobStepsToUpdate
  (job_id, step_id, command_old, command_new, output_file_old, output_file_new)
      select job_id, step_id, command, dbo.fn_PrefaceTokensWithEscapeNone(command), output_file_name, dbo.fn_PrefaceTokensWithEscapeNone(output_file_name)
      from sysjobsteps
      where sysjobsteps.job_id = 
      (select job_id 
       from @jobsToUpdate 
       where job_id = sysjobsteps.job_id)
  
  -- Now we update the actual job step commands. We do this first before
  -- we push out the updated jobs to the target servers so the
  -- target servers actually get the updated version.
  declare @updated_job_id uniqueidentifier
  declare @updated_job_step_id int
  declare @updated_job_step_command nvarchar(max)
  declare @updated_job_step_output_file nvarchar(max)
  
  declare job_steps_cursor CURSOR FOR
      select job_id, step_id, command_new, output_file_new
      from @jobStepsToUpdate
      order by job_id, step_id
  
  OPEN job_steps_cursor
  FETCH NEXT from job_steps_cursor into @updated_job_id, @updated_job_step_id, @updated_job_step_command, @updated_job_step_output_file
  WHILE (@@FETCH_STATUS <> -1)
  BEGIN
      IF (@@FETCH_STATUS <> -2)
      BEGIN
          EXEC sp_update_jobstep @job_id = @updated_job_id, @step_id = @updated_job_step_id, @command = @updated_job_step_command, @output_file_name = @updated_job_step_output_file
      END
      FETCH NEXT from job_steps_cursor into @updated_job_id, @updated_job_step_id, @updated_job_step_command, @updated_job_step_output_file
  END
  
  CLOSE job_steps_cursor
  DEALLOCATE job_steps_cursor
  
  
  -- For multiserver jobs, call the sp_post_msx_operation stored procedure to update
  -- all the target servers. Note that the sp_post_msx_operation stored procedure is safe
  -- to call because it verifies whether the job is really a multiserver job.
  declare jobs_cursor CURSOR FOR
      select job_id
      from @jobsToUpdate
  
  OPEN jobs_cursor
  FETCH NEXT from jobs_cursor into @updated_job_id
  WHILE (@@FETCH_STATUS <> -1)
  BEGIN
      IF (@@FETCH_STATUS <> -2)
      BEGIN
          EXEC sp_post_msx_operation @operation = 'UPDATE', @job_id = @updated_job_id
      END
      FETCH NEXT from jobs_cursor into @updated_job_id
  END
  
  CLOSE jobs_cursor
  DEALLOCATE jobs_cursor

  -- List the jobs that we ran on, including the previous command
  -- text. We list all of the job steps, even the ones that we did not
  -- update. Otherwise, a jumble of job steps from
  -- different jobs run together and the output is not
  -- useful.
  select N'Warning - Jobs Updated' = N'The following job steps and job output file names were analyzed and potentially updated to add the ESCAPE_NONE macro before any job tokens that were not already escaped. Please review the modified job steps and replace ESCAPE_NONE with the correct escape macro.'
  
  select suser_sname(jobs.owner_sid) as N'Job owner', 
         jobs.name as N'Job name', 
         jobs.job_id, 
         jobStepsUpdated.step_id, 
         N'Modified' = CASE WHEN jobStepsUpdated.command_new != jobStepsUpdated.command_old or jobStepsUpdated.output_file_new != jobStepsUpdated.output_file_old THEN 1 ELSE 0 END,
         N'Command' = jobStepsUpdated.command_new, 
         N'Previous Command' = jobStepsUpdated.command_old, 
         N'Output file' = jobStepsUpdated.output_file_new, 
         N'Previous Output file' = jobStepsUpdated.output_file_old
      from sysjobs as jobs, @jobsToUpdate as jobsUpdated, @jobStepsToUpdate as jobStepsUpdated
      where jobsUpdated.job_id = jobs.job_id and jobsUpdated.job_id = jobStepsUpdated.job_id
      order by 'Job name', jobStepsUpdated.step_id
go

Après avoir exécuté le script, la procédure sp_AddEscapeNoneToJobStepTokens stockée est créée. Par défaut, vous mettre à êtes jour toutes les tâches si vous exécutez cette procédure stockée sans paramètres. Si vous souhaitez mettre à jour des tâches spécifiques, vous devez spécifier les valeurs non null pour au moins une des trois paramètres suivants :
  • @job_name
  • @job_id
  • @owner_name
Par exemple, vous pouvez utiliser la syntaxe suivante :
  • mettre à jour toutes les tâches :
    EXEC sp_AddEscapeNoneToJobStepTokens
  • mettre à jour un travail en spécifiant le nom de travail :
    EXEC sp_AddEscapeNoneToJobStepTokens 'MyJob'
  • mettre à jour de tâches qui appartiennent à la même propriétaire :
    EXEC sp_AddEscapeNoneToJobStepTokens null,null,'JobOwner'
Ce script ajoute la macro ESCAPE_NONE toutes les étapes travail qui contiennent des jetons. Après avoir exécuté ce script, nous vous recommandons de consulter vos étapes de travail qu'utiliser jetons dès que possible. Ensuite, remplacez la macro ESCAPE_NONE parmi les autres macros d'échappement qui convient le contexte d'étape de travail.

note Si vous travaillez dans un serveur maître (MSX) et l'environnement de serveur (TSX) cible, vous devez exécuter ce script sur le MSX et le TSX pour vous assurer que travaux principal sur la TSX est correctement mis à jour.

Pour plus d'informations sur comment mettre à jour de tâches à utiliser la nouvelle syntaxe et comment utiliser des macros d'échappement pour activer le remplacement de jeton dans SQL Server Agent travail étapes, consultez la rubrique « à l'aide étapes jetons dans projet » dans Server documentation en ligne de SQL 2005 (avril 2006) ou versions ultérieures d'en ligne de SQL Server 2005.

Statut

Microsoft a confirmé que c'est un problème dans les produits Microsoft répertoriés dans la section « S'applique à ».

Références

Pour plus d'informations à utiliser des jetons dans les étapes de travail, reportez-vous au site de Web MSDN (Microsoft Developer Network) suivant :
http://msdn2.microsoft.com/en-us/library/ms175575.aspx

Propriétés

Numéro d'article: 915845 - Dernière mise à jour: mercredi 24 mai 2006 - Version: 2.1
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft SQL Server 2005 Standard Edition
  • Microsoft SQL Server 2005 Workgroup Edition
  • Microsoft SQL Server 2005 Enterprise Edition
Mots-clés : 
kbmt kbsql2005presp1fix kbprb kbexpertiseadvanced kbtshoot KB915845 KbMtfr
Traduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 915845
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com