您的位置:首页 > 数据库

SQL SERVER 中如何用脚本管理作业

2016-06-03 17:29 429 查看
在SQLSERVER中用脚本管理作业,在绝大部分场景下,脚本都比UI界面管理作业要高效、简洁。打个简单的比方,如果你要查看作业的运行时长,如果用UI界面查看,100个作业,你就得在历史记录里面至少查看一百次甚至更多,还要记录、统计作业各个步骤的执行时间。而用脚本,一个查询就OK了。这篇文章分享一些我在数据库管理过程中积累的一些常用脚本。如有不足或需要完善的地方,也请多多指教。

1:业务场景:你想了解一下所有作业的Schedule信息,方便你作出调整或分析。例如作业的执行频率;例如你想查询那些作业是一小时执行一次的,那些是间隔几分钟执行一次的,使用下面脚本来查看吧。

[code]
[code]DECLARE@WeekDaysTABLE

(

freq_intervalINT,

weekdaysNVARCHAR(120)


)


INSERTINTO@WeekDays

SELECT1,N'星期日'UNIONALL

SELECT2,N'星期一'UNIONALL

SELECT4,N'星期二'UNIONALL

SELECT8,N'星期三'UNIONALL

SELECT16,N'星期四'UNIONALL

SELECT32,N'星期五'UNIONALL

SELECT64,N'星期六'UNIONALL

SELECT3,N'星期日,一'UNIONALL

SELECT5,N'星期日,二'UNIONALL

SELECT9,N'星期日,三'UNIONALL

SELECT17,N'星期日,四'UNIONALL

SELECT33,N'星期日,五'UNIONALL

SELECT65,N'星期日,六'UNIONALL

SELECT6,N'星期一,二'UNIONALL

SELECT10,N'星期一,三'UNIONALL

SELECT18,N'星期一,四'UNIONALL

SELECT34,N'星期一,五'UNIONALL

SELECT66,N'星期一,六'UNIONALL

SELECT12,N'星期二,三'UNIONALL

SELECT20,N'星期二,四'UNIONALL

SELECT36,N'星期二,五'UNIONALL

SELECT68,N'星期二,六'UNIONALL

SELECT24,N'星期三,四'UNIONALL

SELECT40,N'星期三,五'UNIONALL

SELECT72,N'星期三,六'UNIONALL

SELECT48,N'星期四,五'UNIONALL

SELECT80,N'星期四,六'UNIONALL

SELECT96,N'星期五,六'UNIONALL

SELECT7,N'星期日,一,二'UNIONALL

SELECT11,N'星期日,一,三'UNIONALL

SELECT19,N'星期日,一,四'UNIONALL

SELECT35,N'星期日,一,五'UNIONALL

SELECT67,N'星期日,一,六'UNIONALL

SELECT13,N'星期日,二,三'UNIONALL

SELECT21,N'星期日,二,四'UNIONALL

SELECT37,N'星期日,二,五'UNIONALL

SELECT69,N'星期日,二,六'UNIONALL

SELECT25,N'星期日,三,四'UNIONALL

SELECT41,N'星期日,三,五'UNIONALL

SELECT73,N'星期日,三,六'UNIONALL

SELECT49,N'星期日,四,五'UNIONALL

SELECT81,N'星期日,四,六'UNIONALL

SELECT97,N'星期日,五,六'UNIONALL

SELECT14,N'星期一,二,三'UNIONALL

SELECT22,N'星期一,二,四'UNIONALL

SELECT38,N'星期一,二,五'UNIONALL

SELECT70,N'星期一,二,六'UNIONALL

SELECT26,N'星期一,三,四'UNIONALL

SELECT42,N'星期一,三,五'UNIONALL

SELECT74,N'星期一,三,六'UNIONALL

SELECT50,N'星期一,四,五'UNIONALL

SELECT82,N'星期一,四,六'UNIONALL

SELECT98,N'星期一,五,六'UNIONALL

SELECT28,N'星期二,三,四'UNIONALL

SELECT44,N'星期二,三,五'UNIONALL

SELECT76,N'星期二,三,六'UNIONALL

SELECT52,N'星期二,四,五'UNIONALL

SELECT84,N'星期二,四,六'UNIONALL

SELECT100,N'星期二,五,六'UNIONALL

SELECT56,N'星期三,四,五'UNIONALL

SELECT88,N'星期三,四,六'UNIONALL

SELECT104,N'星期三,五,六'UNIONALL

SELECT112,N'星期四,五,六'UNIONALL

SELECT15,N'星期日,一,二,三'UNIONALL

SELECT23,N'星期日,一,二,四'UNIONALL

SELECT39,N'星期日,一,二,五'UNIONALL

SELECT71,N'星期日,一,二,六'UNIONALL

SELECT27,N'星期日,一,三,四'UNIONALL

SELECT43,N'星期日,一,三,五'UNIONALL

SELECT75,N'星期日,一,三,六'UNIONALL

SELECT51,N'星期日,一,四,五'UNIONALL

SELECT83,N'星期日,一,四,六'UNIONALL

SELECT99,N'星期日,一,五,六'UNIONALL

SELECT29,N'星期日,二,三,四'UNIONALL

SELECT45,N'星期日,二,三,五'UNIONALL

SELECT77,N'星期日,二,三,六'UNIONALL

SELECT53,N'星期日,二,四,五'UNIONALL

SELECT85,N'星期日,二,四,六'UNIONALL

SELECT101,N'星期日,二,五,六'UNIONALL

SELECT57,N'星期日,三,四,五'UNIONALL

SELECT89,N'星期日,三,四,六'UNIONALL

SELECT105,N'星期日,三,五,六'UNIONALL

SELECT113,N'星期日,四,五,六'UNIONALL

SELECT30,N'星期一,二,三,四'UNIONALL

SELECT46,N'星期一,二,三,五'UNIONALL

SELECT78,N'星期一,二,三,六'UNIONALL

SELECT54,N'星期一,二,四,五'UNIONALL

SELECT86,N'星期一,二,四,六'UNIONALL

SELECT102,N'星期一,二,五,六'UNIONALL

SELECT58,N'星期一,三,四,五'UNIONALL

SELECT90,N'星期一,三,四,六'UNIONALL

SELECT106,N'星期一,三,五,六'UNIONALL

SELECT114,N'星期一,四,五,六'UNIONALL

SELECT60,N'星期二,三,四,五'UNIONALL

SELECT92,N'星期二,三,四,六'UNIONALL

SELECT108,N'星期二,三,五,六'UNIONALL

SELECT116,N'星期二,四,五,六'UNIONALL

SELECT120,N'星期三,四,五,六'UNIONALL

SELECT31,N'星期日,一,二,三,四'UNIONALL

SELECT47,N'星期日,一,二,三,五'UNIONALL

SELECT79,N'星期日,一,二,三,六'UNIONALL

SELECT55,N'星期日,一,二,四,五'UNIONALL

SELECT87,N'星期日,一,二,四,六'UNIONALL

SELECT103,N'星期日,一,二,五,六'UNIONALL

SELECT59,N'星期日,一,三,四,五'UNIONALL

SELECT91,N'星期日,一,三,四,六'UNIONALL

SELECT107,N'星期日,一,三,五,六'UNIONALL

SELECT115,N'星期日,一,四,五,六'UNIONALL

SELECT61,N'星期日,二,三,四,五'UNIONALL

SELECT93,N'星期日,二,三,四,六'UNIONALL

SELECT109,N'星期日,二,三,五,六'UNIONALL

SELECT117,N'星期日,二,四,五,六'UNIONALL

SELECT121,N'星期日,三,四,五,六'UNIONALL

SELECT62,N'星期一,二,三,四,五'UNIONALL

SELECT94,N'星期一,二,三,四,六'UNIONALL

SELECT110,N'星期一,二,三,五,六'UNIONALL

SELECT118,N'星期一,二,四,五,六'UNIONALL

SELECT122,N'星期一,三,四,五,六'UNIONALL

SELECT124,N'星期二,三,四,五,六'UNIONALL

SELECT63,N'星期日,一,二,三,四,五'UNIONALL

SELECT95,N'星期日,一,二,三,四,六'UNIONALL

SELECT111,N'星期日,一,二,三,五,六'UNIONALL

SELECT119,N'星期日,一,二,四,五,六'UNIONALL

SELECT123,N'星期日,一,三,四,五,六'UNIONALL

SELECT125,N'星期日,二,三,四,五,六'UNIONALL

SELECT126,N'星期一,二,三,四,五,六'UNIONALL

SELECT127,N'星期日,一,二,三,四,五,六';


SELECTd.job_idASjob_id,

j.nameASjob_name,

CASEWHENj.enabled=1THENN'启用'

ELSEN'禁用'ENDASjob_staus,

CASEWHENfreq_type=1THENN'运行一次'

WHENfreq_type=4THENN'每天执行'

WHENfreq_type=8THENN'每周执行'

WHENfreq_type=16THENN'每月执行'

WHENfreq_type=32THENN'每月执行'

WHENfreq_type=64THENN'代理服务启动时运行'

WHENfreq_type=128THENN'在计算机空闲时运行'

ENDASfreq_type,

CASEWHENfreq_type=1THENN'选项无意义'

WHENfreq_type=4THEN

(

CASEWHENfreq_subday_type=4

THENN'每隔'+CONVERT(NVARCHAR(4),freq_subday_interval)+N'分钟执行一次'

WHENfreq_subday_type=8

THENN'每隔'+CONVERT(NVARCHAR(4),freq_subday_interval)+N'小时执行一次'

ELSEN'每天执行'+CONVERT(NVARCHAR(4),freq_interval)+N'次'

END

)

WHENfreq_type=8THEN

(SELECTw.weekdaysFROM@WeekDayswWHEREw.freq_interval=s.freq_interval

)


WHENfreq_type=16THENN'每月'+CONVERT(NVARCHAR(4),freq_interval)+N'号执行'

WHENfreq_type=32THENN'每月星期'+CONVERT(NVARCHAR(4),freq_interval)+N'执行'

ENDASfreq_relative_interval,

CASEWHENfreq_subday_type=1THENN'指定时间点执行一次'

WHENfreq_subday_type=2THENN'每隔:'+CAST(freq_subday_intervalASVARCHAR(2))+N'秒执行一次'

WHENfreq_subday_type=4THENN'每隔:'+CAST(freq_subday_intervalASVARCHAR(2))+N'分执行一次'

WHENfreq_subday_type=8THENN'每隔:'+CAST(freq_subday_intervalASVARCHAR(2))+N'小时执行一次'

ENDASfreq_subday_type,

CASEWHENfreq_subday_type=1THENN'开始时间点:'

+CAST(active_start_time/10000ASVARCHAR(2))+N'点'

+CAST(active_start_time%10000/100ASVARCHAR(2))+N'分'

WHENfreq_subday_type=2THENN'开始时间点:'

+CAST(active_start_time/10000ASVARCHAR(2))+N'点'

+CAST(active_start_time%10000/100ASVARCHAR(2))+N'分'

WHENfreq_subday_type=4THENN'开始时间点:'

+CAST(active_start_time/10000ASVARCHAR(2))+N'点'

+CAST(active_start_time%10000/100ASVARCHAR(2))+N'分'

WHENfreq_subday_type=8THENN'开始时间点:'

+CAST(active_start_time/10000ASVARCHAR(2))+N'点'

+CAST(active_start_time%10000/100ASVARCHAR(2))+N'分'

ENDASjob_start_time,

CASEWHENfreq_subday_type=1THENN'结束时间点:'

+CAST(active_end_time/10000ASVARCHAR(2))+N'点'

+CAST(active_end_time%10000/100ASVARCHAR(2))+N'分'

WHENfreq_subday_type=2THENN'结束时间点:'

+CAST(active_end_time/10000ASVARCHAR(2))+N'点'

+CAST(active_end_time%10000/100ASVARCHAR(2))+N'分'

WHENfreq_subday_type=4THENN'结束时间点:'

+CAST(active_end_time/10000ASVARCHAR(2))+N'点'

+CAST(active_end_time%10000/100ASVARCHAR(2))+N'分'

WHENfreq_subday_type=8THENN'结束时间点:'

+CAST(active_end_time/10000ASVARCHAR(2))+N'点'

+CAST(active_end_time%10000/100ASVARCHAR(2))+N'分'

ENDASjob_end_time,

freq_type,

freq_interval,

freq_subday_type,

freq_subday_interval,

active_start_date,

active_start_time

FROMmsdb.dbo.sysscheduless

INNERJOINmsdb.dbo.sysjobschedulesdONs.schedule_id=d.schedule_id

INNERJOINmsdb.dbo.sysjobsjONd.job_id=j.job_id

ORDERBYj.name

[/code]
[/code]

如下测试案例,非常的清晰明了,一目了然。





2:业务场景:你想查看这个数据库实例有多少作业。

[code]--查看实例下被禁用的作业

SELECTj.job_idASJOB_ID

,j.nameASJOB_NAME

,CASEWHEN[enabled]=1THEN'Enabled'

ELSE'Disabled'ENDASJOB_ENABLED

,l.nameASJOB_OWNER

,j.category_idASJOB_CATEGORY_ID

,c.nameASJOB_CATEGORY_NAME

,[description]ASJOB_DESCRIPTION

,date_createdASDATE_CREATED

,date_modifiedASDATE_MODIFIED

FROMmsdb.dbo.sysjobsj

INNERJOINmsdb.dbo.syscategoriescONj.category_id=c.category_id

INNERJOINsys.sysloginslONl.sid=j.owner_sid

WHEREj.enabled=0

ORDERBYj.name

[/code]
[/code]

4:业务场景:你想查看有那些账号在运行那些作业,例如某个同事离职了,但是他的那个NT账号在运行一些作业,你需要修改作业的Owner,否则当系统管理员禁用这个NT账号后,这些作业就会出错。

[code]
[code]--查看某个Owner的作业

SELECTj.job_idASJOB_ID

,j.nameASJOB_NAME

,CASEWHEN[enabled]=1THEN'Enabled'

ELSE'Disabled'ENDASJOB_ENABLED

,l.nameASJOB_OWNER

,j.category_idASJOB_CATEGORY_ID

,c.nameASJOB_CATEGORY_NAME

,[description]ASJOB_DESCRIPTION

,date_createdASDATE_CREATED

,date_modifiedASDATE_MODIFIED

FROMmsdb.dbo.sysjobsj

INNERJOINmsdb.dbo.syscategoriescONj.category_id=c.category_id

INNERJOINsys.sysloginslONl.sid=j.owner_sid

WHEREl.name='Domain\UserName'

ORDERBYj.name

[/code]
[/code]

5:业务场景:你需要查看作业的具体步骤,例如作业执行的某个存储过程,或者有个同事想了解作业的运行情况,但是他不记得作业的名称,只知道这个作业执行了某个存储过程,那么就可以在下面SQL的基础上进行扩展。


[code]
[code]SELECTj.job_idASJOB_ID

,j.nameASJOB_NAME

,s.step_idASStep_Id

,s.commandASCommand

,CASEWHEN[enabled]=1THEN'Enabled'

ELSE'Disabled'ENDASJOB_ENABLED

,j.category_idASJOB_CATEGORY_ID

,c.nameASJOB_CATEGORY_NAME

,[description]ASJOB_DESCRIPTION

,date_createdASDATE_CREATED

,date_modifiedASDATE_MODIFIED

FROMmsdb.dbo.sysjobsj

INNERJOINmsdb.dbo.syscategoriescONj.category_id=c.category_id

INNERJOINmsdb.dbo.sysjobstepssONj.job_id=s.job_id

ORDERBYj.name,s.step_id

[/code]
[/code]

--查询那个作业执行了某个存储过程(因为有时候,忘记了作业名称,但是知道那个作业调用了某个存储过程,此时开发人员找你帮忙找到对应的作业,就可以通过下面SQL查找)


[code]
[code]SELECTj.job_idASJOB_ID

,j.nameASJOB_NAME

,s.step_idASStep_Id

,s.commandASCommand

,CASEWHEN[enabled]=1THEN'Enabled'

ELSE'Disabled'ENDASJOB_ENABLED

,j.category_idASJOB_CATEGORY_ID

,c.nameASJOB_CATEGORY_NAME

,[description]ASJOB_DESCRIPTION

,date_createdASDATE_CREATED

,date_modifiedASDATE_MODIFIED

FROMmsdb.dbo.sysjobsj

INNERJOINmsdb.dbo.syscategoriescONj.category_id=c.category_id

INNERJOINmsdb.dbo.sysjobstepssONj.job_id=s.job_id

WHEREs.commandLIKE'%procedure_name%'

[/code]
[/code]

6:业务场景:数据库迁移时,你想把属于这个数据库的作业也迁移走,但是那些作业是在这些数据库上面运行呢?可以通过下面SQL来查找。

---查看属于某个数据库的作业(根据作业脚本执行的数据库判定)


[code]
[code]SELECTj.job_idASJOB_ID

,j.nameASJOB_NAME

,CASEWHEN[enabled]=1THEN'Enabled'

ELSE'Disabled'ENDASJOB_ENABLED

,j.category_idASJOB_CATEGORY_ID

,c.nameASJOB_CATEGORY_NAME

,[description]ASJOB_DESCRIPTION

,date_createdASDATE_CREATED

,date_modifiedASDATE_MODIFIED

FROMmsdb.dbo.sysjobsj

INNERJOINmsdb.dbo.syscategoriescONj.category_id=c.category_id

WHEREjob_idIN(SELECTjob_id

FROMmsdb.dbo.sysjobsteps

WHEREdatabase_name='YourSQLDba')

ORDERBYj.name

[/code]
[/code]

7:业务场景:需要查看那些作业类型为“操作系统(CmdExec)"的作业。

--查看作业类型为“操作系统(CmdExec)"的作业


[code]
[code]SELECTj.job_idASJOB_ID

,j.nameASJOB_NAME

,CASEWHEN[enabled]=1THEN'Enabled'

ELSE'Disabled'ENDASJOB_ENABLED

,j.category_idASJOB_CATEGORY_ID

,c.nameASJOB_CATEGORY_NAME

,descriptionASJOB_DESCRIPTION

,date_createdASDATE_CREATED

,date_modifiedASDATE_MODIFIED

FROMmsdb.dbo.sysjobsj

INNERJOINmsdb.dbo.syscategoriescONj.category_id=c.category_id

WHEREEXISTS

(SELECT1FROMmsdb.dbo.sysjobstepssWHERE

j.job_id=s.job_idANDs.subsystem='CmdExec')

[/code]
[/code]

8:业务场景:需要查看今天或某个时间段内出错的作业。

--查询那些作业在今天出错(如果要查询历史出错作业,去掉查询时间条件即可)


[code]
[code]SELECTj.nameASJOB_NAME

,j.descriptionASJOB_Description

,j.date_createdASDate_Created

,j.date_modifiedASDate_Modified

FROMmsdb.dbo.sysjobsj

WHEREenabled=1

ANDEXISTS(

SELECT1

FROMMsdb.dbo.sysjobhistoryh

WHERErun_status=0

ANDj.job_id=h.job_id

ANDrun_date=CAST(CONVERT(VARCHAR(8),GETDATE(),112)ASINT))

[/code]
[/code]

---查看某个或所有作业的出错的历史记录信息


[code]
[code]SELECTj.nameASjob_name

,h.step_idASstep_id

,h.step_nameASjob_step_name

,h.sql_severityASsql_severity

,h.[message]ASerror_message

,h.run_dateASrun_date

,h.run_timeASrun_time

,h.run_durationASrun_duration

FROMmsdb.dbo.sysjobhistoryh

LEFTJOINmsdb.dbo.sysjobsjONh.job_id=j.job_id

WHERErun_status=0

--ANDj.job_name=''

ORDERBYj.name,h.run_date,h.run_time,h.step_id

[/code]
[/code]

9:业务场景:查看作业的执行时间信息。

--查询作业的运行时间,检查作业是否正常运行或存在问题。


[code]
[code]SELECTj.nameASJob_Name,

h.step_idASStep_Id,

h.step_nameASStep_Name,

h.messageASMessage,

h.run_dateASRun_Date,

h.run_timeASRun_Time,

msdb.dbo.agent_datetime(h.run_date,h.run_time)

AS'RunDateTime',

CAST(run_duration/10000ASVARCHAR(2))+N'小时'

+CAST((run_duration-run_duration/10000*10000)/100ASVARCHAR(2))+N'分钟'

+SUBSTRING(CAST(run_durationASVARCHAR(10)),

LEN(CAST(run_durationASVARCHAR(10)))-1,2)+N'秒'

ASrun_duration

FROMmsdb.dbo.sysjobhistoryh

LEFTJOINmsdb.dbo.sysjobsjONh.job_id=j.job_id

ORDERBYJob_Name,h.Step_Id

[/code]
[/code]


[code]
[code]SELECTj.nameASJob_Name,

h.step_idASStep_Id,

h.step_nameASStep_Name,

h.messageASMessage,

h.run_dateASRun_Date,

h.run_timeASRun_Time,

msdb.dbo.agent_datetime(h.run_date,h.run_time)

AS'RunDateTime',

CAST(run_duration/10000ASVARCHAR(2))+N'小时'

+CAST((run_duration-run_duration/10000*10000)/100ASVARCHAR(2))+N'分钟'

+SUBSTRING(CAST(run_durationASVARCHAR(10)),

LEN(CAST(run_durationASVARCHAR(10)))-1,2)+N'秒'

ASrun_duration

FROMmsdb.dbo.sysjobhistoryh

LEFTJOINmsdb.dbo.sysjobsjONh.job_id=j.job_id

WHERERun_Date=CAST(CONVERT(VARCHAR(8),GETDATE(),112)ASINT)--今天执行的作业

ANDh.run_status=1--执行成功

ORDERBYh.run_durationDESC

[/code]
[/code]

10:业务场景:查询作业运行时间超过某个阀值的所有作业。例如作业执行时间超过一分钟的作业

查询今天执行时间大于一分钟的作业


[code]
[code]SELECTj.nameASJob_Name,

h.step_idASStep_Id,

h.step_nameASStep_Name,

h.messageASMessage,

h.run_dateASRun_Date,

h.run_timeASRun_Time,

msdb.dbo.agent_datetime(h.run_date,h.run_time)

AS'RunDateTime',

CAST(run_duration/10000ASVARCHAR(2))+N'小时'

+CAST((run_duration-run_duration/10000*10000)/100ASVARCHAR(2))+N'分钟'

+SUBSTRING(CAST(run_durationASVARCHAR(10)),

LEN(CAST(run_durationASVARCHAR(10)))-1,2)+N'秒'

ASrun_duration

FROMmsdb.dbo.sysjobhistoryh

LEFTJOINmsdb.dbo.sysjobsjONh.job_id=j.job_id

WHERERun_Date=CAST(CONVERT(VARCHAR(8),GETDATE(),112)ASINT)--今天执行的作业

ANDh.run_status=1--执行成功

ANDh.run_duration>100--大于一分钟的作业

ORDERBYJob_Name,h.Step_Id

[/code]
[/code]

11:业务场景,查看正在执行的作业。


[code]
[code]SELECTjob.job_id,

job.name,

sa.run_requested_date,

sa.start_execution_date

FROMmsdb.dbo.sysjobs_viewjob

INNERJOINmsdb.dbo.sysjobactivitysaONjob.job_id=sa.job_id

--getonlythecurrentsession

INNERJOINmsdb.dbo.syssessionssONs.session_id=sa.session_id

INNERJOIN(SELECTMAX(agent_start_date)ASmax_agent_start_date

FROMmsdb.dbo.syssessions

)session_maxONs.agent_start_date=session_max.max_agent_start_date

WHEREsa.run_requested_dateISNOTNULL

ANDsa.stop_execution_dateISNULL;

[/code]
[/code]

12:业务场景,查看某个作业的详细信息。


[code]
[code]EXECmsdb.dbo.sp_help_job@Job_name='YourSQLDba_LogBackups'

[/code]
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: