无需启动SQL Agent,如何查看旧SQL Server实例的SQL Agent Job并生成其代码?
无需启动SQL Agent查看并生成旧作业的方法
嗨,这个问题我太熟了——完全不需要启动旧的SQL Agent就能搞定!SQL Agent的所有作业配置其实都存在msdb系统数据库的一系列表中,只要你能连接到旧服务器的SQL Server数据库引擎(注意是数据库引擎服务,不是Agent服务),就能直接查询这些表,甚至生成完整的作业创建脚本。
下面是具体步骤:
1. 定位目标作业的基本信息
首先,连接到旧服务器的SQL Server实例,执行下面的查询找到你要的作业ID(替换成你的作业名称):
SELECT job_id, name, description, owner_sid FROM msdb.dbo.sysjobs WHERE name = '你的目标作业名称';
这个查询会返回作业的唯一ID、名称、描述以及所有者的SID(后面生成脚本时可能需要替换成新服务器的登录名)。
2. 查询作业的具体步骤
每个作业的执行步骤都存在sysjobsteps表中,用刚才拿到的job_id关联查询:
SELECT step_id, step_name, subsystem, -- 比如TSQL、CmdExec、PowerShell等 command, -- 步骤执行的具体脚本/命令 database_name, -- 执行步骤的目标数据库 on_success_action, -- 步骤成功后的动作(继续下一个步骤/结束作业等) on_fail_action -- 步骤失败后的动作 FROM msdb.dbo.sysjobsteps WHERE job_id = '刚才查到的作业ID';
这里能看到每个步骤的核心逻辑,比如TSQL脚本、命令行指令等。
3. 查询作业的调度规则
作业的调度信息存储在sysjobschedules和sysschedules关联表中,执行下面的查询获取调度详情:
SELECT s.name AS schedule_name, s.freq_type, -- 调度类型:1=一次性,4=每天,8=每周,16=每月等 s.freq_interval, -- 具体执行间隔(比如每周几、每月几号) s.freq_subday_type, -- 日内调度类型:1=指定时间,4=每N分钟等 s.freq_subday_interval, -- 日内间隔时长 s.active_start_date, -- 调度生效起始日期 s.active_start_time -- 调度生效起始时间(格式为HHMMSS) FROM msdb.dbo.sysjobschedules js JOIN msdb.dbo.sysschedules s ON js.schedule_id = s.schedule_id WHERE js.job_id = '刚才查到的作业ID';
如果你需要还原调度,这些参数都是后续创建新作业时需要的。
4. 一键生成完整的作业创建脚本
如果你不想手动整理以上信息,可以用下面的脚本直接生成可执行的TSQL创建代码(替换作业名称即可):
DECLARE @TargetJobName NVARCHAR(128) = '你的目标作业名称'; DECLARE @JobID UNIQUEIDENTIFIER = (SELECT job_id FROM msdb.dbo.sysjobs WHERE name = @TargetJobName); -- 生成作业基础配置 SELECT 'USE [msdb] GO EXEC msdb.dbo.sp_add_job @job_name=N''' + name + ''', @enabled=1, @notify_level_eventlog=0, @notify_level_email=' + CAST(notify_level_email AS NVARCHAR) + ', @notify_level_netsend=' + CAST(notify_level_netsend AS NVARCHAR) + ', @notify_level_page=' + CAST(notify_level_page AS NVARCHAR) + ', @delete_level=0, @description=N''' + ISNULL(description, '') + ''', @category_name=N''' + category_name + ''', @owner_login_name=N''' + SUSER_SNAME(owner_sid) + '''; -- 转换SID为登录名 GO' FROM msdb.dbo.sysjobs WHERE job_id = @JobID; -- 生成作业步骤 DECLARE @StepCursor CURSOR; SET @StepCursor = CURSOR FOR SELECT step_id, step_name, subsystem, command, database_name, on_success_action, on_fail_action, retry_attempts, retry_interval FROM msdb.dbo.sysjobsteps WHERE job_id = @JobID; DECLARE @StepID INT, @StepName NVARCHAR(128), @Subsystem NVARCHAR(40), @Cmd NVARCHAR(MAX), @DBName NVARCHAR(128), @OnSuccess INT, @OnFail INT, @RetryAttempts INT, @RetryInterval INT; OPEN @StepCursor; FETCH NEXT FROM @StepCursor INTO @StepID, @StepName, @Subsystem, @Cmd, @DBName, @OnSuccess, @OnFail, @RetryAttempts, @RetryInterval; WHILE @@FETCH_STATUS = 0 BEGIN SELECT 'EXEC msdb.dbo.sp_add_jobstep @job_name=N''' + @TargetJobName + ''', @step_name=N''' + @StepName + ''', @step_id=' + CAST(@StepID AS NVARCHAR) + ', @subsystem=N''' + @Subsystem + ''', @command=N''' + REPLACE(@Cmd, '''', '''''') + ''', @database_name=N''' + ISNULL(@DBName, '') + ''', @on_success_action=' + CAST(@OnSuccess AS NVARCHAR) + ', @on_fail_action=' + CAST(@OnFail AS NVARCHAR) + ', @retry_attempts=' + CAST(@RetryAttempts AS NVARCHAR) + ', @retry_interval=' + CAST(@RetryInterval AS NVARCHAR) + '; GO' FETCH NEXT FROM @StepCursor INTO @StepID, @StepName, @Subsystem, @Cmd, @DBName, @OnSuccess, @OnFail, @RetryAttempts, @RetryInterval; END CLOSE @StepCursor; DEALLOCATE @StepCursor; -- 生成作业调度 DECLARE @SchedCursor CURSOR; SET @SchedCursor = CURSOR FOR SELECT s.name AS schedule_name, s.freq_type, s.freq_interval, s.freq_subday_type, s.freq_subday_interval, s.freq_relative_interval, s.freq_recurrence_factor, s.active_start_date, s.active_end_date, s.active_start_time, s.active_end_time FROM msdb.dbo.sysjobschedules js JOIN msdb.dbo.sysschedules s ON js.schedule_id = s.schedule_id WHERE js.job_id = @JobID; DECLARE @SchedName NVARCHAR(128), @FreqType INT, @FreqInterval INT, @FreqSubdayType INT, @FreqSubdayInterval INT, @FreqRelativeInterval INT, @FreqRecurFactor INT, @StartDate INT, @EndDate INT, @StartTime INT, @EndTime INT; OPEN @SchedCursor; FETCH NEXT FROM @SchedCursor INTO @SchedName, @FreqType, @FreqInterval, @FreqSubdayType, @FreqSubdayInterval, @FreqRelativeInterval, @FreqRecurFactor, @StartDate, @EndDate, @StartTime, @EndTime; WHILE @@FETCH_STATUS = 0 BEGIN SELECT 'EXEC msdb.dbo.sp_add_jobschedule @job_name=N''' + @TargetJobName + ''', @name=N''' + @SchedName + ''', @freq_type=' + CAST(@FreqType AS NVARCHAR) + ', @freq_interval=' + CAST(@FreqInterval AS NVARCHAR) + ', @freq_subday_type=' + CAST(@FreqSubdayType AS NVARCHAR) + ', @freq_subday_interval=' + CAST(@FreqSubdayInterval AS NVARCHAR) + ', @freq_relative_interval=' + CAST(@FreqRelativeInterval AS NVARCHAR) + ', @freq_recurrence_factor=' + CAST(@FreqRecurFactor AS NVARCHAR) + ', @active_start_date=' + CAST(@StartDate AS NVARCHAR) + ', @active_end_date=' + CAST(@EndDate AS NVARCHAR) + ', @active_start_time=' + CAST(@StartTime AS NVARCHAR) + ', @active_end_time=' + CAST(@EndTime AS NVARCHAR) + '; GO' FETCH NEXT FROM @SchedCursor INTO @SchedName, @FreqType, @FreqInterval, @FreqSubdayType, @FreqSubdayInterval, @FreqRelativeInterval, @FreqRecurFactor, @StartDate, @EndDate, @StartTime, @EndTime; END CLOSE @SchedCursor; DEALLOCATE @SchedCursor; -- 生成作业与服务器的关联(单服务器环境) SELECT 'EXEC msdb.dbo.sp_add_jobserver @job_name=N''' + @TargetJobName + ''', @server_name=N''(local)''; GO' FROM msdb.dbo.sysjobs WHERE job_id = @JobID;
执行这个脚本后,会输出完整的作业创建TSQL,你只需要复制这些代码,调整一下所有者登录名(如果新服务器没有旧的登录账号)、数据库名称等适配新环境的参数,就能在新服务器上运行创建作业了。
注意事项
- 确保你对旧服务器的
msdb数据库有查询权限(至少是db_datareader角色); - 如果旧服务器的数据库引擎已经停止,你可以把旧的
msdb.mdf和msdb.ldf文件挂载到新服务器上,然后查询这个附加的数据库; - 生成的脚本里,作业通知(邮件/消息)部分如果涉及旧服务器的操作员,需要在新服务器上先创建对应的操作员再执行脚本。
内容的提问来源于stack exchange,提问作者andyabel
相关产品推荐
相关产品推荐

