SQL Server-Agent-Aufträge fehlschlagen, wenn die Aufträge Auftrag Schritte enthalten, die nach dem SQL Server 2005 Service Pack 1 installieren Token verwenden

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 915845 - Produkte anzeigen, auf die sich dieser Artikel bezieht
# Fehler: 426808 (SQLBUDT)
Alles erweitern | Alles schließen

Problembeschreibung

Nachdem Sie Microsoft SQL Server 2005 Service Pack 1 (SP1) installiert haben, tritt das folgende Verhalten auf:
  • SQL Server-Agent-Aufträge fehlschlagen, wenn die Aufträge Auftrag Schritte enthalten, die Token verwenden.
  • Folgende Fehlermeldung wird angezeigt:
    Auftrag Schritt enthält eine oder mehrere Tokens. Für SQL Server 2005 Service Pack 1 oder höher müssen alle Auftrag Schritte mit Token mit einem Makro aktualisiert werden, bevor die Auftrag ausgeführt werden kann.
Hinweis: Dieses Problem tritt mit Build 2046 oder späteren Versionen von SQL Server 2005.

Ursache

In SQL Server 2005 SP1 wurde die SQLServerAgent-Auftrag Schritt token Syntax geändert. Nun müssen Sie ein Escape-Makro mit allen Token, die verwendet werden, einschließen, in Schritten von Auftrag. Wenn Sie ein Escape-Makro nicht einschließen, werden diese Auftrag Schritte fehlschlagen. Der folgende Tabelle sind die Escape-Makros aufgeführt.
Tabelle minimierenTabelle vergrößern
Escape-MakroBeschreibung
$ (ESCAPE_SQUOTE (TokenName))Dieses Makro Escapezeichen Apostrophe (') in der Zeichenfolge Tokenersetzung. Das Makro ersetzt ein Apostroph mit zwei Apostrophen.
$ (ESCAPE_DQUOTE (TokenName))Dieses Makro Escapezeichen Anführungszeichen ("") in der Zeichenfolge Tokenersetzung. Das Makro ersetzt ein Anführungszeichen durch zwei Anführungszeichen.
$ (ESCAPE_RBRACKET (TokenName))Dieses Makro Escapezeichen Rechte Klammern (]) in der Zeichenfolge Tokenersetzung. Das Makro ersetzt eine rechte Klammer mit zwei Rechte Klammern.
$ (ESCAPE_NONE (TokenName))Das Makro ersetzt ein Token ohne Escapezeichen für alle Zeichen in der Zeichenfolge. Dieses Makro dient zur Unterstützung der Abwärtskompatibilität in Umgebungen Tokenersetzung Zeichenfolgen nur aus vertrauenswürdigen Benutzern erwartet werden.
Ein Auftrag-Schritt kann z. B. die folgende Transact-SQL-Anweisung, die Eine KOSTENTRÄGERTEXT Token verwendet enthalten:
CREATE DATABASE [$(A-DBN)]
in diesem Beispiel, Sie müssen die Syntax die token aktualisieren, die folgende Syntax:
CREATE DATABASE [$(ESCAPE_RBRACKET(A-DBN))]
diese Änderung unterscheidet sich von früheren SQL Server 2005-Verhalten Escape-Makros nicht erforderlich waren.

Lösung

Auf um dieses Problem zu beheben, aktualisieren Sie entweder alle oder nur bestimmte Aufträge, die die neue token Syntax-Token verwenden. Verwenden Sie dazu das Sp_AddEscapeNoneToJobStepTokens gespeicherten Verfahren. Sie können diese gespeicherte Prozedur erstellen, indem mithilfe des folgenden Transact-SQL-Skripts.

Hinweis: Stellen Sie sicher, dass der SQL Server 2005 SP1-Build, den Sie installieren Build 2046 oder einen späteren Build ist. Darüber hinaus müssen Sie Mitglied der festen Serverrolle Sysadmin, 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

Nachdem Sie das Skript ausgeführt haben, wird die Sp_AddEscapeNoneToJobStepTokens gespeicherte Prozedur erstellt. Standardmäßig werden Sie alle Aufträge aktualisieren, wenn Sie diese gespeicherte Prozedur ohne Parameter ausführen. Wenn Sie nur bestimmte Aufträge aktualisieren möchten, müssen Sie Werte ungleich Null für mindestens eine der folgenden drei Parameter angeben:
  • @ job_name
  • @ job_id
  • @ owner_name
Verwenden Sie z. B. die folgende Syntax:
  • alle Aufträge zu aktualisieren:
    EXEC sp_AddEscapeNoneToJobStepTokens
  • Aktualisieren eine Auftrag durch Angabe von der Auftrag-Name:
    EXEC sp_AddEscapeNoneToJobStepTokens 'MyJob'
  • Aktualisieren Aufträge, die den gleichen Besitzer gehören:
    EXEC sp_AddEscapeNoneToJobStepTokens null,null,'JobOwner'
Dieses Skript wird alle Auftrag Schritte, die Token enthalten das ESCAPE_NONE -Makro hinzugefügt. Nachdem Sie dieses Skript ausführen, wird empfohlen, dass Sie Ihre Auftrag Schritte überprüfen, die Token so bald wie möglich verwenden. Ersetzen Sie anschließend das Makro ESCAPE_NONE mit einem der anderen Escape Makros, die für den Auftrag Schritt Kontext geeignet ist.

Hinweis: Wenn Sie in einem Masterserver (MSX) und Ziel-Serverumgebung (TSX) arbeiten, führen Sie dieses Skript auf dem MSX und den TSX um sicherzustellen, dass master Aufträge auf dem TSX-Server korrekt aktualisiert werden.

Weitere Informationen zum Aktualisieren der Aufträge an die neue Syntax verwenden und zum Escape-Makros verwenden, damit Tokenersetzung in SQL Server-Agent Auftrag Schritten finden Sie "Verwenden von Token in Auftragsschritten" in SQL Server 2005-Onlinedokumentation (April 2006) oder späteren Versionen von SQL Server 2005-Onlinedokumentation.

Status

Microsoft hat bestätigt, dass dies ein Problem in Microsoft-Produkten handelt, die im Abschnitt "Gilt für" aufgeführt sind.

Informationsquellen

Weitere Informationen zur Verwendung von Token in Auftrag Schritten der folgenden Microsoft Developer Network (MSDN)-Website:
http://msdn2.microsoft.com/en-us/library/ms175575.aspx

Eigenschaften

Artikel-ID: 915845 - Geändert am: Mittwoch, 24. Mai 2006 - Version: 2.1
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft SQL Server 2005 Standard Edition
  • Microsoft SQL Server 2005 Workgroup Edition
  • Microsoft SQL Server 2005 Enterprise Edition
Keywords: 
kbmt kbsql2005presp1fix kbprb kbexpertiseadvanced kbtshoot KB915845 KbMtde
Maschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 915845
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.

Ihr Feedback an uns

 

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