<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Maintenance' and 'sp_MSforeachdb'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Maintenance,sp_MSforeachdb&amp;orTags=0</link><description>Search results matching tags 'Maintenance' and 'sp_MSforeachdb'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>A more reliable and more flexible sp_MSforeachdb</title><link>http://sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/a-more-reliable-and-more-flexible-sp-msforeachdb.aspx</link><pubDate>Wed, 29 Dec 2010 16:02:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:31587</guid><dc:creator>AaronBertrand</dc:creator><description>&lt;p&gt;I've complained about sp_MSforeachdb before.&amp;nbsp; In part of my "Bad Habits to Kick" series in 2009-10, I described how I worked around its sporadic inability to actually process all of the databases on an instance: &lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/aaron_bertrand/archive/2010/02/08/bad-habits-to-kick-relying-on-undocumented-behavior.aspx" title="http://sqlblog.com/blogs/aaron_bertrand/archive/2010/02/08/bad-habits-to-kick-relying-on-undocumented-behavior.aspx" target="_blank"&gt;http://sqlblog.com/blogs/aaron_bertrand/archive/2010/02/08/bad-habits-to-kick-relying-on-undocumented-behavior.aspx&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I lumped this in a "Bad Habit" category of relying on undocumented behavior, since - while the procedure does have rampant usage - it is, in fact, both undocumented and unsupported.&amp;nbsp; That said, it can be quite useful to have a procedure like this, but only if you can rely on it.&lt;/p&gt;

&lt;p&gt;Last week, the topic came up on twitter, where someone asked if they had ever seen sp_MSforeachdb miss databases.&amp;nbsp; I raised my hand.&amp;nbsp; The conversation continued beyond my pointing how I worked around the problem; in addition to skipping databases, the built-in option also had difficulty with poorly-named databases such as "foo.com" and "I am a [bracket]."&amp;nbsp; We soon came to the conclusion that there was plenty of room for other improvements, too.&amp;nbsp; For example, why not have a parameter to support only system databases, or only user databases, or only databases in a certain list or matching a certain string pattern?&amp;nbsp; Why not extend that to other properties, such as recovery model, state, and whether auto-close was enabled?&amp;nbsp; And why not support printing the commands instead of executing them, so that you can selectively execute them in multiple windows, or change the order manually?&amp;nbsp; Having performed many maintenance tasks where I did things like:&lt;/p&gt;

&lt;blockquote&gt;

&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font style="color:blue;"&gt;EXEC&lt;/font&gt; &lt;font style="color:maroon;"&gt;sp_MSforeachdb&lt;/font&gt; &lt;font style="color:red;"&gt;N'IF ''?'' LIKE ''%pattern%''&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- do something&lt;br&gt;END'&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;...or...&lt;/p&gt;

&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font style="color:blue;"&gt;EXEC&lt;/font&gt; &lt;font style="color:maroon;"&gt;sp_MSforeachdb&lt;/font&gt; &lt;font style="color:red;"&gt;N'IF EXISTS &lt;br&gt;(&lt;br&gt;    SELECT 1 FROM sys.databases WHERE name = ''?'' &lt;br&gt;    AND recovery_model_desc = N''SIMPLE''&lt;br&gt;)&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- do something&lt;br&gt;END'&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;...or...&lt;/p&gt;

&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font style="color:blue;"&gt;EXEC&lt;/font&gt; &lt;font style="color:maroon;"&gt;sp_MSforeachdb&lt;/font&gt; &lt;font style="color:red;"&gt;N'IF DATABASEPROPERTYEX(''?'', ''IsAutoClose'') = 1&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PRINT ''ALTER DATABASE [?] SET AUTO_CLOSE OFF;'';&lt;br&gt;END'&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;/blockquote&gt;



&lt;p&gt;...I thought that I should encapsulate all of those different features into a single procedure that I could deploy onto all of the instances I manage.&amp;nbsp; And I thought that it would be useful to share this procedure with others.&amp;nbsp; So, this past week, I wrote a tip for &lt;a href="http://mssqltips.com/" title="http://mssqltips.com/" target="_blank"&gt;mssqltips.com&lt;/a&gt;, entitled, much like this post, "&lt;a href="http://mssqltips.com/tip.asp?tip=2201" title="http://mssqltips.com/tip.asp?tip=2201" target="_blank"&gt;Making a more reliable and flexible sp_MSforeachdb&lt;/a&gt;."&amp;nbsp; With more optimized cursor code and plenty of filtering capabilities, I hope that you'll find my implementation a suitable replacement.&amp;nbsp; I did leave a few things as an exercise for the reader:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;while it supports database names containing some common "naughty" characters - namely, periods (.), double-quotes ("), and left and right square brackets ([ ])), as well as database names that start with a number, it does not support databases named with single-quotes (') or leading / trailing spaces.&amp;nbsp; The reason is that the database names are parsed in various ways to support the different filtering types, and it became very tedious to programmatically determine where I had to double-up single quotes and where I couldn't, or where I had to QUOTENAME() the name and where I couldn't.&lt;br&gt;&lt;br&gt;&lt;/li&gt;

&lt;li&gt;it made me feel weak using dynamic SQL, but it was the easiest way I could think of (without creating supplemental functions) to add the IN () list when a comma-separated list of databases was passed in.&amp;nbsp; Thinking back I could have likely used a table variable to hold the names after splitting, but on the plus side, the dynamic SQL makes adding optional filter clauses quite routine.&lt;br&gt;&lt;br&gt;&lt;/li&gt;

&lt;li&gt;I only implemented a few filtering options that I thought would be most commonly required.&amp;nbsp; The model is fairly simple to extrapolate if you have other criteria in mind.&lt;br&gt;&lt;br&gt;&lt;/li&gt;

&lt;li&gt;another feature request was sorting.&amp;nbsp; Given that dynamic SQL is already in use, it would be easy enough to add a clause like '... ORDER BY ' + @order_by + ' ' + @order_by_direction.&amp;nbsp; However, from the tone of the conversation, it didn't seem to me like it was simple column ordering that was desired; rather, people were after very custom things like "process the full recovery databases first, then bulk-logged, then simple" or "process the system databases first, then the user databases that contain the string 'foo', then the rest of the user databases in alphabetical order."&amp;nbsp; Obviously this kind of sorting without defined limits could quickly become a rat's nest.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
Anyway, once again, I hope you find my creation usable.&lt;br&gt;&amp;nbsp;&lt;br&gt;</description></item></channel></rss>