找到 SQL 个要删除的引用不存在的数据库的作业
Find SQL jobs to delete that refer to non-existent databases
我正在尝试查找我们所有的 SQL 工作,由于他们使用的数据库不再存在,因此不再需要这些工作。
逻辑很简单,select 带有命令的作业列表,然后在命令中检查数据库是否列在 sysdatabase table 中。这是我目前所拥有的,几乎就在那里:
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
我只需要 msdb.dbo.sysjobs 和 msdb.dbo.sysjobs 中的所有工作和工作步骤。然后我们可以简单地检查 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)
终于成功了..
此代码允许您删除与旧数据库相关的所有作业步骤,然后您可以跟进并删除每个作业中不存在作业步骤的作业。很高兴我先解决了自己的问题 post!好久reader!
我用作业信息(包括具有 SSIS 连接详细信息的命令列)创建了一个临时文件 table:
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
下一节从临时 table 构建 sp_delete_jobstep 命令,检查 sys.databases table 中不存在在连接字符串中找到的数据库名称:
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)
清理温度table:
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')
我正在尝试查找我们所有的 SQL 工作,由于他们使用的数据库不再存在,因此不再需要这些工作。
逻辑很简单,select 带有命令的作业列表,然后在命令中检查数据库是否列在 sysdatabase table 中。这是我目前所拥有的,几乎就在那里:
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
我只需要 msdb.dbo.sysjobs 和 msdb.dbo.sysjobs 中的所有工作和工作步骤。然后我们可以简单地检查 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)
终于成功了..
此代码允许您删除与旧数据库相关的所有作业步骤,然后您可以跟进并删除每个作业中不存在作业步骤的作业。很高兴我先解决了自己的问题 post!好久reader!
我用作业信息(包括具有 SSIS 连接详细信息的命令列)创建了一个临时文件 table:
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
下一节从临时 table 构建 sp_delete_jobstep 命令,检查 sys.databases table 中不存在在连接字符串中找到的数据库名称:
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)
清理温度table:
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')