微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

查找要删除的引用不存在数据库的 SQL 作业

如何解决查找要删除的引用不存在数据库的 SQL 作业

我试图找到我们所有不再需要的 sql 作业,因为它们使用的数据库不再存在。

逻辑很简单,选择带有命令的作业列表,然后在命令中检查数据库是否列在 sysdatabase 表中。这就是我到目前为止所拥有的几乎就在那里:

SELECT 
   Srv.srvname AS ServerName,Job.name AS JobName,JStep.step_id,--JStep.step_name AS StepName,JStep.command
   --,Job.enabled 
    into #JobListTable
FROM   msdb.dbo.sysjobs Job
JOIN   msdb.dbo.sysjobsteps JStep
   ON  JStep.job_id = Job.job_id 
JOIN   MASTER.dbo.sysservers Srv
   ON  Srv.srvid = Job.originating_server_id
WHERE  JStep.subsystem='SSIS'
--SELECT * FROM #JobListTable

DECLARE @JobName SYSNAME,@StepId INT,@Command NVARCHAR(MAX),@Posstart BIGINT,@PosEnd BIGINT,@Server NVARCHAR(128),@JobList VARCHAR(MAX),@dbnAMETEMP SYSNAME,@sqlStatement VARCHAR(MAX)
DECLARE @MAXID INT,@Counter INT

SET @COUNTER = 1
SELECT @MAXID = COUNT(*) FROM #JobListTable
    
WHILE (@COUNTER <= @MAXID)
--WHILE (@COUNTER <= 3)
    BEGIN
            SET @JobName=(SELECT top 1 JobName FROM #JobListTable)-- WHERE command=@Command)
            SET @command=(SELECT top 1 command FROM #JobListTable)-- WHERE JobName=@JobName)  
            SET @StepId=(SELECT top 1 step_id FROM #JobListTable)

            SELECT @Command = [s].[command]
            FROM msdb.dbo.[sysjobs] [j]
            INNER JOIN msdb.dbo.[sysjobsteps] [s] ON [s].[job_id] = [j].[job_id]
            WHERE [j].[name] = @JobName
              AND [s].[step_id] = @StepId

            SET @Posstart = PATINDEX('%/SERVER %',@Command)+8
            SET @PosEnd = CHARINDEX(' ',@Command,@Posstart)
            SET @Server = SUBSTRING(@Command,@Posstart,@PosEnd - @Posstart)
            SET @Posstart = PATINDEX('%"\"%',@Command)+3
            SET @PosEnd = PATINDEX('%\""%',@Command)
            SET @Command = SUBSTRING(@Command,@PosEnd - @Posstart)

            --select

            --right(@Command,len(@Command) - charindex('Initial Catalog=',1)+1) DBIndexPos,--charindex(';',right(@Command,1)+1),1) SemiColonPos,SET @dbnAMETEMP = 
            replace(left(right(@Command,charindex(';',1)-1),'Initial Catalog=','') --DatabaseName

            --PRINT @dbnAMETEMP 
            
            select 'exec msdb..sp_delete_jobstep @job_name = ''' + j.name + ''',@step_id = ' + convert(varchar(100),js.step_id)
            from msdb..sysjobs j
                inner join msdb..syscategories c
                    on c.category_id = j.category_id
                inner join msdb..sysjobsteps js
                    on js.job_id = j.job_id
                where @dbnAMETEMP not in (select name from sysdatabases)


            SET @sqlStatement= 'EXEC msdb.dbo.sp_delete_job @job_name =''' + @jobName + ''',@delete_unused_schedule=1' 
            PRINT(@sqlStatement)

            --select * from #dblist

                SET @COUNTER = @COUNTER + 1
        
        DELETE FROM #JobListTable WHERE JobName=@JobName

END
    DROP TABLE #JobListTable
    --DROP TABLE #dblist

解决方法

我只需要可以从 msdb.dbo.sysjobs 和 msdb.dbo.sysjobsteps 获得的所有作业和作业步骤。然后我们可以在 sys.databases 中检查作业的数据库当前是否可用。请检查以下查询:

SELECT
     job.job_id,notify_level_email,name,enabled,description,step_name,command,server,database_name
FROM
    msdb.dbo.sysjobs job
INNER JOIN 
    msdb.dbo.sysjobsteps steps        
ON
    job.job_id = steps.job_id
    
WHERE database_name not in ( select name from sys.databases)
    
,

终于搞定了..

此代码允许您删除与旧数据库相关的所有作业步骤,然后您可以跟进并删除每个作业中不存在作业步骤的作业。很高兴我解决了我自己的第一篇文章!长期读者!

我创建了一个带有作业信息的临时表(包括具有 SSIS 连接详细信息的命令列):

SELECT Srv.srvname AS ServerName,Job.name AS JobName,Job.job_id,JStep.step_id,JStep.command as DatabaseName
into #JobListTable
FROM   msdb.dbo.sysjobs Job
JOIN   msdb.dbo.sysjobsteps JStep
   ON  JStep.job_id = Job.job_id 
JOIN   MASTER.dbo.sysservers Srv
   ON  Srv.srvid = Job.originating_server_id
WHERE  JStep.subsystem='SSIS'

然后我更新了(别名)列 DatabaseName 以删除所有我不想要的其余字符串,只留下连接字符串中的数据库名称:

UPDATE #JobListTable
SET DatabaseName = substring(DatabaseName,patindex('%Initial Catalog=%',DatabaseName)+16,(patindex('%Provider=%',DatabaseName)-patindex('%Initial Catalog=%',DatabaseName)-17))
WHERE patindex('%Initial Catalog=%',DatabaseName) > 0

下一部分从临时表构建 sp_delete_jobstep 命令,检查在连接字符串中找到的数据库名称在 sys.databases 表中不存在:

select 'exec msdb..sp_delete_jobstep @job_name = ''' + j.name + ''',@step_id = ' + convert(varchar(100),jlt.step_id)
        from #JobListTable jlt
        --from msdb..sysjobs j
            inner join msdb..sysjobs j
                on j.job_id = jlt.job_id
            where jlt.DatabaseName not in (select name from sys.databases)

清理临时表:

drop table #JobListTable

最后,如果您想删除所有没有作业步骤的作业,请运行:

select c.name,j.job_id,j.name,j.description,j.enabled,j.date_created,'exec msdb..sp_delete_job @job_name = ''' + j.name + ''',@delete_history = 1,@delete_unused_schedule = 1' as delete_cmd
from msdb..sysjobs j
 inner join msdb..syscategories c
   on c.category_id = j.category_id
 where not exists (
    select 1 from msdb..sysjobsteps js
    where js.job_id = j.job_id) and NOT ( c.name = 'Database Maintenance')

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。