{"id":150,"date":"2006-08-30T00:00:00","date_gmt":"2006-08-29T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/executing-ssis-packages\/"},"modified":"2021-06-03T16:45:31","modified_gmt":"2021-06-03T16:45:31","slug":"executing-ssis-packages","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/bi-sql-server\/executing-ssis-packages\/","title":{"rendered":"Executing SSIS Packages"},"content":{"rendered":"<div id=\"pretty\">\n<h2>Executing all SSIS packages in a folder: three methods<\/h2>\n<p>A common requirement is to execute several SSIS packages as part of one logical process. This is especially true when one is transferring existing data from an external system.<\/p>\n<p>If the indivisual packages are placed in a folder and named in such a way that a batch can be executed via a wildcard filemask, then they can be altered without changing any code, and can be used for different processes by changing the filemask. This article presents three different methods of executing all packages in a folder:<\/p>\n<ol>\n<li>SSIS control package<\/li>\n<li>Stored procedure<\/li>\n<li>DOS batch file<\/li>\n<\/ol>\n<p>The methods are of differing complexity and flexibility, the SSIS package being by far the most difficult to code, and the DOS command being by far the simplest but also the least flexible.<\/p>\n<p>The folder that contains the packages is <span class=\"ScreenText\">d<\/span><span class=\"ScreenText\">:\\TestPackages\\<\/span>.<\/p>\n<p>All the packages to be run have names of the format <span class=\"ScreenText\">t1&#8230;&#8230;.dtsx<\/span>.<\/p>\n<h3>SSIS control package<\/h3>\n<p>For this we create a package that uses a for each loop task to call an execute package task for all packages in the folder.<\/p>\n<p>The first task is to create an SSIS package with a Foreach Loop container that will loop round the packages in the folder, setting a variable called &#8220;PackageToRun&#8221; to the file name for each package.<\/p>\n<ol>\n<li>Load Business Intelligence Development Studio and start a SSIS project.<\/li>\n<li>Create a new package.<\/li>\n<li>Add a Foreach Loop container to the package.<\/li>\n<li>Right-click on the <strong>Foreach Loop<\/strong> container and select <b>Edit<\/b>.<\/li>\n<li>Click on <b>Collection<\/b>.<\/li>\n<li>Set the Enumerator to <b>Foreach File Enumerator<\/b>.<\/li>\n<li>In the Enumerator configuration:\n<ol>\n<li>Set <b>Folder<\/b> to &#8220;d:\\TestPackages\\&#8221;<\/li>\n<li>Set <b>Files<\/b> to &#8220;t1*.dtsx&#8221;<\/li>\n<li>Under <b>Retrieve file name<\/b> select <b>Fully qualified<\/b>.<\/li>\n<\/ol>\n<\/li>\n<li>Click <b>OK<\/b>.<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/270-image001.gif\" alt=\"270-image001.gif\" \/><\/p>\n<ol>\n<li>Click on <b>Variable Mappings<\/b>.<\/li>\n<li>Click on the <b>Variable<\/b> drop-down list and select <b>New Variable<\/b>.<\/li>\n<li>Set Name to <span class=\"ScreenText\">PackageToRun<\/span>.<\/li>\n<li>Click <b>OK<\/b>.<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/270-image002.gif\" alt=\"270-image002.gif\" \/><\/p>\n<p>Next, we need to add the <b>Execute Package<\/b> task to the Foreach Loop container so that this task will be executed for each package that we wish to run. We then set the variable value to be the name of the package to be executed by the <b>ExecutePackage<\/b> task.<\/p>\n<ol>\n<li>Drag an <b>Execute Package<\/b> task into the Foreach Loop container.<\/li>\n<li>Right-click on the <b>Execute Package<\/b> task and select <b>Edit<\/b>.<\/li>\n<li>Select <b>Package<\/b>.<\/li>\n<li>Set Location to <span class=\"ScreenText\">File system<\/span><\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/270-image003.gif\" alt=\"270-image003.gif\" \/><\/p>\n<ol>\n<li>Click on the <strong>Connection<\/strong> drop-down list and select <span class=\"ScreenText\">&lt;New connection&#8230;&gt;<\/span>.<\/li>\n<li>Set the File to an existing package.<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/270-image004.gif\" alt=\"270-image004.gif\" \/><\/p>\n<ol>\n<li>Click <b>OK<\/b> to save the connection.<\/li>\n<li>Click <b>OK<\/b> to complete the Execute Package task configuration.<\/li>\n<\/ol>\n<p>Finally, we configure the connection to use the variable package name:<\/p>\n<ol>\n<li>Right-click on the connection and select <b>Properties<\/b>.<\/li>\n<li>In the Properties window change the name to <span class=\"ScreenText\">PackageToRunConnection<\/span>.<\/li>\n<\/ol>\n<p><b><i>Note<\/i><\/b><i>: this will automatically update the connection name in the Execute Package Task.<\/i><\/p>\n<ol>\n<li>Select Expressions and add a new expression.<\/li>\n<li>In the property drop-down list select <b>ConnectionString<\/b>.<\/li>\n<li>Click on the <b>Expression Edito<\/b>r button.<\/li>\n<li>From the Variables tree drag <span class=\"ScreenText\">@[User::PackageToRun]<\/span> into the Expression window.<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/270-image005.gif\" alt=\"270-image005.gif\" \/><\/p>\n<ol>\n<li>Click <b>OK<\/b> twice, to save the expression.<\/li>\n<\/ol>\n<p>The package should now look like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/270-image006.gif\" alt=\"270-image006.gif\" \/><\/p>\n<p>If you now run the package, it will execute each package in the folder with the correct filename mask.<\/p>\n<h3>Stored Procedure<\/h3>\n<p>This involves the following steps:<\/p>\n<ol>\n<li>Retrieve a list of the package names to run from the folder<\/li>\n<li>Loop through each package name<\/li>\n<li>Execute each package<\/li>\n<\/ol>\n<p>First of all, we need to get a list of all packages in the folder. The following code executes the DOS command <b>dir \/B d:\\TestPackages\\ t1*.dtsx<\/b> and places the output in the temporary table <b>#dir<\/b>. The DOS command gets a list of the filenames in the folder which satisfy the filemask.<\/p>\n<pre>Create table #dir (Filename varchar(1000))\r\nInsert #dir\r\nExec master..xp_cmdshell 'dir \/B d:\\TestPackages\\ t1*.dtsx'\r\ndelete #dir where Filename is null or Filename like '%not found%'<\/pre>\n<p>The following is a useful technique for looping through values in a table and here we use it to loop through the filenames in <b>#dir<\/b>:<\/p>\n<pre>Declare @Filename varchar(1000)\r\nSelect @Filename = ''\r\nWhile @Filename &lt; (select max(Filename) from #dir)\r\nBegin\r\n\u00a0\u00a0 Select @Filename = min(Filename) from #dir where Filename &gt; @Filename\r\nend<\/pre>\n<p>Now we just need to create the command to execute the package:<\/p>\n<pre>Declare @cmd varchar(1000)\r\nselect @cmd = 'dtexec \/F \" d:\\TestPackages\\' + @FileName + '''\r\nexec master..xp_cmdshell @cmd\r\n<\/pre>\n<p>This takes the package name and uses the <strong>dtexec<\/strong> command to execute it. Putting this all together, we get:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">Declare @Filename varchar(1000)\r\nDeclare @cmd varchar(1000)\r\nCreate table #dir (Filename varchar(1000))\r\nInsert #dir\r\nExec master..xp_cmdshell 'dir \/B d:\\TestPackages\\t1*.dtsx'\r\ndelete #dir where Filename is null or Filename like '%not found%'\r\nSelect @Filename = ''\r\nWhile @Filename &lt; (select max(Filename) from #dir)\r\nBegin\r\n\u00a0\u00a0 Select @Filename =\u00a0 min(Filename) from #dir where Filename &gt; @Filename\r\n\u00a0\u00a0 select\u00a0 @cmd =\u00a0 'dtexec \/F \"d:\\TestPackages\\' + @Filename + '\"'\r\n\u00a0\u00a0 exec master..xp_cmdshell @cmd\r\nend\r\ndrop table #dir\r\n<\/pre>\n<p>The above completes the code needed for the requirement but to simplify the implementation I like to keep a utility stored procedure which calls another stored procedure for each file (SSIS package) in a folder. The following utility stored procedure, <b>ProcessAllFilesInDir<\/b>, uses the above techniques to obtain a list of files from a folder and calls another stored procedure for each one. The file path and mask are input as parameters together with the <b>@ProcSP<\/b> parameter that defines the stored procedure to be called for each file (in this case this will be the <b>ExecutePackage<\/b> procedure that executes each SSIS package).<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">Create procedure [dbo].[s_ProcessAllFilesInDir]\r\n@FilePath varchar(1000) ,\r\n@FileMaskvarchar(100) ,\r\n@ProcSp varchar(128)\r\nas\r\n\u00a0\u00a0 set nocount on\r\n\u00a0\u00a0 \r\ndeclare @File varchar(128) ,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 @MaxFile varchar(128) ,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 @cmd\u00a0\u00a0\u00a0\u00a0 varchar(2000)\r\n\u00a0\u00a0 \r\n\u00a0\u00a0 create table #Dir (s varchar(8000))\r\n\u00a0\u00a0 \r\n\u00a0\u00a0 select @cmd = 'dir \/B ' + @FilePath + @FileMask\r\n\u00a0\u00a0 insert #Dir exec master..xp_cmdshell @cmd\r\n\u00a0\u00a0 \r\n\u00a0\u00a0 delete #Dir where s is null or s like '%not found%'\r\n\u00a0\u00a0 \r\n\u00a0\u00a0 select @File = '', @MaxFile = max(s) from #Dir\r\n\u00a0\u00a0 while @File &lt; @MaxFile\r\n\u00a0\u00a0 begin\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 select @File = min(s) from #Dir where s &gt; @File\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 select @cmd = @ProcSp + ' ''' + @FilePath + ''' , ''' + @File + ''''\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 exec (@cmd)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \r\n\u00a0\u00a0 end\r\n\u00a0\u00a0 drop table #Dir\r\ngo\r\n<\/pre>\n<p>With this, the only coding needed is to create the procedure to execute the package and to call it. The <b>ExecutePackage<\/b> procedure is as follows:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">\t\tCreate procedure [dbo].[s_ExecutePackage]\r\n@FilePath\u00a0\u00a0 varchar(1000) ,\r\n@Filename\u00a0\u00a0 varchar(128)\r\nas\r\nDeclare @cmd varchar(1000)\r\n\u00a0\u00a0 select @cmd =\u00a0 'dtexec \/F \"' + @FilePath + @Filename + '\"'\r\n\u00a0\u00a0 exec master..xp_cmdshell @cmd\r\ngo\r\n<\/pre>\n<p>And the call:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">Exec [dbo].[s_ProcessAllFilesInDir]\r\n\u00a0\u00a0 @FilePath = 'd:\\TestPackages\\' ,\r\n\u00a0\u00a0 @FileMask = 't1*.dtsx' ,\r\n\u00a0\u00a0 @ProcSp = '[dbo].[s_ExecutePackage]'\r\n<\/pre>\n<h3>DOS batch file<\/h3>\n<p>The DOS command required is <b>dtexec \/F &#8220;d:\\TestPackages\\mypackagename<\/b><b>&#8220;<\/b> as above. We can make use of a DOS For loop to execute this command for all files in a folder:<\/p>\n<pre>for %1 in (d:\\TestPackages\\t1*.dtsx) do dtexec \/F \"%1\"<\/pre>\n<p>This uses the for loop construct:<\/p>\n<ul>\n<li><b>(d:\\TestPackages\\t1*.dtsx) <\/b>returns a list of the files which meet the path (similar to a dir command).<\/li>\n<li><b>For %1 in (d:\\TestPackages\\t1*.dtsx)<\/b> loops through the file list setting the variable %1 to the filename.<\/li>\n<li><b>Do dtexec \/F %<\/b> executes <b>dtexec \/F<\/b> with each filename in turn.<\/li>\n<\/ul>\n<p>Note that you can place this command in a <b>bat<\/b> file to execute.<\/p>\n<h2>Summary<\/h2>\n<p>We have introduced three different methods of executing all packages in a folder. The methods are of differing complexity, the SSIS control package being by far the most difficult to code, and the DOS command by far the simplest.<\/p>\n<p>There are a few things missing from the solutions presented which would (or should) prevent them from being used in a production system. At a minimum this should include logging and error handling. The start and end time of each package execution should be logged by the control process and also errors should be detected and logged.<\/p>\n<p>At first sight, it may seem that the <b>DOS comman<\/b>d is the one that we should be using, but this method loses a lot of flexibility. There is much you can do with batch files, but not many people have skills in writing such code beyond very simple commands, so you can quickly end up with an un-maintainable system.<\/p>\n<p>The <b>stored procedure<\/b> solution gives a lot of flexibility &#8211; it is easy to add logging and pre\/post processing to the process. However, it does require an installation of SQL Server. Although this process would usually be run via SQL Server, it may sometimes need to be run on a client machine (or not involve SQL Server at all); this is quite difficult with a stored procedure as it is server based whereas the other two solutions are client applications.<\/p>\n<p>The <b>SSIS solution<\/b> keeps the process within SSIS, so you can take advantage of the integration of package processing, e.g. inheritance of properties from the calling package, development and debugging of packages, within the development studio.<\/p>\n<p>Overall, none of these solutions is very difficult to implement, so the decision which to use will probably depend on the experience of the developer, how much flexibility is required, and the environment in which it is to be run.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Nigel Rivett demonstrates how to execute all SSIS packages in a given folder using either an SSIS control package, a stored procedure or a DOS batch file.&hellip;<\/p>\n","protected":false},"author":223267,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143528],"tags":[4405,4179,4150,4404,4306],"coauthors":[48340],"class_list":["post-150","post","type-post","status-publish","format-standard","hentry","category-bi-sql-server","tag-package-execution","tag-source-control","tag-sql","tag-sql-server-2005-integration-services","tag-ssis"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/150","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/223267"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=150"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/150\/revisions"}],"predecessor-version":[{"id":74762,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/150\/revisions\/74762"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=150"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=150"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=150"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=150"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}