{"id":1292,"date":"2012-02-16T00:00:00","date_gmt":"2012-02-16T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/exploring-ssis-architecture-and-execution-history-through-scripting\/"},"modified":"2021-06-03T16:45:26","modified_gmt":"2021-06-03T16:45:26","slug":"exploring-ssis-architecture-and-execution-history-through-scripting","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/bi-sql-server\/exploring-ssis-architecture-and-execution-history-through-scripting\/","title":{"rendered":"Exploring SSIS Architecture and Execution History Through Scripting"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">My previous <a href=\"http:\/\/www.simple-talk.com\/sql\/database-administration\/administrating-sql-server-integration-services---planning,-documenting-and-troubleshooting\/\">article on SSIS<\/a> was focused on the architecture and the functioning of the product. I had also provided a few essential T-SQL scripts which provide certain ways for documenting the SSIS environment. <\/p>\n<p>In this article I will focus more on the T-SQL scripting and the ways to reveal configuration, performance and architectural information through scripting. <\/p>\n<h2>Exploring SSIS&#8217;s Metadata Objects <\/h2>\n<h3>SSIS Metadata Objects in sys.objects <\/h3>\n<p>Let&#8217;s start simple by exploring the metadata objects that are related to the SSIS installation. <\/p>\n<p>If we look at the Integration Services metadata objects in SQL 2005 we will notice that the objects contain the &#8216;DTS&#8217; phrase in their names. By executing the following script in SQL 2005 we will get all objects related to the SSIS metadata (notice that the script is executed in the MSDB context): <\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">USE msdb ;\n\nSELECT&#160;&#160;*\nFROM&#160;&#160;&#160;&#160;sys.objects\nWHERE&#160;&#160; name LIKE '%dts%' <\/pre>\n<p>Later on, in the SQL 2008 and later we have objects containing the phrase &#8216;DTS&#8217; as well as &#8216;SSIS&#8217; in the names. Execute the following script to view the objects (again, in the context of the MSDB database):<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">USE msdb ;\n\nSELECT&#160;&#160;*\nFROM&#160;&#160;&#160;&#160;sys.objects\nWHERE&#160;&#160; name LIKE '%dts%'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;OR name LIKE '%ssis%' <\/pre>\n<p>Why is this? In SQL Server 2005 you will find dbo.sysdtspackages and dbo. sysdtspackages90, which help SQL Server distinguish between Integration Services packages created in BIDS and legacy packages inherited and transferred from the old SQL Server 2000 DTS (Data Transformation Services). <\/p>\n<p>In SQL Server 2008 and up we find dbo. sysdtspackages and dbo. sysssispackages, where the first table contains legacies, and the second &#8211; the BIDS packages with versions from 2005 and 2008. <\/p>\n<h3><strong><em>SSIS <\/em><\/strong>Metadata Objects in other system tables <\/h3>\n<p>In SQL 2008 and up we have: <\/p>\n<div>\n<table>\n<tbody>\n<tr>\n<td colspan=\"2\"><strong>name &#8211; 2008<\/strong><\/td>\n<\/tr>\n<tr>\n<td>sysdtscategories<\/td>\n<td>One row for each category description<\/td>\n<\/tr>\n<tr>\n<td>sysdtspackagelog<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysdtspackages<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysdtssteplog<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysdtstasklog<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysssislog<\/td>\n<td>One row per entry generated by SSIS package at runtime (when the SQL Server log provider is used)<\/td>\n<\/tr>\n<tr>\n<td>sysssispackagefolders<\/td>\n<td>One row for each folder in the SSIS structure<\/td>\n<\/tr>\n<tr>\n<td>sysssispackages<\/td>\n<td>One row for each SSIS package <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&#8230; and in SQL 2005 there is &#8230; <\/p>\n<div>\n<table>\n<tbody>\n<tr>\n<td colspan=\"2\"><strong>name &#8211; 2005<\/strong><\/td>\n<\/tr>\n<tr>\n<td>sysdtscategories<\/td>\n<td>One row for each category description<\/td>\n<\/tr>\n<tr>\n<td>sysdtslog90<\/td>\n<td>One row per entry generated by SSIS package at runtime<\/td>\n<\/tr>\n<tr>\n<td>sysdtspackagefolders90<\/td>\n<td>One row for each folder in the SSIS structure<\/td>\n<\/tr>\n<tr>\n<td>sysdtspackagelog<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysdtspackages<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysdtspackages90<\/td>\n<td>One row for each SSIS package<\/td>\n<\/tr>\n<tr>\n<td>sysdtssteplog<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<tr>\n<td>sysdtstasklog<\/td>\n<td><em>Legacy<\/em><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h2><strong><em>Structure and contents of the SSIS packages<\/em><\/strong> <\/h2>\n<p>As we know, the SSIS packages are just structured XML files that contain all information needed for the package to carry out its tasks. In other words, the SSIS package itself contains the objects in the flows, the precedence, the connections and their configurations. <\/p>\n<p>SSIS Packages may be saved on the file system, or in MSDB repository. In the case of the package being saved in MSDB, the package definition is saved in the packagedata column of the dbo.sysssispackages table (or in dbo.sysdtspackages90 in SQL Server 2005). <\/p>\n<p>The column itself is of the <em>image<\/em> datatype, hence in order for us to retrieve the contents, we need to cast it as a VARBINARY(MAX) first, and then as a XML data type. <\/p>\n<p>Depending on the security level of the package, however, it might not be very easy to explore the contents of the package definitions in MSDB; in case the package is encrypted, the package definition will begin with the <strong>EncryptedData<\/strong> tag. <\/p>\n<h3>Retrieving the definitions of the SSIS Packages <\/h3>\n<p>So, here is how to retrieve the definitions of the SSIS packages in MSDB: <\/p>\n<h4><strong>In 2005: <\/strong><\/h4>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT&#160;&#160;&#160;&#160; p.[name] AS [PackageName]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,[description] AS [PackageDescription]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,CASE [packagetype]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 0 THEN 'Undefined'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 1 THEN 'SQL Server Import and Export Wizard'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 2 THEN 'DTS Designer in SQL Server 2000'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 3 THEN 'SQL Server Replication'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 5 THEN 'SSIS Designer'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 6 THEN 'Maintenance Plan Designer or Wizard'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END&#160;&#160;&#160;&#160; AS [PackageType]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,CASE [packageformat]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 0 THEN 'SSIS 2005 version'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 1 THEN 'SSIS 2008 version'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END AS [PackageFormat]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,p.[createdate]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,CAST(CAST(packagedata AS VARBINARY(MAX)) AS XML) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;&#160;&#160;[msdb].[dbo].[sysdtspackages90]&#160;&#160;&#160;&#160; p <\/pre>\n<h4>In 2008 and up: <\/h4>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT&#160;&#160;&#160;&#160; p.[name] AS [PackageName]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,[description] AS [PackageDescription]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,CASE [packagetype]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 0 THEN 'Undefined'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 1 THEN 'SQL Server Import and Export Wizard'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 2 THEN 'DTS Designer in SQL Server 2000'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 3 THEN 'SQL Server Replication'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 5 THEN 'SSIS Designer'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 6 THEN 'Maintenance Plan Designer or Wizard'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END&#160;&#160;&#160;&#160; AS [PackageType]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,CASE [packageformat]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 0 THEN 'SSIS 2005 version'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 1 THEN 'SSIS 2008 version'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END AS [PackageFormat]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,p.[createdate]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,CAST(CAST(packagedata AS VARBINARY(MAX)) AS XML) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;&#160;&#160;[msdb].[dbo].[sysssispackages]&#160;&#160;&#160;&#160; p <\/pre>\n<p>Now that we have the definition, what can we do with it? We can parse it and extract some useful data. <\/p>\n<h3>Extracting connection strings from an SSIS definition <\/h3>\n<p>Here is how to retrieve the data connection strings: <\/p>\n<h4>In SQL 2005: <\/h4>\n<pre class=\"theme:ssms2012 lang:tsql\">;WITH XMLNAMESPACES ('www.microsoft.com\/SqlServer\/Dts' AS pNS1,\n&#160;&#160;'www.microsoft.com\/SqlServer\/Dts' AS DTS) -- declare XML namespaces\nSELECT c.name,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property [@pNS1:Name=\"DelayValidation\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS DelayValidation,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ObjectName\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ObjectName,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"Description\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS Description,\n&#160;&#160; SSIS_XML.value('pNS1:ObjectData[1]\/pNS1:ConnectionManager[1]\n\/pNS1:Property[@pNS1:Name=\"Retain\"][1]', 'varchar(MAX)') Retain,&#160;&#160;\n&#160;&#160; SSIS_XML.value('pNS1:ObjectData[1]\/pNS1:ConnectionManager[1]\n\/pNS1:Property[@pNS1:Name=\"ConnectionString\"][1]', 'varchar(MAX)') ConnectionString\nFROM&#160;&#160;\n--\n( SELECT&#160;&#160;&#160;&#160;id ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CAST(CAST(packagedata AS VARBINARY(MAX)) AS XML) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;&#160;&#160;[msdb].[dbo].[sysdtspackages90]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CROSS APPLY PackageXML.nodes('\/DTS:Executable\/DTS:ConnectionManager') SSIS_XML ( SSIS_XML )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INNER JOIN [msdb].[dbo].[sysdtspackages90] c ON PackageXML.id = c.id <\/pre>\n<h4>In SQL 2008 and up: <\/h4>\n<pre class=\"theme:ssms2012 lang:tsql\">;WITH XMLNAMESPACES ('www.microsoft.com\/SqlServer\/Dts' AS pNS1,\n&#160;&#160;'www.microsoft.com\/SqlServer\/Dts' AS DTS) -- declare XML namespaces\nSELECT c.name,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property [@pNS1:Name=\"DelayValidation\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS DelayValidation,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ObjectName\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ObjectName,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"Description\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS Description,\n&#160;&#160; SSIS_XML.value('pNS1:ObjectData[1]\/pNS1:ConnectionManager[1]\n\/pNS1:Property[@pNS1:Name=\"Retain\"][1]', 'varchar(MAX)') Retain,&#160;&#160;\n&#160;&#160; SSIS_XML.value('pNS1:ObjectData[1]\/pNS1:ConnectionManager[1]\n\/pNS1:Property[@pNS1:Name=\"ConnectionString\"][1]', 'varchar(MAX)') ConnectionString\nFROM&#160;&#160;\n--\n( SELECT&#160;&#160;&#160;&#160;id ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CAST(CAST(packagedata AS VARBINARY(MAX)) AS XML) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;&#160;&#160;[msdb].[dbo].[sysssispackages]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CROSS APPLY PackageXML.nodes('\/DTS:Executable\/DTS:ConnectionManager') SSIS_XML ( SSIS_XML )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INNER JOIN [msdb].[dbo].[sysssispackages] c ON PackageXML.id = c.id <\/pre>\n<h3>Extracting connection strings from an SSIS definition <\/h3>\n<p>Here is how to retrieve the package configurations: <\/p>\n<h4>In SQL 2005: <\/h4>\n<pre class=\"theme:ssms2012 lang:tsql\">;WITH XMLNAMESPACES ('www.microsoft.com\/SqlServer\/Dts' AS pNS1,\n&#160;&#160;'www.microsoft.com\/SqlServer\/Dts' AS DTS) -- declare XML namespaces\nSELECT c.name,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property [@pNS1:Name=\"ConfigurationType\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationType,\n&#160;&#160;CASE CAST(SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ConfigurationType\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS INT)\n&#160;&#160;&#160;&#160;WHEN 0 THEN 'Parent Package'\n&#160;&#160;&#160;&#160;WHEN 1 THEN 'XML File'\n&#160;&#160;&#160;&#160;WHEN 2 THEN 'Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 3 THEN 'Registry Entry'\n&#160;&#160;&#160;&#160;WHEN 4 THEN 'Parent Package via Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 5 THEN 'XML File via Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 6 THEN 'Registry Entry via Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 7 THEN 'SQL Server'\n&#160;&#160;END AS ConfigurationTypeDesc,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ConfigurationVariable\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationVariable,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ObjectName\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationName,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ConfigurationString\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationString\nFROM&#160;&#160;\n( SELECT&#160;&#160;&#160;&#160;id ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CAST(CAST(packagedata AS VARBINARY(MAX)) AS XML) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;&#160;&#160;[msdb].[dbo].[sysdtspackages90]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CROSS APPLY PackageXML.nodes('\/DTS:Executable\/DTS:Configuration') SSIS_XML ( SSIS_XML )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INNER JOIN [msdb].[dbo].[sysdtspackages90] c ON PackageXML.id = c.id <\/pre>\n<h4>In SQL 2008 and up: <\/h4>\n<pre class=\"theme:ssms2012 lang:tsql\">;WITH XMLNAMESPACES ('www.microsoft.com\/SqlServer\/Dts' AS pNS1,\n&#160;&#160;'www.microsoft.com\/SqlServer\/Dts' AS DTS) -- declare XML namespaces\nSELECT c.name,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property [@pNS1:Name=\"ConfigurationType\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationType,\n&#160;&#160;CASE CAST(SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ConfigurationType\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS INT)\n&#160;&#160;&#160;&#160;WHEN 0 THEN 'Parent Package'\n&#160;&#160;&#160;&#160;WHEN 1 THEN 'XML File'\n&#160;&#160;&#160;&#160;WHEN 2 THEN 'Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 3 THEN 'Registry Entry'\n&#160;&#160;&#160;&#160;WHEN 4 THEN 'Parent Package via Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 5 THEN 'XML File via Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 6 THEN 'Registry Entry via Environmental Variable'\n&#160;&#160;&#160;&#160;WHEN 7 THEN 'SQL Server'\n&#160;&#160;END AS ConfigurationTypeDesc,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ConfigurationVariable\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationVariable,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ObjectName\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationName,\n&#160;&#160;SSIS_XML.value('.\/pNS1:Property[@pNS1:Name=\"ConfigurationString\"][1]', \n&#160;&#160;&#160;&#160;'varchar(100)') AS ConfigurationString\nFROM&#160;&#160;\n( SELECT&#160;&#160;&#160;&#160;id ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CAST(CAST(packagedata AS VARBINARY(MAX)) AS XML) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;&#160;&#160;[msdb].[dbo].[sysssispackages]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;) PackageXML\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CROSS APPLY PackageXML.nodes('\/DTS:Executable\/DTS:Configuration') SSIS_XML ( SSIS_XML )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INNER JOIN [msdb].[dbo].[sysssispackages] c ON PackageXML.id = c.id <\/pre>\n<p>There are many other aspects to be explored in the definitions of the SSIS packages, and it is all matter of finding the node names and parsing them. <\/p>\n<p>In the remaining part of this article, I would like to shift our attention to these areas: the interaction between SQL Agent and the SSIS packages and some scripts to gather performance statistics. <\/p>\n<h2><strong><em>Overriding the package internal configurations<\/em><\/strong> <\/h2>\n<p>The SSIS packages can be executed in several ways: as a scheduled job from the SQL Server Agent or from the command line (or even from a batch file). <\/p>\n<p>Regardless of which method is used for the execution, it is always the DTExec.exe who carries the task. <\/p>\n<p>Before executing the SSIS package, the SQL Server Agent or the command line script have to form an execution string and pass parameters to the DTExec, and thus control the execution of the package. <\/p>\n<p>Here is a script which shows all SQL Agent jobs steps which execute SSIS packages and the custom configurations provided through the SQL Agent job: <\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">USE [msdb]\nGO\nSELECT j.job_id,\n&#160;&#160;&#160;&#160;&#160;&#160; s.srvname,\n&#160;&#160;&#160;&#160;&#160;&#160; j.name,\n&#160;&#160;&#160;&#160;&#160;&#160; js.subsystem,\n&#160;&#160;&#160;&#160;&#160;&#160; js.step_id,\n&#160;&#160;&#160;&#160;&#160;&#160; js.command,\n&#160;&#160;&#160;&#160;&#160;&#160; j.enabled,\n&#160;&#160;&#160;&#160;&#160;&#160; js.output_file_name,\n&#160;&#160;&#160;&#160;&#160;&#160; js.last_run_outcome,\n&#160;&#160;&#160;&#160;&#160;&#160; js.last_run_duration,\n&#160;&#160;&#160;&#160;&#160;&#160; js.last_run_retries,\n&#160;&#160;&#160;&#160;&#160;&#160; js.last_run_date,\n&#160;&#160;&#160;&#160;&#160;&#160; js.last_run_time,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;js.proxy_id \nFROM&#160;&#160; dbo.sysjobs j\nJOIN&#160;&#160; dbo.sysjobsteps js\n&#160;&#160; ON&#160;&#160;js.job_id = j.job_id \nJOIN&#160;&#160; MASTER.dbo.sysservers s\n&#160;&#160; ON&#160;&#160;s.srvid = j.originating_server_id\n--filter only the job steps which are executing SSIS packages \nWHERE&#160;&#160;subsystem = 'SSIS'\n--use the line below to enter some search criteria\n--AND js.command LIKE N'%ENTER_SEARCH%'\nGO <\/pre>\n<p>As you noticed, you can even use the script above to filter and search through the configurations of the SQL Agent Jobs. For example, you can search for all jobs which are executing encrypted SSIS packages by using &#8230; <\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">AND&#160;&#160;&#160;&#160;js.command LIKE N'%\/DECRYPT%' <\/pre>\n<p>&#8230;as a search criteria in the above script. You may also want to search for a server name, for example. <\/p>\n<h2><strong><em>Exploring <\/em><\/strong><strong><em>execution history<\/em><\/strong> <\/h2>\n<p>Finally, let&#8217;s look into some execution history of the SSIS packages which are scheduled as SQL Server Agent jobs. <\/p>\n<p>The following script will return all SQL Server Agent Jobs, which are currently (as of the moment of the execution of the script) executing SSIS packages and also the last execution time and duration, as well as the execution command. <\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SET NOCOUNT ON\n-- Check if the SQL Server Agent is running\nIF EXISTS ( SELECT&#160;&#160;1\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;MASTER.dbo.sysprocesses\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHERE&#160;&#160; program_name = N'SQLAgent - Generic Refresher' ) \n&#160;&#160;&#160;&#160;BEGIN\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SELECT&#160;&#160;@@SERVERNAME AS 'InstanceName' ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1 AS 'SQLServerAgentRunning'\n&#160;&#160;&#160;&#160;END\nELSE \n&#160;&#160;&#160;&#160;BEGIN\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SELECT&#160;&#160;@@SERVERNAME AS 'InstanceName' ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;0 AS 'SQLServerAgentRunning'&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAISERROR('The SQL Server Agent is not running.', 16, 1) WITH SETERROR ;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;&#160;&#160;&#160;END\n-- Execute the script\nIF EXISTS ( SELECT&#160;&#160;*\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;FROM&#160;&#160;&#160;&#160;tempdb.dbo.sysobjects\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHERE&#160;&#160; id = OBJECT_ID(N'[tempdb].[dbo].[Temp1]') ) \n&#160;&#160;&#160;&#160;DROP TABLE [tempdb].[dbo].[Temp1]\nGO\nCREATE TABLE [tempdb].[dbo].[Temp1]\n&#160;&#160;&#160;&#160;(\n&#160;&#160;&#160;&#160;&#160;&#160;job_id UNIQUEIDENTIFIER NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;last_run_date NVARCHAR(20) NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;last_run_time NVARCHAR(20) NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;next_run_date NVARCHAR(20) NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;next_run_time NVARCHAR(20) NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;next_run_schedule_id INT NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;requested_to_run INT NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;request_source INT NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;request_source_id SYSNAME COLLATE database_default\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;running INT NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;current_step INT NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;current_retry_attempt INT NOT NULL ,\n&#160;&#160;&#160;&#160;&#160;&#160;job_state INT NOT NULL\n&#160;&#160;&#160;&#160;)\nDECLARE @job_owner SYSNAME\nDECLARE @is_sysadmin INT\nSET @is_sysadmin = ISNULL(IS_SRVROLEMEMBER('sysadmin'), 0)\nSET @job_owner = SUSER_SNAME()\nINSERT&#160;&#160;INTO [tempdb].[dbo].[Temp1]\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;EXECUTE MASTER.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\nUPDATE&#160;&#160;[tempdb].[dbo].[Temp1]\nSET&#160;&#160;&#160;&#160; last_run_time = RIGHT('000000' + last_run_time, 6) ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;next_run_time = RIGHT('000000' + next_run_time, 6) ;\n-----\nSELECT&#160;&#160;j.name AS JobName ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;j.enabled AS Enabled ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CASE x.running\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 1 THEN 'Running'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ELSE CASE h.run_status\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 2 THEN 'Inactive'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN 4 THEN 'Inactive'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE 'Completed'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;END AS CurrentStatus ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;COALESCE(x.current_step, 0) AS CurrentStepNbr ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CASE x.running\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 1 THEN js.step_name\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ELSE NULL\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;END AS CurrentStepName ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CASE WHEN x.last_run_date &gt; 0\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; THEN CONVERT (DATETIME, SUBSTRING(x.last_run_date, 1, 4) + '-'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;+ SUBSTRING(x.last_run_date, 5, 2) + '-'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;+ SUBSTRING(x.last_run_date, 7, 2) + ' '\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;+ SUBSTRING(x.last_run_time, 1, 2) + ':'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;+ SUBSTRING(x.last_run_time, 3, 2) + ':'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;+ SUBSTRING(x.last_run_time, 5, 2) + '.000', 121)\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE NULL\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;END AS LastRunTime ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CASE h.run_status\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 0 THEN 'Fail'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 1 THEN 'Success'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 2 THEN 'Retry'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 3 THEN 'Cancel'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;WHEN 4 THEN 'In progress'\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;END AS LastRunOutcome ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CASE WHEN h.run_duration &gt; 0\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; THEN ( h.run_duration \/ 1000000 ) * ( 3600 * 24 )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;+ ( h.run_duration \/ 10000 % 100 ) * 3600 + ( h.run_duration\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\/ 100 % 100 )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;* 60 + ( h.run_duration % 100 )\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE NULL\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;END AS LastRunDuration ,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;js.command AS SSISPackageExecutionCommand\nFROM&#160;&#160;&#160;&#160;[tempdb].[dbo].[Temp1] x\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LEFT JOIN msdb.dbo.sysjobs j ON x.job_id = j.job_id\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;JOIN msdb.dbo.sysjobsteps js ON js.job_id = j.job_id\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LEFT OUTER JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LEFT OUTER JOIN msdb.dbo.sysjobhistory h ON x.job_id = h.job_id\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AND x.last_run_date = h.run_date\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AND x.last_run_time = h.run_time\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AND h.step_id = 0\nWHERE&#160;&#160; x.running = 1\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AND js.subsystem = 'SSIS'\n\nDROP TABLE [tempdb].[dbo].[Temp1] <\/pre>\n<p>In conclusion, SSIS is a vast product which provides significant amount of metadata available to the SQL Server administrator. In this article I have shown the way to explore the SSIS metadata through some scripts and hopefully they will make the daily administration of your SSIS environments much easier. <\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>When you are using SSIS, there soon comes a time when you are confronted with having to do a tricky task such as searching for particular connection strings in all your SSIS packages, or checking the execution history of scheduled SSIS jobs.  You can do this type of work effectively in TSQL as Feodor explains.&hellip;<\/p>\n","protected":false},"author":221902,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143528],"tags":[5424,4296,5606,4150,4306,5605,4190],"coauthors":[],"class_list":["post-1292","post","type-post","status-publish","format-standard","hentry","category-bi-sql-server","tag-integration-services","tag-metadata","tag-scripting","tag-sql","tag-ssis","tag-ssis-architecture","tag-tsql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1292","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\/221902"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1292"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1292\/revisions"}],"predecessor-version":[{"id":40643,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1292\/revisions\/40643"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1292"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1292"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}