Я пытаюсь найти все наши задания 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, @PosStart, @PosEnd - @PosStart)

            --select

            --right(@Command, len(@Command) - charindex('Initial Catalog=',@Command ,1)+1) DBIndexPos,
            --charindex(';',right(@Command, len(@Command) - charindex('Initial Catalog=',@Command ,1)+1),1) SemiColonPos,
            SET @DBNAMETEMP = 
            replace(left(right(@Command, len(@Command) - charindex('Initial Catalog=',@Command ,1)+1), charindex(';',right(@Command, len(@Command) - charindex('Initial Catalog=',@Command ,1)+1),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
0
pete4x4 11 Фев 2021 в 15:32

2 ответа

Лучший ответ

Наконец-то все заработало ..

Этот код позволяет удалить все этапы задания, относящиеся к старой базе данных, а затем вы можете отслеживать и удалять задания, для которых этапы задания отсутствуют в каждом задании. Счастлив, что решил свой первый пост! Давний читатель!

Я создал временную таблицу с информацией о задании (включая столбец команд, в котором есть сведения о соединении 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')
0
pete4x4 11 Фев 2021 в 16:09

Мне просто нужны все задания и этапы работы, которые вы можете получить из 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)
    
0
Kazi Mohammad Ali Nur 11 Фев 2021 в 12:52
66154856