SQL Server scheduling by script - sql-server

I created a job to execute a procedure every 5 minutes but the job has no history of being run and also when I execute exec sp_help_jobactivity #job_name = 'Update Subscription flags', I get empty result. I also checked sysjobschecdules that has 0 for next_run_date and time. My procedure is compiled and works fine when i execute it manually. I'm not sure what exactly is wrong here. Here's the schedule:
--Add a Job to SQL Server Agent
GO
EXEC msdb.dbo.sp_add_job
#job_name = N'Update Subscription flags'; -- the job name
GO
GO
EXEC msdb.dbo.sp_add_jobstep
#job_name = N'Update Subscription flags' -- Job name specified in sp_add_job
,#step_name = N'Step - Set subscription flags to false' -- step name
,#database_name = 'db' --Database Name
,#command = N'EXEC UpdateSubscriptionFlags;' -- SQL Command
GO
--Attach server name. Not needed if you are creating job on same server.
EXEC msdb.dbo.sp_add_jobserver
#job_name = N'Update Subscription flags'
,#server_name = N'DESKTOP-3DR2LAE\SQLEXPRESS'; -- LOCAL by default
GO
GO
EXEC msdb.dbo.sp_add_schedule
#schedule_name = N'Daily - Every 5 Minutes' -- specify the schedule name
,#freq_type = 4 -- 4 indicates job is scheduled daily, refer msdn link for reference
,#freq_interval = 1 -- The days that a job is executed and depends on the value of
,#freq_subday_type = 4 --At specified time (At specific time/second/minutes/hours)
,#freq_subday_interval = 5 --Run every 5 min once the job is scheduled
GO
--Attach Created Job name to Schedule name
GO
EXEC msdb.dbo.sp_attach_schedule
#job_name = N'Update Subscription flags' -- Job Name
,#schedule_name = N'Daily - Every 5 Minutes' ; -- Schedule Name
GO

Related

How do I look at SQL Agent Job without starting SQL Agent?

I have just set up a new SQL Server instance on a new server and moved our application to use the new server. So I've had to turn SQL Agent off on the old server - turning it on would start the scheduler and start sending out emails and running things that shouldn't be run any more.
However, I need to take a close look at a SQL Agent Job on the old server, and ideally reverse-engineer the code to recreate it so I can modify it and apply it to the new server.
How do I generate the code for that Job on the old server without turning SQL Agent on?
Thanks
Even if SQL server agent is not running, you can see how jobs and schedules were set up by viewing the following system DMVs.
msdb.dbo.sysjobs_view
msdb.dbo.sysjobs
msdb.dbo.sysjobschedules
msdb.dbo.sysschedules
I use preset scripts to create all my jobs and schedules independent of the server. Here is a sample script to create the recycle log job. You can modify this or use any piece of this as you see fit.
DECLARE #sql nvarchar(max)
BEGIN TRY
IF EXISTS (SELECT job_id
FROM msdb.dbo.sysjobs_view
WHERE name = N'Cycle SQL log')
EXEC msdb.dbo.sp_delete_job #job_name=N'Cycle SQL log'
, #delete_unused_schedule=1
EXEC msdb.dbo.sp_add_job
#job_name = N'Cycle SQL log',
#description = N'This job forces SQL to start a new error log (In the Managment node of SSMS)',
#owner_login_name = N'your_sql_login' ;
EXEC msdb.dbo.sp_add_jobstep
#job_name = N'Cycle SQL log',
#step_name = N'sp_cycle_errorlog',
#subsystem = N'TSQL',
#command = N'exec sp_cycle_errorlog' --put your executable code here
--These next two lines set the target server to local, so that the job can be modified if necessary
SET #sql = 'EXEC msdb.dbo.sp_add_jobserver #job_name=N''Cycle SQL Log'', #server_name = N''' + ##SERVERNAME + ''''
EXEC sys.sp_executesql #stmt = #sql
END TRY
BEGIN CATCH
PRINT 'Uh-oh. Something bad happened when creating the Cycle SQL Log job. See the following error.'
PRINT CAST(ERROR_MESSAGE() AS NVARCHAR(1000))
END CATCH
You can use use code to automate the addition of schedules based on values you pull from the DMVs listed above.

Parameterize sp_add_jobstep for SSIS

From a TSQL Stored Procedure, I want to use the sp_add_jobstep stored procedure in the msdb database to create an SQL Agent job, which calls an SSIS package. I need to do this programmatically to dynamically set one of the parameters in the SSIS package at time of Job creation. In the "SQL Server Agent>Jobs>New Job" GUI, this is done under the "Steps>Edit>Configuration>Parameters" screen. How does one assign parameters with the sp_add_jobstep Stored Procedure?
The Microsoft documentation: https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-add-jobstep-transact-sql
does not explain this.
Related posts:
This post shows how to create an Agent job in T-SQL or C#: Create SQL Server Agent jobs programatically
And this post shows the SSIS syntax but does not discuss parameters: How do I create a step in my SQL Server Agent Job which will run my SSIS package?
As noted in the response by SAS, the params have to be passed as part of the command. The documentation for sp_add_jobstep shows a parameter called #additional_parameters, but notes this is not supported. So, while I didn't script it out (which would have been quicker), I did make an example job & then query the msdb.dbo.sysjobsteps table to see the format of the command. Based on that, and the earlier post by CSharper, I wrote the following stored procedure:
CREATE PROCEDURE [dbo].[CreateAgentjobHourlySSIS]
#job NVARCHAR(128),
#package NVARCHAR(max), -- \SSISDB\MyCatalog\MyProject\MyPackage.dtsx
#params NVARCHAR(max), -- /Par "\"$Project::MyParameter\"";ParameterValue /Par "\"$ServerOption::LOGGING_LEVEL(Int16)\"";1 /Par "\"$ServerOption::SYNCHRONIZED(Boolean)\"";True
#servername NVARCHAR(28),
#startdate DATE,
#starttime TIME,
#frequencyhours INT
AS
BEGIN TRY
BEGIN TRAN
--GRANT EXEC on CreateAgentjobHourlySSIS to PUBLIC
--1. Add a job
EXEC msdb.dbo.sp_add_job
#job_name = #job
--2. Add a job step named process step. This step runs the stored procedure
DECLARE #SSIScommand as NVARCHAR(max)
SET #SSIScommand = '/ISSERVER "\"'+#package+'\"" /SERVER "\"'+#servername+'\"" '+#params+' /CALLERINFO SQLAGENT /REPORTING E'
EXEC msdb.dbo.sp_add_jobstep
#job_name = #job,
#step_name = N'process step',
#subsystem = N'Dts',
#command = #SSIScommand
--3. Schedule the job starting at a specified date and time
DECLARE #startdateasint int = YEAR(#startDate)*10000+MONTH(#startdate)*100+DAY(#startdate)
DECLARE #starttimeasint int = DATEPART(HOUR,#starttime)*10000+DATEPART(MINUTE,#starttime)*100+DATEPART(SECOND,#starttime)
EXEC msdb.dbo.sp_add_jobschedule #job_name = #job,
#name = 'Hourly Schedule',
#freq_type = 4, --daily
#freq_interval = 1,
#freq_subday_type = 0x8, -- hourly
#freq_subday_interval = #frequencyhours,
#active_start_date = #startdateasint,
#active_start_time = #starttimeasint
--4. Add the job to the SQL Server
EXEC msdb.dbo.sp_add_jobserver
#job_name = #job,
#server_name = #servername
COMMIT TRAN
END TRY
BEGIN CATCH
SELECT ERROR_Message(), ERROR_Line();
ROLLBACK TRAN
END CATCH
You construct the call like this:
#command=N'/ISSERVER "
...
/Par "\"$Project::MyParam\"";ParamValue
...
If you already have a similar job you can right-click in SSMS and script it out.
That will show you the syntax.

Schedule Script for SQL Jobs

How to schedule a SQL Jobs using SQL Script.I have around 80 SQL jobs. I want to schedule all my SQL jobs and get details of Job scheduled jobs using script.
SELECT *
FROM [msdb].[dbo].[sysjobschedules]
The above query only gives me list of schedule jobs, but does not provide any way to schedule a SQL Job. I am looking for a generalized script to Schedule SQL job in Database. How do I do it?
try this
USE msdb ;
GO
EXEC sp_add_schedule
#schedule_name = N'NightlyJobs' ,
#freq_type = 4,
#freq_interval = 1,
#active_start_time = 010000 ;
GO
EXEC sp_attach_schedule
#job_name = N'BackupDatabase',
#schedule_name = N'NightlyJobs' ;
GO
EXEC sp_attach_schedule
#job_name = N'RunReports',
#schedule_name = N'NightlyJobs' ;
GO
sp_add_schedule
simple-way-to-create-a-sql-server-job-using-tsql
generate-sql-agent-job-schedule-report
create-MS-SQL-Server-agent-jobs-and-schedule
I would use this built-in proc to do this:
sp_add_schedule
Here is what the proc does:
1) Creates a schedule with the specified parameters and returns the
schedule id
2) Attaches the schedule to an existing job.
Sample Code:
declare #start_date varchar(8) = convert(varchar(8), DATEADD(day,1,GETDATE()), 112)
EXEC sp_add_schedule
#schedule_name = N'SomeName',
#freq_type = 1,
#active_start_date = #start_date,
#active_start_time = 010000;
Also, you could use this query to find your current job schedules info:
SELECT * FROM msdb.dbo.sysschedules;
Hope this helps!
sorry, misread the question.
how about something like that:
EXEC msdb.dbo.sp_add_jobschedule #job_id=N'yourjobid',#name=N'TestSchedule1',
#enabled=1,
#freq_type=8, -- 4 - daily, 8 - weekly
#freq_interval=2, --for weekly jobs 2 is Monday, 4 is Tuesday etc.
#freq_subday_type=1,
#freq_subday_interval=0,
#freq_relative_interval=0,
#freq_recurrence_factor=1,
#active_start_date=20150729,
#active_start_time=0,
schedule_id=#schedule_id
GO
or use sp_add_schedule for SQL Server 2014 and 2016. SQL 2012 and below - use sp_add_jobschedule

SQL Job with TRY reports success on failure when inserting from remote SP

I've found a way to fail a SQL Scheduled Job (with severity 16) that does not report failure (and so does not send email notifications). I've fixed my immediate issue, but I want to know why there is a failure case that does not report as failure, and if there are any other surprising ways to miss notification.
I've set up two linked servers and am attempting to run an hourly scheduled SQL Job on one that queries the other. I found this morning that the code in the SP had not been running, but the history on the Job was reporting success. The Job's only step is EXEC _testSP. If I ran EXEC _testSP in a query window from SSMS, I received this error message:
Msg 0, Level 11, State 0, Line 0 A severe error occurred on the
current command. The results, if any, should be discarded.
The SP's contents are wrapped in TRY ... CATCH. If I remove the TRY ... CATCH, executing the SP gives up this error message:
Msg 213, Level 16, State 7, Line 1
Insert Error: Column name or number of supplied values does not match table definition.
This made sense. The remote table was referenced with a SELECT * FROM and some columns had been added to it. I've removed the asterix and the job runs fine now, but I want to make sure that all future exceptions get logged either by the job failure notification, or the CATCH block in _testSP. I don't understand why this one didn't get logged, and I hope that someone can explain it to me.
The job runs and fails and notifies just as I would expect when the TRY ... CATCH wrapping is removed, but we have some important things in the TRY ... CATCH that need to be kept.
This is not a duplicate of this related question. The Microsoft BOL for TRY...CATCH says that some exceptions cannot be caught by TRY...CATCH. It may be related, but what I've found is an exception that is not caught by the Scheduled Job agent.
Reproduceable example: (also try removing the TRY...CATCH wrapper and see the change)
USE [RemoteServer].[Database]
CREATE TABLE [Tally](
[ID] [int] IDENTITY(0,1) NOT NULL,
[ID2] [int] NOT NULL
) ON [PRIMARY]
GO
USE [LocalServer]
-- Setup procedure
CREATE PROCEDURE _testSP
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
-- Create destination temp table
CREATE TABLE #tempb (a int)
-- Insert into temp table from remote Tally table
DECLARE #query nvarchar(4000)
SELECT #query = '
SELECT TOP 5 *
FROM [Database].[dbo].Tally
'
INSERT INTO #tempb
EXEC [RemoteServer].[master].[dbo].sp_executesql #query
END TRY BEGIN CATCH
-- Log the exception
-- ...
-- Rethrow the exception
DECLARE #ErrorMessage nvarchar(max), #ErrorSeverity int, #ErrorState int;
SELECT
#ErrorMessage = 'Handled Exception: ' + ERROR_MESSAGE() + ' line ' + CAST(ERROR_LINE() as nvarchar(5)),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
RAISERROR (#ErrorMessage, #ErrorSeverity, #ErrorState);
END CATCH
END
GO
-- Setup job
DECLARE #database varchar(100)
SELECT #database = DB_Name()
EXEC msdb.dbo.sp_add_job
#job_name = '_testSPJob'
EXEC msdb.dbo.sp_add_jobstep
#job_name = '_testSPJob',
#step_name = '_testSPJob',
#subsystem = N'TSQL',
#command = 'EXEC _testSP',
#database_name = #database
EXEC msdb.dbo.sp_add_jobserver
#job_name = '_testSPJob',
#server_name = ##SERVERNAME
GO
-- Manual execution fails
EXEC _testSP
GO
-- Run job
EXEC msdb.dbo.sp_start_job
#job_name = '_testSPJob'
WAITFOR DELAY '00:00:02'
GO
-- Select job history
SELECT * FROM msdb.dbo.sysjobhistory
WHERE step_name = '_testSPJob'
ORDER BY run_date, run_time
GO
I really need to convince the bosses to get off SQL 2000. Here are my software versions. Perhaps this is fixed in later versions of SQL?
SSMS Version: 2012 (11.0.5058.0)
Local DB: SQL 2005 (9.0.5069)
Remote DB: SQL 2000 (8.0.760)
I think that what is happening is correct, because you're handdling an exception, so the job is not failling. A solution could be a log so when the exception y catch you insert a row with the error description.

How to automatically run SQL agent job upon failure of other job

I have a stored procedure that gets a job name as input and send mail with job history information.
How can I automatically runs this job when other jobs fail?
Is there a way to pass the name (or ID) of the job to this stored procedure?
Thanks
You can use SQL Agent tokens to get the name or ID of the currently executing job (http://technet.microsoft.com/en-us/library/ms175575(v=sql.105).aspx).
To set this up, do the following:
Add new step "Email job history" to the end of your job
Change each job step to have an "OnFailure" action of "Go to step: {n} Email job history", where {n} is the step # of the step added above.
Use the SQL Agent tokens to get your currently executing JOBID and any other info you need. Example of "Email job history" T-SQL step below, where msdb.dbo.usp_SQLAgentSendJobStepFailedEmail would be your procedure name:
Example of "Email job history" T-SQL step:
DECLARE #jobid uniqueidentifier, #run_date int, #run_time int, #profile_name sysname;
set #profile_name = 'MyDatabaseMailProfileName';
--USE SQL AGENT "TOKENS" TO GET CURRENT JOB PARAM VALUES
set #jobid = $(ESCAPE_NONE(JOBID));
set #run_date = $(ESCAPE_NONE(STRTDT));
set #run_time = $(ESCAPE_NONE(STRTTM));
EXEC msdb.dbo.usp_SQLAgentSendJobStepFailedEmail #jobid = #jobid, #run_date = #run_date, #run_time = #run_time, #email_profile_name = #profile_name;

Resources