Categorías
Donaciones

Todo el contenido es gratuito y en beneficio de la comunidad. Puedes reconocer el esfuerzo con una donación si lo deseas.

Inserte aquí su publicidad

La palabra “conocer” es polisémica. Aparte del sentido bíblico, podemos establecer dos niveles. Está “saber lo que es conceptualmente, ser consciente de su existencia” y luego está el nivel “dominar y poseer experiencia en la materia en cuestión”. yo no hace tanto que llegué a ese segundo nivel con OpenQuery. Los que tenemos la “suerte” de lidiar con motores que no son SQL Server, como DB2, estamos acostumbrados a que aquello, vía linked server tal cual (por nombres de cuatro partes), sea un suplicio. Sin embargo, con OpenQuery, le mandas lo que haya que buscar, filtradito, y la diferencia es como la noche y el día. Y lo mismo para leer que para escribir. No hay que olvidar que con OpenQuery estamos enviando la sentencia completa al servidor de destino para que la resuelva él.

Ahora estoy en la fase de, como lo que tengo es un martillo, todo me parece un clavo, y lo último que me he preparado es un recopilador de datos de jobs por esta vía. Es decir, ya no es sólo para acceder a DB2, sino también a otros motores SQL Server. Que se puede hacer de otras formas, que no rinde tan mal incluso directamente, pero como ya le he cogido el truco y la inercia al “select * from OpenQuery(…”, sabe hasta mejor.

Así, la sentencia básica sería:

select 'INSTANCIA' as Server, Job, DiaEjecucion, 
	HoraEjecucion, Duracion, Paso, NombrePaso, Mensaje
from OpenQuery([INSTANCIA], '
select g.name as Job, cast(h.run_date as varchar(20)) as DiaEjecucion, 
	right(''000000'' + cast(h.run_time as varchar(20)), 6) as HoraEjecucion,
	right(''000000'' + cast(h.run_duration as varchar(20)), 6) as Duracion,
	h.step_id as Paso,
	h.step_name as NombrePaso,
	h.message as Mensaje
from (
select j.name,h.instance_id id   
from 
	msdb.dbo.sysjobs j with(nolock) inner join 
	msdb.dbo.sysjobhistory h with(nolock) on j.job_id = h.job_id   
and h.run_status=0    
) g inner join msdb.dbo.sysjobhistory h with(nolock)on g.id = h.instance_id   
where h.step_id > 0 and
	h.run_date >= cast(CONVERT(char(8),dateadd(dd,-1,getdate()),112) as int)') T

 

Y si eso lo hacemos dinámico, empleando los servidores vinculados, volcando el resultado a una tabla, obtenemos lo siguiente (lleva una segunda parte para formatear un HTML que permita enviar el resultado por mail):

create proc [dbo].[Jobs_Fallidos] 
  @pOut varchar(max) = null output, 
  @pDestino varchar(10) = 'Mail', 
  @pTODO_OK bit = 0 output,
  @pFechaHoraDesde smalldatetime = null
  
  as

--Para sólo recuperar los de las últimas x horas
select @pFechaHoraDesde = isnull(@pFechaHoraDesde, dateadd(hh, -14, getdate()))

declare @sql nvarchar(max), @parte_fija nvarchar(max)

select @sql = '', @parte_fija = N'
    select ''#NombreLinkedServer#'' as Server, Job, DiaEjecucion, 
	  HoraEjecucion, Duracion, Paso, NombrePaso, Mensaje
	from OpenQuery([#NombreLinkedServer#], ''
	select g.name as Job, cast(h.run_date as varchar(20)) as DiaEjecucion, 
		right(''''000000'''' + cast(h.run_time as varchar(20)), 6) as HoraEjecucion,
		right(''''000000'''' + cast(h.run_duration as varchar(20)), 6) as Duracion,
		h.step_id as Paso,
		h.step_name as NombrePaso,
		h.message as Mensaje
	from (
	select j.name,h.instance_id id   
	from 
		msdb.dbo.sysjobs j with(nolock) inner join 
		msdb.dbo.sysjobhistory h with(nolock) on j.job_id = h.job_id   
	and h.run_status=0    
	) g inner join msdb.dbo.sysjobhistory h with(nolock)on g.id = h.instance_id   
	where h.step_id > 0 and
	  h.run_date >= cast(CONVERT(char(8),dateadd(dd,-1,getdate()),112) as int)'') T'  


if object_id ('tempdb..#fjobs') > 0
	 drop table #fjobs   
	 
create table #fjobs 
  (Server varchar(15) not null, 
   Job varchar(100) not null, 
   DiaEjecucion char(8) not null, 
   HoraEjecucion char(6) not null, 
   Duracion char(6) not null,
   Paso int null,
   NombrePaso varchar(100) null,
   Mensaje varchar(max) null
   )


select @sql = @sql + replace(@parte_fija, '#NombreLinkedServer#', name) + ' union all
'
from sys.servers where provider = 'SQLNCLI'

select @sql = left(@sql, len(@sql) - 12)

insert #fjobs
exec sp_executesql @sql

delete from #fjobs 
where DiaEjecucion + ' ' + 
  left(HoraEjecucion,2)+':'+substring(HoraEjecucion,3,2) < @pFechaHoraDesde

--Listado de jobs que han fallado
 select cast(h.Server as nvarchar(15)) Server, 
  cast(h.Job as nvarchar(100)) as Job, 
  cast(h.DiaEjecucion as nvarchar(8)) as DiaEjecucion,  
  cast(HoraEjecucion as nvarchar(6)) as HoraEjecucion, 
  cast(Duracion as nvarchar(8)) as Duracion,
  cast(Paso as nvarchar(10)) as Paso, 
  cast(NombrePaso as nvarchar(100)) as NombrePaso, 
  cast(Mensaje as nvarchar(500)) as Mensaje
 from #fjobs h 
 order by Server, Job, DiaEjecucion, HoraEjecucion, Paso 
 

--Apartir de aquí, es un divertimento para enviar un mail con este listado
if @pDestino = 'Mail' and exists(select top 1 h.Server from #fjobs h)  
 begin
  select @pOut = '<html> 
<head> 
<STYLE TYPE="text/css"> 
<!-- 
body{font-family: Segoi UI; font-size: 9pt;} 
TH{font-family: Segoi UI; font-size: 9pt; color: 000099} 
TD{font-family: Segoi UI; font-size: 9pt;} 
---> 
</STYLE> 
</head> 
<body><p>'+ 
  'Jobs Fallidos en las últimas horas:</p>' +    
'<table  border=1 cellspacing=0 cellpadding=3> 
<tr><th>Servidor</th><th>Job</th><th>Dia</th><th>Hora</th><th>Duracion</th>
<th>Step</th><th>Nombre</th><th>Mensaje</th>
</tr>'
 
  select @pOut = @pOut +  ' 
  <tr>' + 
  '<td>' + h.Server + '</td>' + 
  '<td>' + rtrim(h.Job)  + ' </td>' +   
  '<td>' + h.DiaEjecucion  + ' </td>' +   
  '<td>' + left(h.HoraEjecucion,2)+':'+substring(h.HoraEjecucion,3,2) + ' </td>' +   
  '<td>' + left(h.Duracion,2)+':'+substring(h.Duracion,3,2)+':'+right(h.Duracion,2)+''' </td>'+
  '<td>' + cast(h.Paso as varchar(10)) + ' </td>' +
  '<td>' + h.NombrePaso + ' </td>' +
  '<td>' + left(h.Mensaje, 200) + ' </td>' +
  + '</tr>'
  from #fjobs h  
  order by Server, Job, DiaEjecucion, HoraEjecucion, Paso
 
 select @pOut = @pOut + '</table>' + 
 '<p>No responda a este mensaje</p>' +
 '<p>Sistemas de Información.<BR>
 Plus Ultra Seguros.</p>' +
'</body> 
</html>'

 end

if not exists(select top 1 h.Server from #fjobs h) 
 select @pTODO_OK = 1
else 
 select @pTODO_OK = 0

if object_id ('tempdb..#fjobs') > 0
 drop table #fjobs
 
set nocount off

return 0

 

Y bueno, ya está. Hemos hecho uso y abuso de OpenQuery.

Un comentario para “Abusando de OpenQuery”

  • Inaurys dice:

    Al aplicar ese script me dice que:

    Mens. 7411, Nivel 16, Estado 1, Línea 1
    El servidor ‘INSTANCIA’ no está configurado para DATA ACCESS.

    Y necesito ese script que hace MESES que estoy tratando de encontrar algo como eso.

    MUCHISIMAS GRACIAS POR EL APORTE !!!!!!!!!!

Deja un comentario


Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies