Tareas de SQLServerAgent no cuando los trabajos contienen pasos de trabajo que utilizan los símbolos (tokens) después de instalar SQL Server 2005 Service Pack 1

IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.

Haga clic aquí para ver el artículo original (en inglés): 915845
Nº de error: 426808 (SQLBUDT)
Síntomas
Después de instalar Microsoft SQL Server 2005 Service Pack 1 (SP1), experimenta el comportamiento siguiente:
  • Trabajos del Agente SQL Server fallar a los trabajos contienen pasos de trabajo que utilizan símbolos (tokens).
  • Recibirá el siguiente mensaje de error:
    El paso de trabajo contiene uno o más testigos. Para SQL Server 2005 Service Pack 1 o versiones posteriores, todos los pasos de trabajo con símbolos (tokens) deben actualizarse con una macro antes de que puede ejecutar el trabajo.
Nota Este problema se produce con versiones de generación 2046 o posteriores de SQL Server 2005.
Causa
En SQL Server 2005 SP1, ha cambiado la sintaxis de símbolo (token) de paso de trabajo de Agente SQL Server. Ahora, debe incluir una macro de escape con todos los tokens que se utilizan en los pasos de trabajo. Si no incluye una macro de escape, estos pasos de trabajo producirá un error. En la tabla siguiente se enumeran las macros de escape.
Macro de escapeDescripción
$ (ESCAPE_SQUOTE (TokenName))Esta macro escapes apóstrofos (') en la cadena de reemplazo símbolo (token). La macro reemplaza un apóstrofo con dos apóstrofos.
$ (ESCAPE_DQUOTE (TokenName))Esta macro de secuencias de escape comillas ("") en la cadena de reemplazo símbolo (token). La macro reemplaza una comilla con dos comillas.
$ (ESCAPE_RBRACKET (TokenName))Esta macro escapes paréntesis derecho (]) en la cadena de símbolo (token) de reemplazo. La macro reemplaza un corchete de cierre con dos corchetes derecho.
$ (ESCAPE_NONE (TokenName))La macro reemplaza un símbolo (token) sin escape cualquier caracteres de la cadena. Esta macro se proporciona para la compatibilidad con versiones anteriores en entornos donde se esperan sólo cadenas de reemplazo símbolo (token) de usuarios de confianza.
Por ejemplo, un paso de trabajo puede contener la siguiente instrucción de Transact-SQL que utiliza el token A DBN :
CREATE DATABASE [$(A-DBN)]
en este ejemplo, debe actualizar la sintaxis de símbolo (token) a la siguiente sintaxis:
CREATE DATABASE [$(ESCAPE_RBRACKET(A-DBN))]
este cambio difiere del comportamiento anterior de SQL Server 2005, donde las macros de escape no eran necesarias.
Solución
Para resolver este problema, actualice todos los o sólo los trabajos concretos que utilizan símbolos a la nueva sintaxis de símbolo (token). Para ello, utilice el procedimiento sp_AddEscapeNoneToJobStepTokens almacenados. Puede crear este procedimiento almacenado mediante la siguiente secuencia de comandos Transact-SQL.

Nota Asegúrese de que la generación de SQL Server 2005 SP1 instalar es generar 2046 o una versión posterior. Además, debe ser un miembro de la función fija de servidor sysadmin para ejecutar el 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    returnENDuse msdbgoif exists (select * from sys.objects where name = N'fn_PrefaceTokensWithEscapeNone' and type = 'FN')    drop function fn_PrefaceTokensWithEscapeNonego-- This function manipulates @commands so that all bare tokens-- are prefaced with ESCAPE_NONE.create function fn_PrefaceTokensWithEscapeNone(@commands nvarchar(max)) RETURNS nvarchar(max)ASBEGIN    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 @commandsENDgoif exists (select * from sys.objects where name = N'sp_AddEscapeNoneToJobStepTokens' and type = 'P')    drop procedure sp_AddEscapeNoneToJobStepTokensgo-- 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_idgo
Después de ejecutar la secuencia de comandos, el procedimiento sp_AddEscapeNoneToJobStepTokens almacenado se crea. De forma predeterminada, se actualizarán todos los trabajos si ejecuta este procedimiento almacenado sin parámetros. Si desea actualizar sólo los trabajos concretos, debe especificar los valores no null para al menos uno de los siguientes tres parámetros:
  • @ job_name
  • @ job_id
  • @ owner_name
Por ejemplo, puede utilizar la sintaxis siguiente:
  • actualizar todos los trabajos:
    EXEC sp_AddEscapeNoneToJobStepTokens
  • actualizar un trabajo, que especifica el nombre de trabajo:
    EXEC sp_AddEscapeNoneToJobStepTokens 'MyJob'
  • Actualizar trabajos que pertenecen al mismo propietario:
    EXEC sp_AddEscapeNoneToJobStepTokens null,null,'JobOwner'
Esta secuencia de comandos agrega la macro ESCAPE_NONE a todos los pasos de trabajo que contienen símbolos (tokens). Después de ejecutar esta secuencia de comandos, recomendamos que revise los pasos de trabajo que utilizan símbolos (tokens) tan pronto como sea posible. A continuación, reemplace la macro ESCAPE_NONE con uno de las macros de escape adecuada para el contexto de paso de trabajo.

Nota Si está trabajando en un servidor principal (MSX) y el entorno de destino (TSX) de servidor, debe ejecutar esta secuencia de comandos en el servidor principal y el servidor de destino para asegurarse de que se actualizan correctamente trabajos maestros en el servidor de destino.

Para obtener más información acerca de cómo actualizar los trabajos para utilizar la nueva sintaxis y cómo utilizar las macros de escape para habilitar el símbolo (token) de reemplazo en pasos de trabajo del Agente SQL Server, vea el tema "Mediante testigos en pasos de trabajo" en libros en pantalla de SQL Server 2005 (abril de 2006) o versiones posteriores de libros en pantalla de SQL Server 2005.
Estado
Microsoft ha confirmado que se trata de un problema de los productos de Microsoft enumerados en la sección "La información de este artículo se refiere a:".
Referencias
Para obtener más información acerca de cómo utilizar testigos en pasos de trabajo, visite el siguiente sitio Web de Microsoft Developer Network (MSDN):

Advertencia: este artículo se tradujo automáticamente

Propiedades

Id. de artículo: 915845 - Última revisión: 05/24/2006 16:37:19 - Revisión: 2.1

Microsoft SQL Server 2005 Standard Edition, Microsoft SQL Server 2005 Workgroup Edition, Microsoft SQL Server 2005 Enterprise Edition

  • kbmt kbsql2005presp1fix kbprb kbexpertiseadvanced kbtshoot KB915845 KbMtes
Comentarios