SQL Server Agent úlohy selhat při úlohy obsahovat úlohy kroků, které používají tokeny po instalaci SQL Server 2005 Service Pack 1

Překlady článku Překlady článku
ID článku: 915845 - Produkty, které se vztahují k tomuto článku.
Chyba č: 426808 (SQLBUDT)
Rozbalit všechny záložky | Minimalizovat všechny záložky

Příznaky

Po instalaci aktualizace Service Pack 1 (SP1) pro Microsoft SQL Server 2005 vyskytnout následující chování:
  • SQL Server Agent úlohy selhat při úlohy obsahovat úlohy kroků, které používají tokeny.
  • Zobrazí se následující chybová zpráva:
    Krok úloha obsahuje jeden nebo více tokeny. Pro SQL Server 2005 Service Pack 1 nebo novější verze musí být před spuštěním úlohy s makro aktualizovány všechny kroky úlohy s tokeny.
Poznámka: K tomuto problému dochází s sestavení 2046 nebo novější verze aplikace SQL Server 2005.

Příčina

V SQL Server 2005 SP1 syntaxe SQL Server Agent úlohy kroku token změnil. Nyní musí obsahovat makro escape s všechny tokeny, které jsou použity v krocích úlohy. Pokud makro escape neobsahují, tyto kroky úloha nezdaří. Následující tabulka obsahuje makra escape.
Zmenšit tuto tabulkuRozšířit tuto tabulku
Makro escapePOPIS
$ (ESCAPE_SQUOTE (TokenName))Toto makro escapes apostrofy (') token náhradní řetězec. Makro nahradí jeden apostrof dva apostrofy.
$ (ESCAPE_DQUOTE (TokenName))Toto makro escapes uvozovek (") v tokenu náhradní řetězec. Makro nahradí jeden uvozovky dvou uvozovek.
$ (ESCAPE_RBRACKET (TokenName))Toto makro escapes pravé hranaté závorky (]) v tokenu náhradní řetězec. Makro nahradí jeden pravá hranatá závorka dvě pravé závorky.
$ (ESCAPE_NONE (TokenName))Makro nahrazuje token bez escaping všechny znaky v řetězci. Toto makro je poskytováno podporovat zpětné kompatibility v prostředích, kde jsou token nahrazení řetězce pouze očekávané od důvěryhodným uživatelům.
Úloha krok může obsahovat například následující příkaz Transact-SQL, který používá token DBN A:
CREATE DATABASE [$(A-DBN)]
V tomto příkladu, musíte aktualizovat token syntaxe následující syntaxe:
CREATE DATABASE [$(ESCAPE_RBRACKET(A-DBN))]
tato změna se liší od chování předchozí SQL Server 2005, kde nebyly požadovaná makra escape.

Řešení

Tento problém vyřešíte aktualizací buď všechny nebo pouze určité úlohy, které používají tokeny novou syntaxi token. To provedete pomocí postupu sp_AddEscapeNoneToJobStepTokens uloženy. Uloženou proceduru můžete vytvořit pomocí následujících skriptů Transact-SQL.

Poznámka: Zkontrolujte, zda je sestavení SQL Server 2005 SP1, které nainstalovat sestavení 2046 nebo novější sestavení. Navíc musí být členem role sysadmin dlouhodobého serveru spuštění skriptu
      -- 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

Po spuštění skriptu je vytvořen sp_AddEscapeNoneToJobStepTokens uložené procedury. Ve výchozím aktualizujete všechny úlohy Pokud spustíte tuto uloženou proceduru bez parametrů. Pokud chcete aktualizovat pouze určité úlohy, je nutné zadat hodnoty null pro jeden z následujících tří parametrů:
  • @ job_name
  • @ job_id
  • @ owner_name
Například může použít následující syntaxi:
  • Aktualizovat všechny úlohy:
    EXEC sp_AddEscapeNoneToJobStepTokens
  • Aktualizovat úlohu zadáním název úlohy:
    EXEC sp_AddEscapeNoneToJobStepTokens 'MyJob'
  • Aktualizovat vlastněných stejného vlastníka úlohy:
    EXEC sp_AddEscapeNoneToJobStepTokens null,null,'JobOwner'
Tento skript přidá makro ESCAPE_NONE všechny kroky úlohy, které obsahují tokeny. Po spuštění tohoto skriptu doporučujeme zkontrolovat své úlohy kroků, které používají tokeny co nejdříve. Potom nahraďte makro ESCAPE_NONE s ostatní makra escape, která je vhodná pro kontext kroku úlohy.

Poznámka: Pokud pracujete v prostředí cílového serveru (TSX) a hlavní server (MSX), je nutné spustit tohoto skriptu na MSX i TSX Ujistěte se, že hlavní úlohy na TSX správně aktualizován.

Další informace o aktualizaci úlohy použít novou syntaxi a použití makra escape povolení token nahrazení kroky úlohy SQL Server Agent v tématu "Použití tokeny v projektu kroky" SQL Server 2005 Books Online (duben 2006) nebo novější verze aplikace SQL Server 2005 Books Online.

Prohlášení

Společnost Microsoft potvrzuje, že se jedná o problém v produktech této společnosti, které jsou uvedeny v části Informace v tomto článku jsou určeny pro produkt.

Odkazy

Další informace o použití tokeny kroky úlohy na webu Microsoft Developer Network (MSDN):
http://msdn2.microsoft.com/en-us/library/ms175575.aspx

Vlastnosti

ID článku: 915845 - Poslední aktualizace: 24. května 2006 - Revize: 2.1
Informace v tomto článku jsou určeny pro produkt:
  • Microsoft SQL Server 2005 Standard Edition
  • Microsoft SQL Server 2005 Workgroup Edition
  • Microsoft SQL Server 2005 Enterprise Edition
Klíčová slova: 
kbmt kbsql2005presp1fix kbprb kbexpertiseadvanced kbtshoot KB915845 KbMtcs
Strojově přeložený článek
Důležité: Tento článek byl přeložen pomocí software společnosti Microsoft na strojový překlad, ne profesionálním překladatelem. Společnost Microsoft nabízí jak články přeložené překladatelem, tak články přeložené pomocí software na strojový překlad, takže všechny články ve Znalostní databázi (Knowledge Base) jsou dostupné v češtině. Překlad pomocí software na strojový překlad ale není bohužel vždy dokonalý. Obsahuje chyby ve skloňování slov, skladbě vět, nebo gramatice, podobně jako když cizinci dělají chyby při mluvení v češtině. Společnost Microsoft není právně zodpovědná za nepřesnosti, chyby nebo škody vzniklé chybami v překladu, nebo při použití nepřesně přeložených instrukcí v článku zákazníkem. Společnost Microsoft aktualizuje software na strojový překlad, aby byl počet chyb omezen na minimum.
Projděte si také anglickou verzi článku:915845

Dejte nám zpětnou vazbu

 

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