<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>A Developer&#039;s Blog &#187; Script</title>
	<atom:link href="http://blog.hoegaerden.be/tag/script/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hoegaerden.be</link>
	<description>SQL Server, BI, .NET, IT and anything else I have been playing with.</description>
	<lastBuildDate>Tue, 07 Sep 2010 18:29:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Recursively Delete SSIS Folder</title>
		<link>http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/</link>
		<comments>http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 21:12:51 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Integration Services]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/</guid>
		<description><![CDATA[A while ago I posted a query to create a list of all the Integration Services packages deployed to the MSDB.  I am now using that query to take it a step further.
If you’ve been using SSIS for a while you’ve probably noticed that the Management Studio doesn’t like to delete Integration Services folders that [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I posted <a title="List All SSIS Packages Deployed On Your Integration Server" href="http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/" target="_blank">a query to create a list of all the Integration Services packages deployed to the MSDB</a>.  I am now using that query to take it a step further.</p>
<p>If you’ve been using SSIS for a while you’ve probably noticed that the Management Studio doesn’t like to delete Integration Services folders that are not empty.  In fact, it will politely ask you if you’re sure that you want to delete the folder on which you’ve just selected the “Delete” option through the right-click menu.</p>
<p><img style="display: inline; border: 0px;" title="Right-click pop-up menu on SSIS folder" src="http://blog.hoegaerden.be/wp-content/uploads/image195.png" border="0" alt="Right-click pop-up menu on SSIS folder" width="393" height="160" /></p>
<p><img style="display: inline; border: 0px;" title="I am sure I want to delete this non-empty SSIS folder" src="http://blog.hoegaerden.be/wp-content/uploads/image196.png" border="0" alt="I am sure I want to delete this non-empty SSIS folder" width="621" height="137" /></p>
<p>So you click the Yes button.  But then it shows you the following message:</p>
<blockquote><p>SSIS folder &#8216;FolderWithSubfolders&#8217; contains packages and/or other folders. You must drop these first. (Microsoft SQL Server Native Client 10.0)</p></blockquote>
<p>Graphically it looks like this:</p>
<p><img style="display: inline; border: 0px;" title="Object Explorer pop-up: you can't delete SSIS folders that contain packages or other folders" src="http://blog.hoegaerden.be/wp-content/uploads/image197.png" border="0" alt="Object Explorer pop-up: you can't delete SSIS folders that contain packages or other folders" width="621" height="137" /></p>
<p>And this message can be really annoying if you’ve got a main folder with, let’s say, five subfolders, and each subfolder contains about 20-30 packages.  If you want to delete this folder you first need to delete each package separately and then delete the five subfolders, and then you can finally delete the main folder.  And all that through the right-click pop-up menu because you can’t just select the object in the Object Explorer and hit the Delete button on the keyboard – it doesn’t have an action on SSIS objects…</p>
<p>So, I wasn’t planning on doing such a job manually and came up with the following stored procedure.</p>
<p>It’s probably a bit long but don’t run away just yet, I will explain what’s going on down below the code, and there are some comments in the code as well.</p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: green;">/*
DESCRIPTION: Deletes all folders and packages under, and including, specified folder.
WRITTEN BY:  Valentino Vranken
CREATED:     2010-02-28
VERSION:     1.0
USAGE:
  -- mind the forward slash
  EXEC dbo.SSIS_RecursiveDeleteFolder '/FolderWithSubfolders'
  -- to delete a subfolder
  EXEC dbo.SSIS_RecursiveDeleteFolder '/FolderWithSubfolders/ASubfolderWithPackages'

COPIED FROM: http://blog.hoegaerden.be

Note 1: folder names are not case-sensitive
Note 2: uses system tables and (undocumented) stored procedures located in MSDB.
Note 3: this code was written for SQL Server 2008. For 2005:
  o sysssispackagefolders -&gt; sysdtspackagefolders90
  o sysssispackages -&gt; sysdtspackages90
  o sp_ssis_deletefolder -&gt; sp_dts_deletefolder
  o sp_ssis_deletepackage -&gt; sp_dts_deletepackage
*/
</span><span style="color: blue;">CREATE PROCEDURE </span>dbo<span style="color: gray;">.</span>SSIS_RecursiveDeleteFolder
    @Folder <span style="color: blue;">varchar</span><span style="color: gray;">(</span>2000<span style="color: gray;">)
</span><span style="color: blue;">AS
BEGIN
    set nocount on</span><span style="color: gray;">;

    </span><span style="color: blue;">declare </span>@foldersToDelete <span style="color: blue;">table
    </span><span style="color: gray;">(
        </span>folderid <span style="color: blue;">uniqueidentifier</span><span style="color: gray;">,
        </span>Lvl <span style="color: blue;">int
    </span><span style="color: gray;">);

    </span><span style="color: blue;">declare </span>@packagesToDelete <span style="color: blue;">table
    </span><span style="color: gray;">(
        </span>PackageName <span style="color: blue;">sysname</span><span style="color: gray;">,
        </span>folderid <span style="color: blue;">uniqueidentifier</span><span style="color: gray;">,
        </span>Lvl <span style="color: blue;">int
    </span><span style="color: gray;">);

    </span><span style="color: green;">--retrieve list of folders to be deleted
    </span><span style="color: blue;">with </span>ChildFolders
    <span style="color: blue;">as
    </span><span style="color: gray;">(
        </span><span style="color: blue;">select </span>PARENT<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span><span style="color: red;">'' </span><span style="color: blue;">as sysname</span><span style="color: gray;">) </span><span style="color: blue;">as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>PARENT<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">)) </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>0 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders PARENT
        <span style="color: blue;">where </span>PARENT<span style="color: gray;">.</span>parentfolderid <span style="color: gray;">is null
        </span><span style="color: blue;">UNION </span><span style="color: gray;">ALL
        </span><span style="color: blue;">select </span>CHILD<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: blue;">case </span>ChildFolders<span style="color: gray;">.</span>Lvl
                <span style="color: blue;">when </span>0 <span style="color: blue;">then </span>CHILD<span style="color: gray;">.</span>foldername
                <span style="color: blue;">else </span>ChildFolders<span style="color: gray;">.</span>RootFolder
            <span style="color: blue;">end as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>ChildFolders<span style="color: gray;">.</span>FullPath <span style="color: gray;">+ </span><span style="color: red;">'/' </span><span style="color: gray;">+ </span>CHILD<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">))
                </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>ChildFolders<span style="color: gray;">.</span>Lvl <span style="color: gray;">+ </span>1 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders CHILD
            <span style="color: gray;">inner join </span>ChildFolders <span style="color: blue;">on </span>ChildFolders<span style="color: gray;">.</span>folderid <span style="color: gray;">= </span>CHILD<span style="color: gray;">.</span>parentfolderid
    <span style="color: gray;">)
    </span><span style="color: blue;">insert into </span>@foldersToDelete
    <span style="color: blue;">select </span>F<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>F<span style="color: gray;">.</span>Lvl
    <span style="color: blue;">from </span>ChildFolders F
    <span style="color: blue;">where </span>F<span style="color: gray;">.</span>FullPath <span style="color: gray;">like </span>@Folder <span style="color: gray;">+ </span><span style="color: red;">'%'</span><span style="color: gray;">;

    </span><span style="color: green;">--retrieve list of packages to be deleted
    </span><span style="color: blue;">with </span>ChildFolders
    <span style="color: blue;">as
    </span><span style="color: gray;">(
        </span><span style="color: blue;">select </span>PARENT<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span><span style="color: red;">'' </span><span style="color: blue;">as sysname</span><span style="color: gray;">) </span><span style="color: blue;">as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>PARENT<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">)) </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>0 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders PARENT
        <span style="color: blue;">where </span>PARENT<span style="color: gray;">.</span>parentfolderid <span style="color: gray;">is null
        </span><span style="color: blue;">UNION </span><span style="color: gray;">ALL
        </span><span style="color: blue;">select </span>CHILD<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: blue;">case </span>ChildFolders<span style="color: gray;">.</span>Lvl
                <span style="color: blue;">when </span>0 <span style="color: blue;">then </span>CHILD<span style="color: gray;">.</span>foldername
                <span style="color: blue;">else </span>ChildFolders<span style="color: gray;">.</span>RootFolder
            <span style="color: blue;">end as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>ChildFolders<span style="color: gray;">.</span>FullPath <span style="color: gray;">+ </span><span style="color: red;">'/' </span><span style="color: gray;">+ </span>CHILD<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">))
                </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>ChildFolders<span style="color: gray;">.</span>Lvl <span style="color: gray;">+ </span>1 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders CHILD
            <span style="color: gray;">inner join </span>ChildFolders <span style="color: blue;">on </span>ChildFolders<span style="color: gray;">.</span>folderid <span style="color: gray;">= </span>CHILD<span style="color: gray;">.</span>parentfolderid
    <span style="color: gray;">)
    </span><span style="color: blue;">insert into </span>@packagesToDelete
    <span style="color: blue;">select </span>P<span style="color: gray;">.</span>name<span style="color: gray;">, </span>F<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>F<span style="color: gray;">.</span>Lvl
    <span style="color: blue;">from </span>ChildFolders F
        <span style="color: gray;">inner join </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackages P <span style="color: blue;">on </span>P<span style="color: gray;">.</span>folderid <span style="color: gray;">= </span>F<span style="color: gray;">.</span>folderid
    <span style="color: blue;">where </span>F<span style="color: gray;">.</span>FullPath <span style="color: gray;">like </span>@Folder <span style="color: gray;">+ </span><span style="color: red;">'%'</span><span style="color: gray;">;

    </span><span style="color: green;">--use cursor to loop over objects to be deleted
    </span><span style="color: blue;">declare </span>objectsToDelete_cursor <span style="color: blue;">cursor
    for
        select </span>P<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>P<span style="color: gray;">.</span>Lvl<span style="color: gray;">, </span>P<span style="color: gray;">.</span>PackageName<span style="color: gray;">, </span><span style="color: red;">'P' </span><span style="color: blue;">as </span>ObjectType
        <span style="color: blue;">from </span>@packagesToDelete P
        <span style="color: blue;">UNION </span><span style="color: gray;">ALL
        </span><span style="color: blue;">select </span>F<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>F<span style="color: gray;">.</span>Lvl<span style="color: gray;">, null, </span><span style="color: red;">'F'
        </span><span style="color: blue;">from </span>@foldersToDelete F
        <span style="color: blue;">order by </span>Lvl <span style="color: blue;">desc</span><span style="color: gray;">, </span>ObjectType <span style="color: blue;">desc</span><span style="color: gray;">;

    </span><span style="color: blue;">open </span>objectsToDelete_cursor<span style="color: gray;">;

    </span><span style="color: blue;">declare </span>@folderid <span style="color: blue;">uniqueidentifier</span><span style="color: gray;">;
    </span><span style="color: blue;">declare </span>@lvl <span style="color: blue;">int</span><span style="color: gray;">;
    </span><span style="color: blue;">declare </span>@packageName <span style="color: blue;">sysname</span><span style="color: gray;">;
    </span><span style="color: blue;">declare </span>@objectType <span style="color: blue;">char</span><span style="color: gray;">;

    </span><span style="color: blue;">fetch next from </span>objectsToDelete_cursor
    <span style="color: blue;">into </span>@folderid<span style="color: gray;">, </span>@lvl<span style="color: gray;">, </span>@packageName<span style="color: gray;">, </span>@objectType<span style="color: gray;">;

    </span><span style="color: blue;">while </span><span style="color: magenta;">@@FETCH_STATUS </span><span style="color: gray;">= </span>0
    <span style="color: blue;">begin
        if </span>@objectType <span style="color: gray;">= </span><span style="color: red;">'F'
        </span><span style="color: blue;">begin
            print </span><span style="color: red;">'exec msdb.dbo.sp_ssis_deletefolder '
                </span><span style="color: gray;">+ </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>@folderid <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">));
            </span><span style="color: blue;">exec </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span><span style="color: maroon;">sp_ssis_deletefolder </span>@folderid<span style="color: gray;">;
        </span><span style="color: blue;">end
        else
        begin
            print </span><span style="color: red;">'exec msdb.dbo.sp_ssis_deletepackage '
                </span><span style="color: gray;">+ </span>@packageName <span style="color: gray;">+ </span><span style="color: red;">', ' </span><span style="color: gray;">+ </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>@folderid <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">));
            </span><span style="color: blue;">exec </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span><span style="color: maroon;">sp_ssis_deletepackage </span>@packageName<span style="color: gray;">, </span>@folderid<span style="color: gray;">;
        </span><span style="color: blue;">end

        fetch next from </span>objectsToDelete_cursor
        <span style="color: blue;">into </span>@folderid<span style="color: gray;">, </span>@lvl<span style="color: gray;">, </span>@packageName<span style="color: gray;">, </span>@objectType<span style="color: gray;">;
    </span><span style="color: blue;">end</span><span style="color: gray;">;

    </span><span style="color: blue;">close </span>objectsToDelete_cursor<span style="color: gray;">;
    </span><span style="color: blue;">deallocate </span>objectsToDelete_cursor<span style="color: gray;">;
</span><span style="color: blue;">END</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Before trying to dismantle this stored procedure, I recommend you to read <a title="List All SSIS Packages Deployed On Your Integration Server" href="http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/" target="_blank">my previous article on retrieving the list of packages</a>.  That already explains half of the code, if not 75%.</p>
<p>Our mission is to find a way to recursively delete packages and folders contained in a specified folder.  To be able to loop over those objects in the correct order (from the deepest level up until the level of the folder specified), the SP creates two table variables: one to hold all folders under the specified folder (@foldersToDelete) and one to hold the packages under the specified folder, including all subfolders (@packagesToDelete).</p>
<p>Based on those two lists I create a cursor that joins these two together, taking their level and object type into consideration.  That’s important because we first need to delete the packages in the lowest level folder, followed by their containing folder, then move one level up and do the same.</p>
<p>We then use the cursor to loop over the packages and folders and use two undocumented system stored procedures – one for each object type- to delete the package or folder.  These system SPs are located in the MSDB.  Here’s how they are defined:</p>
<pre class="code"><span style="color: blue;">ALTER PROCEDURE </span>[dbo]<span style="color: gray;">.</span>[sp_ssis_deletefolder]
  @folderid <span style="color: blue;">uniqueidentifier
AS</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue;">ALTER PROCEDURE </span>[dbo]<span style="color: gray;">.</span>[sp_ssis_deletepackage]
  @name <span style="color: blue;">sysname</span><span style="color: gray;">,
  </span>@folderid <span style="color: blue;">uniqueidentifier
AS</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see, the parameters for these procedures are not that complicated.  Both of them expect a <em>uniqueidentifier</em> as identification for the folder.  That’s okay, these IDs are stored in the <em>msdb.dbo.sysssispackagefolders</em> table and retrieved by our queries to create the list of to-be-deleted objects.</p>
<p>Furthermore, the <em>sp_ssis_deletepackage</em> SP expects the name of the package to be deleted.  Not a problem either, those names are obtained from the<em> msdb.dbo.sysssispackages</em> table.</p>
<p><strong>Note for SQL Server 2005 users:</strong> this code was written for SQL Server 2008.  The system stored procedures and system tables exist in 2005 as well, but they have different names.  See the comment header of my SP for more details.</p>
<p>So, let’s give it a little test.  Following screenshot shows the setup.  What I will do is use the stored procedure to delete the <em>FolderWithSubfolders</em> folder.  If you’ve been paying close attention, that is the same folder which I tried to delete manually through the Management Studio’s right-click menu (see first screenshot above).</p>
<p><img style="display: inline; border: 0px;" title="Overview of my deployed folders and packages" src="http://blog.hoegaerden.be/wp-content/uploads/image198.png" border="0" alt="Overview of my deployed folders and packages" width="255" height="207" /></p>
<p>After creating the SP, I ran following command:</p>
<pre class="code"><span style="color: blue;">EXEC </span>dbo<span style="color: gray;">.</span>SSIS_RecursiveDeleteFolder <span style="color: red;">'/FolderWithSubfolders'</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>And that gave me the following output in the Messages pane:</p>
<blockquote><p>exec msdb.dbo.sp_ssis_deletepackage AnotherPackage, 7F38288D-4370-40A8-80E3-E92283033E4C</p>
<p>exec msdb.dbo.sp_ssis_deletepackage Package, 7F38288D-4370-40A8-80E3-E92283033E4C</p>
<p>exec msdb.dbo.sp_ssis_deletefolder 4102ED59-ED75-4D93-BBAE-0A162447BF02</p>
<p>exec msdb.dbo.sp_ssis_deletefolder 7F38288D-4370-40A8-80E3-E92283033E4C</p>
<p>exec msdb.dbo.sp_ssis_deletefolder C156B436-8C78-4BF9-99F9-5ABFAB10C405</p></blockquote>
<p>I have deliberately put a couple of print commands in the stored procedure to dump the commands that are actually being executed.  This gives us a good idea of what’s going on.</p>
<p>That’s it for now folks.  Thank you for reading this, and if you found it useful or you’ve got some questions about it: post a comment!</p>
<p>Have fun!</p>
<p>Valentino.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>List All SSIS Packages Deployed On Your Integration Server</title>
		<link>http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/</link>
		<comments>http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 21:23:40 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Integration Services]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/</guid>
		<description><![CDATA[When deploying packages to SQL Server Integration Services, it&#8217;s advisable to set up a folder structure so that you can easily distinguish packages belonging to different projects.&#160; Furthermore it may be interesting to create subfolders under the main project folder to separate packages according to the different phases in your ETL (Extract, Transform, Load) process.&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>When deploying packages to SQL Server Integration Services, it&#8217;s advisable to set up a folder structure so that you can easily distinguish packages belonging to different projects.&#160; Furthermore it may be interesting to create subfolders under the main project folder to separate packages according to the different phases in your <a title="Wikipedia: Extract, transform, load" href="http://en.wikipedia.org/wiki/Extract,_transform,_load" target="_blank">ETL (Extract, Transform, Load)</a> process.&#160; When loading a data warehouse, interesting folder names are Dimensions for your dimension ETLs and Facts for the packages that load the fact tables.</p>
<p>After a while you end up with lots of packages spread over lots of folders.&#160; To get a good view of what is deployed on your server, it may be interesting to find a way to list all the packages.&#160; And that&#8217;s exactly the reason why I&#8217;m writing this article.</p>
<p>The query further down generates <strong>a list of all packages deployed in the MSDB database</strong> on your SQL Server.&#160; What you get is the name of the packages, their location and version-related information.&#160; I&#8217;ve also created a&#160; RootFolder column so that it&#8217;s easy to filter on project.&#160; (See now why it&#8217;s interesting to create separate folders per project?)</p>
<p>It’s <strong>important to note</strong> that packages deployed to the <strong>File System will not be shown</strong> in the list.&#160; After all, they are not stored in the MSDB database but in a folder somewhere on the server&#8217;s hard drive, more precisely in a subfolder of where you&#8217;ve installed your SQL Server.&#160; In case you&#8217;ve forgotten where that was, here&#8217;s a small tip.&#160; On your server, open up the list of Windows Services (Start &gt; Run &gt; type &quot;services.msc&quot; &gt; enter) and locate the service called <em>SQL Server Integration Services 10.0</em>.&#160; Open the properties of that service and have a look at the <em>Path to executable</em> value in the General tab.&#160; Take the path, drop the \Binn part and add \Packages instead.&#160; That is where, by default, the packages are deployed.&#160; (If you’re running SQL Server 2005, apply the same procedure but look for a service called <em>SQL Server Integration Services</em>.)</p>
<p>On my system, this is where the packages are located: D:\Program Files\Microsoft SQL Server\100\DTS\Packages.&#160; I will also prove it with following screenshot:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Packages deployed to the file system on SSIS 2008" border="0" alt="Packages deployed to the file system on SSIS 2008" src="http://blog.hoegaerden.be/wp-content/uploads/image140.png" width="381" height="82" /></p>
<p>Okay, time for the real stuff, the query:</p>
<pre class="code"><span style="color: green">/*
    DESCRIPTION: Lists all SSIS packages deployed to the MSDB database.
    WRITTEN BY: Valentino Vranken
    VERSION: 1.1
    COPIED FROM: http://blog.hoegaerden.be

    Note: this query was written for SQL Server 2008. For SQL2005:
        o sysssispackagefolders =&gt; sysdtspackagefolders90
        o sysssispackages =&gt; sysdtspackages90
*/
</span><span style="color: blue">with </span>ChildFolders
<span style="color: blue">as
</span><span style="color: gray">(
    </span><span style="color: blue">select </span>PARENT<span style="color: gray">.</span>parentfolderid<span style="color: gray">, </span>PARENT<span style="color: gray">.</span>folderid<span style="color: gray">, </span>PARENT<span style="color: gray">.</span>foldername<span style="color: gray">,
        </span><span style="color: magenta">cast</span><span style="color: gray">(</span><span style="color: red">'' </span><span style="color: blue">as sysname</span><span style="color: gray">) </span><span style="color: blue">as </span>RootFolder<span style="color: gray">,
        </span><span style="color: magenta">cast</span><span style="color: gray">(</span>PARENT<span style="color: gray">.</span>foldername <span style="color: blue">as varchar</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">)) </span><span style="color: blue">as </span>FullPath<span style="color: gray">,
        </span>0 <span style="color: blue">as </span>Lvl
    <span style="color: blue">from </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackagefolders PARENT
    <span style="color: blue">where </span>PARENT<span style="color: gray">.</span>parentfolderid <span style="color: gray">is null
    </span><span style="color: blue">UNION </span><span style="color: gray">ALL
    </span><span style="color: blue">select </span>CHILD<span style="color: gray">.</span>parentfolderid<span style="color: gray">, </span>CHILD<span style="color: gray">.</span>folderid<span style="color: gray">, </span>CHILD<span style="color: gray">.</span>foldername<span style="color: gray">,
        </span><span style="color: blue">case </span>ChildFolders<span style="color: gray">.</span>Lvl
            <span style="color: blue">when </span>0 <span style="color: blue">then </span>CHILD<span style="color: gray">.</span>foldername
            <span style="color: blue">else </span>ChildFolders<span style="color: gray">.</span>RootFolder
        <span style="color: blue">end as </span>RootFolder<span style="color: gray">,
        </span><span style="color: magenta">cast</span><span style="color: gray">(</span>ChildFolders<span style="color: gray">.</span>FullPath <span style="color: gray">+ </span><span style="color: red">'/' </span><span style="color: gray">+ </span>CHILD<span style="color: gray">.</span>foldername <span style="color: blue">as varchar</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">))
            </span><span style="color: blue">as </span>FullPath<span style="color: gray">,
        </span>ChildFolders<span style="color: gray">.</span>Lvl <span style="color: gray">+ </span>1 <span style="color: blue">as </span>Lvl
    <span style="color: blue">from </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackagefolders CHILD
        <span style="color: gray">inner join </span>ChildFolders <span style="color: blue">on </span>ChildFolders<span style="color: gray">.</span>folderid <span style="color: gray">= </span>CHILD<span style="color: gray">.</span>parentfolderid
<span style="color: gray">)
</span><span style="color: blue">select </span>F<span style="color: gray">.</span>RootFolder<span style="color: gray">, </span>F<span style="color: gray">.</span>FullPath<span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">as </span>PackageName<span style="color: gray">,
    </span>P<span style="color: gray">.</span><span style="color: blue">description as </span>PackageDescription<span style="color: gray">, </span>P<span style="color: gray">.</span>packageformat<span style="color: gray">, </span>P<span style="color: gray">.</span>packagetype<span style="color: gray">,
    </span>P<span style="color: gray">.</span>vermajor<span style="color: gray">, </span>P<span style="color: gray">.</span>verminor<span style="color: gray">, </span>P<span style="color: gray">.</span>verbuild<span style="color: gray">, </span>P<span style="color: gray">.</span>vercomments<span style="color: gray">,
    </span><span style="color: magenta">cast</span><span style="color: gray">(</span><span style="color: magenta">cast</span><span style="color: gray">(</span>P<span style="color: gray">.</span>packagedata <span style="color: blue">as varbinary</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">)) </span><span style="color: blue">as xml</span><span style="color: gray">) </span><span style="color: blue">as </span>PackageData
<span style="color: blue">from </span>ChildFolders F
    <span style="color: gray">inner join </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackages P <span style="color: blue">on </span>P<span style="color: gray">.</span>folderid <span style="color: gray">= </span>F<span style="color: gray">.</span>folderid
<span style="color: blue">order by </span>F<span style="color: gray">.</span>FullPath <span style="color: blue">asc</span><span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">asc</span><span style="color: gray">;</span></pre>
<p>The query uses a recursive CTE (<a title="BOL 2008: Using Common Table Expressions" href="http://msdn.microsoft.com/en-us/library/ms190766.aspx">Common Table Expression</a>) to get data out of a system table called <a title="BOL 2008: sysssispackagefolders (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189477.aspx">sysssispackagefolders</a>, located in the MSDB system database.&#160; The CTE gives us a list of all folders stored in the database and at the same time uses the hierarchical structure of the table to build the <em>FullPath</em> and the <em>Lvl</em> columns.</p>
<p><strong>Note:</strong> the <a title="BOL 2008: CAST and CONVERT (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms187928.aspx">CAST()</a> calls are needed because the data type of the <em>foldername</em> column is <a title="BOL 2008: Using Special Data Types" href="http://msdn.microsoft.com/en-us/library/ms191240.aspx">sysname</a>.&#160; And sysname does not implicitly convert to varchar, which is needed for the concatenation building the <em>FullPath</em> column.</p>
<p>The CTE is joined with another system table called <a title="BOL 2008: sysssispackages (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms181582.aspx">sysssispackages</a>, also located in MSDB.&#160; Not all columns are being retrieved from that table but I believe I&#8217;ve selected the most important ones.&#160; Have a look in the Books Online for more info on the columns available.</p>
<p>There’s one column however on which I’d like to add some additional info myself.&#160; That column is called <em>packagedata</em> and it contains the actual SSIS package.&#160; The data type of this column is <a title="BOL 2008: ntext, text, and image (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms187993.aspx">image</a>, not sure why because after all, an SSIS package (or .dtsx file for that matter) is pure XML.&#160; So why isn’t it stored as XML? <strike> If anyone knows the reason: post a comment!</strike></p>
<p><strong>Update:</strong> since I wrote the above paragraph I’ve come across the answer myself.&#160; The reason that the XML is not stored as xml datatype is because of the overhead that this would cause.&#160; So there you go, use image instead of xml if you’re not going to query the xml structure itself.</p>
<p>Anyway, as you can see in the query, to get it converted from image to XML you need to go through varbinary.&#160; The image datatype cannot convert directly to XML.&#160; See the Books Online here on what casts are allowed: <a title="http://msdn.microsoft.com/en-us/library/ms187928.aspx" href="http://msdn.microsoft.com/en-us/library/ms187928.aspx">http://msdn.microsoft.com/en-us/library/ms187928.aspx</a></p>
<p><strong>Note for SQL Server 2005 users:</strong> as mentioned in the query’s comments, these tables don’t exist in SQL Server 2005.&#160; Well, actually they do, they just have different names.&#160; See the comment in the code for their equivalent.</p>
<p>To finish off I&#8217;ll show you what the results look like when executing the query on my test system.&#160; But first, following screenshot shows all deployed packages as reported by the Management Studio.&#160; As you can see, two packages are deployed to the File System.&#160; These two packages were shown earlier in the first screenshot.&#160; Some other packages have been deployed to the MSDB database.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Object Explorer showing all deployed SSIS packages" border="0" alt="Object Explorer showing all deployed SSIS packages" src="http://blog.hoegaerden.be/wp-content/uploads/image141.png" width="329" height="306" /></p>
<p>And here are the results of the query:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image143.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="A list of all SSIS packages deployed to my SQL Server 2008 MSDB database" border="0" alt="A list of all SSIS packages deployed to my SQL Server 2008 MSDB database" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb37.png" width="692" height="84" /></a></p>
<p>To be honest, I added a little filter to keep the results clean.&#160; The <a title="BOL 2008: Introducing the Data Collector" href="http://msdn.microsoft.com/en-us/library/bb677248.aspx">Data Collector</a>, a new feature of SQL Server 2008, also uses some packages so I’ve filtered those out by adding a WHERE clause to the SELECT statement at the bottom of the full query:</p>
<pre class="code"><span style="color: blue">select </span>F<span style="color: gray">.</span>RootFolder<span style="color: gray">, </span>F<span style="color: gray">.</span>FullPath<span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">as </span>PackageName<span style="color: gray">,
    </span>P<span style="color: gray">.</span><span style="color: blue">description as </span>PackageDescription<span style="color: gray">, </span>P<span style="color: gray">.</span>packageformat<span style="color: gray">, </span>P<span style="color: gray">.</span>packagetype<span style="color: gray">,
    </span>P<span style="color: gray">.</span>vermajor<span style="color: gray">, </span>P<span style="color: gray">.</span>verminor<span style="color: gray">, </span>P<span style="color: gray">.</span>verbuild<span style="color: gray">, </span>P<span style="color: gray">.</span>vercomments<span style="color: gray">,
    </span><span style="color: magenta">cast</span><span style="color: gray">(</span><span style="color: magenta">cast</span><span style="color: gray">(</span>P<span style="color: gray">.</span>packagedata <span style="color: blue">as varbinary</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">)) </span><span style="color: blue">as xml</span><span style="color: gray">) </span><span style="color: blue">as </span>PackageData
<span style="color: blue">from </span>ChildFolders F
    <span style="color: gray">inner join </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackages P <span style="color: blue">on </span>P<span style="color: gray">.</span>folderid <span style="color: gray">= </span>F<span style="color: gray">.</span>folderid
<span style="color: blue">where </span>F<span style="color: gray">.</span>RootFolder <span style="color: gray">&lt;&gt; </span><span style="color: red">'Data Collector'
</span><span style="color: blue">order by </span>F<span style="color: gray">.</span>FullPath <span style="color: blue">asc</span><span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">asc</span><span style="color: gray">;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>If you’ve been paying attention, you’ve noticed that the two packages deployed to the File System are not mentioned in the output of the query, as expected.</p>
<p>Now that you know how to list your packages, <a title="Recursively Delete SSIS Folder" href="http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/" target="_blank">check out my article on deleting them</a>.</p>
<p>That’s all for now folks, have fun!</p>
<p><strong>References</strong></p>
<p><a title="BOL 2008: Tutorial: Creating a Simple ETL Package" href="http://msdn.microsoft.com/en-us/library/ms169917.aspx">BOL 2008: Tutorial: Creating a Simple ETL Package</a></p>
<p><a title="BOL 2008: sysssispackagefolders (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189477.aspx">BOL 2008: sysssispackagefolders (Transact-SQL)</a></p>
<p><a title="BOL 2008: sysssispackages (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms181582.aspx">BOL 2008: sysssispackages (Transact-SQL)</a></p>
<p><a title="BOL 2008: Recursive Queries Using Common Table Expressions" href="http://msdn.microsoft.com/en-us/library/ms186243.aspx">BOL 2008: Recursive Queries Using Common Table Expressions</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Script: Find All Empty Columns In Database</title>
		<link>http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/</link>
		<comments>http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 21:06:40 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/</guid>
		<description><![CDATA[Earlier this week a colleague had an interesting question.&#160; He was working on an application that uses a database containing more than 200 tables and wanted to find all columns in the database where this column is null for all records, so in other words all empty columns.&#160; This would give him an idea of [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week a colleague had an interesting question.&#160; He was working on an application that uses a database containing more than 200 tables and wanted to find all columns in the database where this column is null for all records, so in other words all empty columns.&#160; This would give him an idea of possibly unused (i.e. obsolete) columns.</p>
<p>Obviously he did not want to do this manually.</p>
<p>So I wrote him this script:</p>
<pre class="code"><span style="color: green">/*
DESCRIPTION: Returns a list of all columns in current database
             where the column's value is null for all records.
WRITTEN BY:  Valentino Vranken
CREATED:     2009-02-15
VERSION:     1.0

COPIED FROM: http://blog.hoegaerden.be
*/
</span><span style="color: blue">declare </span>@tempTable <span style="color: blue">table
</span><span style="color: gray">(
    </span>TableSchema <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">),
    </span>TableName <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">),
    </span>ColumnName <span style="color: blue">sysname</span><span style="color: gray">,
    </span>NotNullCnt <span style="color: blue">bigint
</span><span style="color: gray">);

</span><span style="color: blue">declare </span>@sql <span style="color: blue">nvarchar</span><span style="color: gray">(</span>4000<span style="color: gray">);
</span><span style="color: blue">declare </span>@tableSchema <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">);
</span><span style="color: blue">declare </span>@tableName <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">);
</span><span style="color: blue">declare </span>@columnName <span style="color: blue">sysname</span><span style="color: gray">;
</span><span style="color: blue">declare </span>@cnt <span style="color: blue">bigint</span><span style="color: gray">;

</span><span style="color: blue">declare </span>columnCursor <span style="color: blue">cursor for
    select </span>TABLE_SCHEMA<span style="color: gray">, </span>TABLE_NAME<span style="color: gray">, </span>COLUMN_NAME <span style="color: blue">from </span><span style="color: green">INFORMATION_SCHEMA</span><span style="color: gray">.</span><span style="color: green">COLUMNS
    </span><span style="color: blue">where </span>IS_NULLABLE <span style="color: gray">= </span><span style="color: red">'YES'</span><span style="color: gray">;

</span><span style="color: blue">open </span>columnCursor<span style="color: gray">;

</span><span style="color: blue">fetch next from </span>columnCursor <span style="color: blue">into </span>@tableSchema<span style="color: gray">, </span>@tableName<span style="color: gray">, </span>@columnName<span style="color: gray">;

</span><span style="color: blue">while </span><span style="color: magenta">@@FETCH_STATUS </span><span style="color: gray">= </span>0
<span style="color: blue">begin
    </span><span style="color: green">-- use dynamic sql to get count of records where column is not null
    </span><span style="color: blue">set </span>@sql <span style="color: gray">= </span><span style="color: red">'select @cnt = COUNT(*) from [' </span><span style="color: gray">+ </span>@tableSchema <span style="color: gray">+ </span><span style="color: red">'].[' </span><span style="color: gray">+ </span>@tableName <span style="color: gray">+
        </span><span style="color: red">'] where [' </span><span style="color: gray">+ </span>@columnName <span style="color: gray">+ </span><span style="color: red">'] is not null'</span><span style="color: gray">;
    </span><span style="color: green">-- print @sql; --uncomment for debugging
    </span><span style="color: blue">exec </span><span style="color: maroon">sp_executesql </span>@sql<span style="color: gray">, </span><span style="color: red">N'@cnt bigint output'</span><span style="color: gray">, </span>@cnt <span style="color: gray">= </span>@cnt <span style="color: blue">output</span><span style="color: gray">;

    </span><span style="color: blue">insert into </span>@tempTable <span style="color: blue">select </span>@tableSchema<span style="color: gray">, </span>@tableName<span style="color: gray">, </span>@columnName<span style="color: gray">, </span>@cnt<span style="color: gray">;

    </span><span style="color: blue">fetch next from </span>columnCursor <span style="color: blue">into </span>@tableSchema<span style="color: gray">, </span>@tableName<span style="color: gray">, </span>@columnName<span style="color: gray">;
</span><span style="color: blue">end</span><span style="color: gray">;

</span><span style="color: blue">close </span>columnCursor<span style="color: gray">;
</span><span style="color: blue">deallocate </span>columnCursor<span style="color: gray">;

</span><span style="color: blue">select </span><span style="color: gray">* </span><span style="color: blue">from </span>@tempTable <span style="color: blue">where </span>NotNullCnt <span style="color: gray">= </span>0<span style="color: gray">;</span></pre>
<p>Yes I know, it uses a cursor and dynamic SQL but hey, it&#8217;s not something that will run every minute in a production environment.&#160; And I couldn&#8217;t really think of an easy way to do this without these features.</p>
<p>For more info on dynamic SQL I would like to point you to this excellent website by <a title="Erland Sommarskog&#39;s site" href="http://www.sommarskog.se" target="_blank">Erland Sommarskog</a>.&#160; I&#8217;ve read his articles since several years now and always keep coming back to them to refresh my memory.&#160; The particular article here is called <a title="The Curse and Blessings of Dynamic SQL" href="http://www.sommarskog.se/dynamic_sql.html" target="_blank">The Curse and Blessings of Dynamic SQL</a>.</p>
<p>And finally here&#8217;s a Microsoft Support article that explains <a title="How to specify output parameters when you use the sp_executesql stored procedure in SQL Server" href="http://support.microsoft.com/default.aspx/kb/262499" target="_blank">how to capture the output of a dynamic query executed by sp_executesql</a>.&#160; According to the article this feature is not documented in the BOL.&#160; I think this is no longer a valid statement, there&#8217;s even an example in the <a title="Books Online: sp_executesql (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188001.aspx" target="_blank">BOL page on sp_executesql</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
