O Unit Separator (US) e o erro ao tentar desabilitar um JOB no SQL Server Agent!

Olá pessoal tudo certo? Espero que sim!

Recentemente no cliente passei por algo bem interessante, havia um JOB que não conseguia desabilitar no SQL Server Agent, quando eu tentava o erro abaixo ocorria:


Via T-SQL também dava o mesmo erro, porém surgiu a primeira dica:


Msg 6841, Level 16, State 1, Procedure tr_job_disable, Line 27

FOR XML could not serialize the data for node 'td' because it contains a character (0x001F) which is not allowed in XML. To retrieve this data using FOR XML, convert it to binary, varbinary or image data type and use the BINARY BASE64 directive.

Que objeto seria este? Como o ambiente era bem tranquilo com relação ao volume de transações, decidi rodar um Profiler capturando os seguintes eventos:

·         Errors & Warnings (All).
·         SP: StmtStarting
·         SQL: BatchStarting
·         SQL: StmtStarting

Com o Profiler no ar, tentei o Disable novamente no JOB para provocar o erro, vejam que interessante. Antes de ocorrer um Exception foi capturado o seguinte trecho de código:




Olhando a coluna Object Name e Object Type foi possível confirmar que o objeto envolvido era uma trigger:


Esta trigger estava criada dentro da tabela de sistema sysjobs no MSDB, e seu intuito era que toda vez que algum JOB fosse desabilitado um e-mail fosse enviado para os DBA’s. Voltando ao nosso erro:

Msg 6841, Level 16, State 1, Procedure tr_job_disable, Line 27

FOR XML could not serialize the data for node 'td' because it contains a character (0x001F) which is not allowed in XML. To retrieve this data using FOR XML, convert it to binary, varbinary or image data type and use the BINARY BASE64 directive.

Nosso problema dentro da trigger está no comando abaixo, mais precisamente no que esta marcado em amarelo:

SET @tableHTML =   
   N'<H1>Job desabilitado!</H1>' +   
   N'<table border="2">' +   
   N'<tr><th>Job</th>' +   
   N'<th>Server</th>' +             
   N'<th>Data</th>' +       
   N'<th>Usuário</th></tr>' +   
   CAST ( ( SELECT td = Job,       '',   
       td = @@servername, '',   
       td = data, '',    
       td = Usuario, ''          
       FROM #TableIC            
       FOR XML PATH('tr'), TYPE    
   ) AS NVARCHAR(MAX) ) +   
   N'</table>' ;  

O SQL está dizendo que existe um caracter inválido 0x001F para formatação do e-mail, mas quem seria 0x001F?

Pesquisando um pouco descobri que este é o valor hexadecimal correspondente ao UNIT SEPARATOR (US), um caracter que seria uma espécie de “underline”, visível apenas em alguns editores de texto:

Unicode Map : Public Unicode Character Map

What is character 0x1f?

Já sabendo do US notei outra coisa, vejam como ficou a seleção do job no SQL Server Agent quando foi "clicado":

Ele tem realmente um “espaço em branco” na frente. Pois bem, gerei o script do mesmo. No Management Studio do SQL Server, tudo ok:

Mas no Notepad++, notem o US aparecendo!

E no Word, notem o “_” aparecendo!

Desabilitando a trigger, ou então removendo o US do nome do JOB:


Sucesso! Foi possível desabilitar o job.

Para fechar o assunto, deixo como recomendação que todo script escrito fora do SSMS seja analisado com cuidado e lembro ainda, que triggers sobre tabelas de sistema não são suportadas pela Microsoft, conforme link abaixo:

System Databases

Espero que tenha sido útil! Um abraço!