Importing/Exporting Data  «Prev  Next»

Lesson 8 SQL Server Agent
Objective Scheduling and running a package with SQL Server Agent

Scheduling a Package with SQL Server Agent in SQL Server 2025

SQL Server gives you the ability to schedule when a package runs, rather than kicking it off by hand every time. In SQL Server 2025, four tools cover most of the ways an SSIS package actually gets scheduled.

1. SQL Server Agent

SQL Server Agent is the most common and recommended way to schedule an SSIS package. It lets you:

  • Create jobs with multiple steps.
  • Add a step that runs an SSIS package.
  • Schedule the job to run on a recurring basis, daily, weekly, or whatever the task needs.
  • Monitor job history and execution status.

To schedule a package using SQL Server Agent:

  1. Open SQL Server Management Studio (SSMS).
  2. Navigate to SQL Server Agent > Jobs.
  3. Create a new job.
  4. Add a job step of type "SQL Server Integration Services Package."
  5. Select the package from the SSISDB catalog or the file system.
  6. Define the schedule under the Schedules page.
  7. Save and enable the job.
2. SSISDB + SQL Server Agent

Packages deployed to the SSISDB catalog, the project deployment model this course has already covered, get two benefits when scheduled through SQL Server Agent: richer logging and parameter handling than running a loose file ever provides, and visibility through the Integration Services Dashboard in SSMS. The dashboard shows an overview report of recent executions across every package in the catalog, and drilling into any one of them opens an execution performance report with the step-by-step timing and status that would otherwise mean piecing together job history by hand.

3. dtexec and Task Scheduler

dtexec, already introduced in this course, can run a package from PowerShell or a batch file, which Windows Task Scheduler can then trigger on its own schedule:

Start-Process "dtexec" -ArgumentList '/f "C:\Packages\MyPackage.dtsx"'

/f, or its long form /File, points at a package on the file system. A package sitting in the SSISDB catalog instead uses /Server for the instance plus /ISServer for the package's path inside the catalog, and a package stored the older way in msdb uses /Server plus /SQL. This path matters specifically because SQL Server Agent isn't included in SQL Server Express Edition, a licensing limitation rather than a bug, so a package running on Express has no Agent to schedule it through. Task Scheduler calling dtexec directly is the practical substitute in that one case, not a general-purpose alternative to Agent on an edition that already has it.

4. Azure Data Factory

For a package lifted into Azure, Azure Data Factory pipelines can orchestrate and schedule its execution through the Azure-SSIS Integration Runtime, the same lift-and-shift path this course has already covered as the first step many teams take before considering a native Fabric Data Factory rebuild.

Summary
Tool Use Case
SQL Server AgentPrimary scheduling method
SSISDB + SQL Server AgentManaged deployment and scheduling
Task Scheduler + dtexecLightweight or Express deployments
Azure Data FactoryCloud-integrated scheduling

Choosing a Scheduling Method

For most SQL Server 2025 deployments running Standard or Enterprise edition, SQL Server Agent scheduling a package from the SSISDB catalog is the right default: it's the option with the richest logging, the one that integrates with parameters and environments the way this course covered when it introduced the catalog, and the one every other DBA working on the same instance will expect to find a scheduled job in. Task Scheduler plus dtexec earns its place only where Agent genuinely isn't available, Express Edition being the common case, or occasionally where a package needs to run as part of a broader Windows automation sequence that Task Scheduler already manages for other, non-SQL-Server reasons. Azure Data Factory becomes the right answer once the package, or the data it touches, has actually moved to Azure; reaching for it while everything still runs on-premises just adds a dependency on infrastructure the package doesn't need yet.


SQL Server Agent job step

The following procedure automates the execution of a package by using a SQL Server Agent job step to run it.

To automate package execution by using SQL Server Agent
  1. In SQL Server Management Studio, connect to the instance of SQL Server on which you want to create a job, or the instance that contains the job to which you want to add a step.
  2. Expand the SQL Server Agent node in Object Explorer and perform one of the following tasks:
    1. To create a new job, right-click Jobs and then click New Job.
    2. To add a step to an existing job, expand Jobs, right-click the job, and then click Properties.
  3. On the General page, if you are creating a new job, provide a job name, select an owner and job category, and, optionally, provide a job description.
  4. To make the job available for scheduling, select Enabled.
  5. To create a job step for the package you want to schedule, click Steps, and then click New.
  6. Select Integration Services Package for the job step type.
  7. In the Run as list, select SQL Server Agent Service Account or select a proxy account that has the credentials that the job step will use.

Service Account or Proxy Account

Running a job step as the SQL Server Agent service account means the step inherits whatever that service account can already do, which is often broader than what the step itself actually requires. A proxy account narrows that down to only the credentials the package needs for its own connections, the same least-privilege principle this course has already applied to bulk-load credentials and Azure Blob Storage access: grant the step what it needs to run, not whatever the service account happens to already have. Running under a proxy account also resolves a category of permission errors that otherwise show up only when a package runs under the Agent service account, since that account's own permissions don't always line up with what an individual package's connections expect, an OLE DB connection manager authenticating with a specific Microsoft Entra ID identity, for instance, the same authentication options this course covered when it introduced SSIS's connection managers.

Who Can Manage SQL Server Agent Jobs

Access to Agent jobs doesn't depend on broad server-level permissions the way some of the permissions this course already covered do; it runs through three fixed database roles inside msdb specifically, each one layered on top of the last:

  • SQLAgentUserRole, the least privileged: create, edit, and delete only the jobs and schedules a member owns, with no visibility into anyone else's jobs at all.
  • SQLAgentReaderRole: everything SQLAgentUserRole can do, plus viewing every local job, schedule, and job history entry on the instance, including jobs owned by someone else, though still without the ability to run, edit, or stop those jobs.
  • SQLAgentOperatorRole, the most privileged of the three: everything the first two roles allow, plus the ability to start, stop, enable, and disable any local job and purge its history, without actually being able to edit someone else's job definition or change who owns it.

A member of sysadmin bypasses all three and has full control regardless. For a package like the nightly load built later in this lesson, membership in SQLAgentOperatorRole is usually the right fit for whoever needs to restart a failed run or temporarily disable the job during maintenance, without handing that person the broader database permissions this course covered earlier in this module.

Defining the Schedule

Back on the Schedules page, a new schedule offers a few distinct shapes rather than one generic recurrence setting: recurring on a frequency (daily, weekly on specific days, or monthly), one time only at a specific date and time, automatically whenever SQL Server Agent itself starts, which is useful for a package that should run once after a server restart, or whenever the CPU becomes idle, rarely the right choice for a data load but occasionally useful for a low-priority maintenance task that shouldn't compete with real workload. A daily load feeding a reporting table ahead of business hours is the common case: recurring daily, a start time early enough that the load finishes well before anyone needs the data, and, if the environment calls for it, an end date far enough in the future that the job doesn't quietly stop running because someone picked a default that expired. A "Repeat every" setting inside a daily or weekly recurrence can also run the job every few minutes or hours within a defined window, useful for a package that polls a drop folder for a new file throughout the business day rather than running once on a fixed clock.

Handling Success and Failure

A job step's Advanced page controls what happens next depending on whether the step succeeds or fails: go on to the next step, quit the job reporting success, or quit the job reporting failure. Chaining a validation step after the package itself, a quick row-count check against the table the package just loaded, the same kind of check this course has applied after every loading method covered so far, catches a package that completed without error but still didn't actually load anything, which an SSIS package's own execution status won't always surface on its own. On failure, a job can also notify an operator by email, page, or a Windows Application Event Log entry, configured on the Notifications page of the job's properties, so a nightly load failing at 2 a.m. doesn't go unnoticed until someone happens to check in the morning.

Operators and Database Mail

The email notification mentioned above depends on two pieces being set up ahead of time, neither of which is automatic. An operator, configured once under SQL Server Agent > Operators, is simply a named alias, Database Team, say, mapped to one or more email addresses; a job's Notifications page then points at that operator rather than at a hard-coded address, so the destination can change without editing every job that uses it. Sending that email at all requires Database Mail configured on the instance first, a mail profile with a working SMTP account, since SQL Server Agent has no mail capability of its own and relies entirely on Database Mail to actually send anything. A job with a notification configured but no working Database Mail profile behind it fails silently in exactly the way the notification was supposed to prevent, so it's worth testing with sp_send_dbmail directly before trusting a job's failure notification in production.

Job History and Logging

Two separate logs cover a scheduled package, and they answer slightly different questions. The Agent job's own history, viewed by right-clicking the job and choosing View History, shows whether the job step itself started, succeeded, or failed, and how long it ran, the same level of detail this course already relied on for any other job step. For what actually happened inside the package while it ran, the SSISDB catalog's own execution details, covered when this course introduced the catalog, go a level deeper: which task failed, what the actual error message said, and how long each step inside the package took, through views like catalog.executions and catalog.operation_messages. A job step that reports simple failure in Agent's history is the signal to go look at the catalog's own logging next, not the full explanation on its own.

Chaining Multiple Steps

A single job isn't limited to one step. A job built around the load-then-validate pattern this course has applied to every loading method covered so far can use one step to run a package that loads a staging table, a second step, an Execute SQL Task or a plain T-SQL job step, to validate row counts and data quality against that staging table, and a third to run the package, or stored procedure, that merges validated rows into the final table. Each step's own on-success and on-failure actions control whether the job moves to the next step, stops, or runs a different step entirely, making the same staging-then-merge discipline this module has applied to individual statements into something that runs unattended, start to finish, on its own schedule.

A Worked Example

Putting this together against the ETL_SalesData_Import package this course built in the previous lesson: a new job named Nightly SalesOrders Import, a single step of type Integration Services Package pointing at that package's path inside the SSISDB catalog, running under a proxy account scoped to exactly the source and destination connections the package actually uses, and a daily schedule starting at 1:00 AM. The step's Advanced page is set to quit the job reporting failure if the package itself fails, and a notification on the job's Notifications page emails the team's shared operator account when that happens. From that point on, the load this course originally wrote as a single statement, then rebuilt as an orchestrated package, now also runs on its own every night without anyone needing to remember to start it.

The morning after the first scheduled run, checking the job is a two-part habit, not a one-glance confirmation: View History on the job itself confirms the Agent step ran and reported success, and a quick look at the catalog's execution report, or a plain row-count check against SalesOrdersArchive, confirms the package actually did what it was supposed to rather than simply finishing without error. The gap between "the job succeeded" and "the data is actually right" is exactly why this course has insisted on that same validation step after every other loading method, and an unattended schedule is no reason to stop checking it.

Scaling Beyond One Server

Everything covered so far assumes one job on one instance. For an environment managing the same job, or a family of related jobs, across many SQL Server instances, SQL Server Agent also supports a multiserver administration model: one instance acts as a master server (MSX), and other instances enroll as target servers (TSX), downloading jobs from the master and reporting status back to it. It's a heavier setup than this lesson's worked example needs, and most environments never touch it, but it's the answer when "schedule this one package on this one server" turns into "run the same job across twenty servers without configuring each one by hand."


This lesson closes out the module's coverage of importing and exporting data: from a single INSERT statement, through SELECT INTO, BULK INSERT, and bcp, to a full SSIS package built in SSDT and now scheduled to run on its own. The DP-300 (Azure Database Administrator Associate) skills outline, referenced at several points across this module under planning and implementing a migration strategy, ultimately describes exactly this arc: not one correct tool, but the judgment to pick the right one for a given job and the discipline to make it run reliably once it's picked. A one-off load earns a single statement; a load that needs to happen every night, unattended, with a record of whether it worked, earns everything this lesson covered to get it there.
SEMrush Software 8 SEMrush Banner 8