<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.infosupport.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>Bertrand Rohrbock </title><link>http://blogs.infosupport.com/blogs/bertrand/default.aspx</link><description>All things related to SQL Server administration</description><dc:language>en</dc:language><generator>CommunityServer 2.1 (Build: 60809.935)</generator><item><title>Detecting if DTC is running</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2008/03/14/Detecting-if-DTC-is-running.aspx</link><pubDate>Fri, 14 Mar 2008 10:35:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:13628</guid><dc:creator>BertrandR</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/13628.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=13628</wfw:commentRss><description>
&lt;p&gt;I&amp;#39;ve recently worked on a fix for one of our jobs that starts when the SQL agent is started and proceeds to contact a central server to report the new node the instance is running on. The problem is that sometimes the MSDTC isn&amp;#39;t running when SQL agent starts and the job reports a failure because it can&amp;#39;t write data over a linked server when the MSDTC isn&amp;#39;t running. The following code detects if DTC is running, I use it in a while loop to wait for the DTC. The code is cluster compaitible.&lt;/p&gt;
&lt;p style="background-color:silver;"&gt;
SET NOCOUNT ON&lt;br /&gt;
&lt;br /&gt;
DECLARE @DTC_Found INT&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE #output (line NVARCHAR(4000))&lt;br /&gt;
&lt;br /&gt;
INSERT INTO #output&lt;br /&gt;
EXEC master..xp_cmdshell N&amp;#39;net start&amp;#39;&lt;br /&gt;
&lt;br /&gt;
SELECT @DTC_Found = COUNT(1) FROM #output WHERE [line] LIKE &amp;#39;%Distributed Transaction Coordinator%&amp;#39;&lt;br /&gt;
&lt;br /&gt;
IF @DTC_Found &amp;lt; 1&lt;br /&gt;
BEGIN&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TRUNCATE TABLE #output&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; INSERT INTO #output&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; EXEC master..xp_cmdshell N&amp;#39;cluster res&amp;#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT @DTC_Found = COUNT(1) FROM #output WHERE [line] LIKE &amp;#39;%MSDTC%Online%&amp;#39;&lt;br /&gt;
END&lt;br /&gt;
&lt;br /&gt;
DROP TABLE #output&lt;br /&gt;
&lt;br /&gt;
SELECT @DTC_Found&lt;br /&gt;
&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=13628" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Clustering/default.aspx">Clustering</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2000/default.aspx">SQL 2000</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+Agent/default.aspx">SQL Agent</category></item><item><title>Problems starting the SQL Backup Agent service</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2008/01/09/Problems-starting-the-SQL-Backup-Agent-service.aspx</link><pubDate>Wed, 09 Jan 2008 07:57:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:13337</guid><dc:creator>BertrandR</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/13337.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=13337</wfw:commentRss><description>
&lt;p&gt;Sometimes one or more of our backup proceses hang and when this happens the SQL Backup Agent service needs to be restarted in addition to the process being killed on the server. However for some reason (my thesis is that this happens when you do not kill the process on the SQL Server first) sometimes the SQL Backup Agent won&amp;#39;t start giving error event 5000.&lt;/p&gt;

&lt;p&gt;The following error message is displayed in the event viewer:&lt;/p&gt;

&lt;p style="font-weight:bold;color:red;"&gt;SQL Backup Agent startup error: error initialising IPC objects.&amp;nbsp; Error creating mutex (already exists): Global\SQBMutex_&amp;lt;instancename&amp;gt;&lt;/p&gt;

&lt;p&gt;Because I have a programming background I know what a mutex is, but if you don&amp;#39;t you can find a global description on &lt;a href="http://en.wikipedia.org/wiki/Mutual_exclusion" title="Mutual Exclusion" target="_blank"&gt;wikipedia&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My initial thoughts were that SQL Backup Pro was somehow keeping a handle on a mutex or that it didn&amp;#39;t clean up properly. So I deinstalled SQL Backup Pro and reinstalled it, but got the same error. I was able to delete all files and there wasn&amp;#39;t any SQB process on the server that could have held those handles.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx" title="Sysinternals Proces Explorer" target="_blank"&gt;Proces Explorer&lt;/a&gt; I found out it was actually SQL Server that was keeping the handle on the mutex so in order to be able to start the SQL Backup Agent you have to restart SQL Server.&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=13337" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Red+Gate+SQL+Backup+Pro/default.aspx">Red Gate SQL Backup Pro</category></item><item><title>Moving datafiles, the easy way</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/11/19/Moving-datafiles_2C00_-the-easy-way.aspx</link><pubDate>Mon, 19 Nov 2007 09:39:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:13111</guid><dc:creator>BertrandR</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/13111.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=13111</wfw:commentRss><description>&lt;p&gt;Sunday morning (I love maintenance windows) I had to move some datafiles that were placed incorrectly. I thought this would be an easy job. Detach, move the files and reattach, right ? Wrong.&lt;/p&gt;
&lt;p&gt;It appears that SQL Server won&amp;#39;t release handles on the datafiles until you put the databases in offline mode. However when you reattach a database that you previously put offline and detached you get an error message (it will attach the database though) and the database is in read-only mode.
&lt;/p&gt;&lt;p&gt;
Even worse for me was that I was able to move datafiles of an offline database that I hadn&amp;#39;t detached (it was 2am I guess I wasn&amp;#39;t so clear). This resulted in weird behaviour namely OS errors when trying to reattach the files. I was already getting visions of restoring the lastest backup and all transaction logs, but my last attempt at recovering the databases worked.&lt;/p&gt;
&lt;p&gt;
I finally ended up moving all the files back, putting the database in read-only mode (to prevent missing any changes to the data), creating a backup and restoring the backup with MOVE TO parameters and then turning off read-only mode, which is actually much easier and faster to do.&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=13111" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Datafiles/default.aspx">Datafiles</category></item><item><title>Restoring MSDB across instances, a bad idea</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/11/14/Restoring-MSDB-across-instances_2C00_-a-bad-idea.aspx</link><pubDate>Wed, 14 Nov 2007 08:22:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:13092</guid><dc:creator>BertrandR</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/13092.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=13092</wfw:commentRss><description>&lt;p&gt;We&amp;#39;ve recently been migrating instances of SQL Server between different clusters in order to dismantle an old cluster. To move the jobs we&amp;#39;ve been copying the MSDB from the old instance to the new one by performing a restore and we didn&amp;#39;t run into any problems ...&amp;nbsp; until yesterday. A job that used CmdExec instead of a T-SQL jobstep wouldn&amp;#39;t run, put the job in suspended state and give the following error:&lt;/p&gt;

&lt;p style="color:red;font-weight:bold;"&gt;Unable to start execution of step 1 (reason: The CmdExec subsystem failed to load [see the SQLAGENT.OUT file for details]; The job has been suspended).&amp;nbsp; The step failed.&lt;/p&gt;

&lt;p&gt;Checking the agent log provided the following error message:&lt;/p&gt;

&lt;p style="color:red;font-weight:bold;"&gt;Step 1 of job &amp;#39;&amp;lt;jobname&amp;gt;&amp;#39; (&amp;lt;job_id&amp;gt;) cannot be run because the CmdExec subsystem failed to load.&amp;nbsp; The job has been suspended&lt;/p&gt;

&lt;p&gt;After further examination of the agent log I found the following startup errors:&lt;/p&gt;

&lt;p style="color:red;font-weight:bold;"&gt;Subsystem &amp;#39;ActiveScripting&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;CmdExec&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;Snapshot&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;LogReader&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;Distribution&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;Merge&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;QueueReader&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;ANALYSISQUERY&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;ANALYSISCOMMAND&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;br /&gt;
Subsystem &amp;#39;SSIS&amp;#39; could not be loaded (reason: The specified module could not be found)&lt;/p&gt;

&lt;p&gt;As it turns out, SQL agent stores a path name to the DLL files required to perform the non T-SQL jobsteps in the MSDB. This is documented here: &lt;a href="http://support.microsoft.com/kb/903205"&gt;Microsoft KB 903205&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Moving (reinstalling) the server caused the directory of these DLL&amp;#39;s to change (in this case from MSSQL.6 to MSSQL.12) and the agent was unable to load them. As we rarely use any non T-SQL jobsteps we hadn&amp;#39;t run into this problem yet.&lt;/p&gt;

&lt;p&gt;The solution was performing an update to the &lt;strong&gt;msdb.dbo.syssubsystems&lt;/strong&gt; table updating the values of subsystem_dll column to the current situation and restarting the agent.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; It appears only SQL 2005 is affected, SQL 2000 doesn&amp;#39;t store these references in the MSDB. I&amp;#39;ve compiled a script to fix wrong references:&lt;br /&gt;
&lt;/p&gt;

&lt;p style="background-color:silver;"&gt;
SET NOCOUNT ON&lt;br /&gt;
DECLARE		@SQLRoot		NVARCHAR(512)&lt;br /&gt;&lt;br /&gt;
IF @@VERSION LIKE (&amp;#39;% 9.%&amp;#39;)&lt;br /&gt;
BEGIN&lt;br /&gt;
&amp;nbsp; &amp;nbsp; EXEC master.dbo.xp_instance_regread&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; N&amp;#39;HKEY_LOCAL_MACHINE&amp;#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; ,N&amp;#39;SOFTWARE\Microsoft\MSSQLServer\Setup&amp;#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,N&amp;#39;SQLPath&amp;#39;, @SQLRoot OUTPUT&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; UPDATE msdb.dbo.syssubsystems &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
SET subsystem_dll = @SQLRoot+RIGHT(subsystem_dll,LEN(subsystem_dll)-CHARINDEX(&amp;#39;\MSSQL\binn\&amp;#39;,subsystem_dll)-5)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
subsystem_dll NOT LIKE @SQLRoot + &amp;#39;%&amp;#39; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
AND subsystem_dll &amp;lt;&amp;gt; &amp;#39;[Internal]&amp;#39;&lt;br /&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; IF @@ROWCOUNT &amp;gt; 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BEGIN&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PRINT &amp;#39;Bad references found on &amp;#39;+@@SERVERNAME&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PRINT &amp;#39;Server root: &amp;#39;+@SQLRoot	&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; END&lt;br /&gt;&lt;br /&gt;
END
&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=13092" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Clustering/default.aspx">Clustering</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Errorlog/default.aspx">Errorlog</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Migration/default.aspx">Migration</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+Agent/default.aspx">SQL Agent</category></item><item><title>Reporting version number on SQL Backup Pro</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/10/26/Reporting-version-number-on-SQL-Backup-Pro.aspx</link><pubDate>Fri, 26 Oct 2007 11:51:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:13009</guid><dc:creator>BertrandR</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/13009.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=13009</wfw:commentRss><description>&lt;p&gt;Just a quick update to share a piece of handy information. Red Gate does not document it in their help files, but there is a way to get the version number of the Red Gate DLL used to create backups with T-SQL with the following query:&lt;/p&gt;

&lt;p style="background-color:silver;"&gt;
DECLARE @version nvarchar(32)&lt;br /&gt;
DECLARE @edition int&lt;br /&gt;
&lt;br /&gt;
exec master..sqbutility 21, @edition OUTPUT, @version OUTPUT&lt;br /&gt;
&lt;br /&gt;
SELECT @version&lt;/p&gt;

&lt;p&gt;
Quite handy if you&amp;#39;re doing a survey on what versions of SQB are in use in your SQL environment.&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=13009" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Red+Gate+SQL+Backup+Pro/default.aspx">Red Gate SQL Backup Pro</category></item><item><title>Reading the SQL errorlog</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/10/25/Reading-the-SQL-errorlog.aspx</link><pubDate>Thu, 25 Oct 2007 07:56:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:12996</guid><dc:creator>BertrandR</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/12996.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=12996</wfw:commentRss><description>&lt;p&gt;Yesterday I was doing an analysis of the SQL errorlog in response to a cluster node that had been crashing frequently.&lt;/p&gt;
&lt;p&gt;
First I noticed there&amp;#39;s a rather annoying bug in SQL Server Management Studio: if you press the filter button before all the log files are read (if you select more then one) you will only filter based on the part of the log that&amp;#39;s already read by the Management Studio. I saw huge holes in my log files with entire days missing and thought we might have a serious problem until I discovered that data I had read previously was now gone.&lt;/p&gt;
&lt;p&gt;Besides this annoying bug it&amp;#39;s rather painful to examine the tabular data of the errorlog window by hand and I was wondering if there were some way I could do this in SQL. I looked in the SQL help, but couldn&amp;#39;t find anything to help me except a function in SQL-DMO I was unable to call from T-SQL. Today Google helped me out and provided me with the solution: sp_readerrorlog.&lt;/p&gt;
&lt;p&gt;
This stored procedure is nicely documented at &lt;a href="http://vyaskn.tripod.com/sp_readerrorlog_undocumented.htm" title="sp_readerrorlog documentation"&gt;http://vyaskn.tripod.com/sp_readerrorlog_undocumented.htm&lt;/a&gt; and it appears that you can read any text file that SQL Server can access into a table with this stored procedure, which could come in handy some other time.&lt;br /&gt;&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=12996" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2000/default.aspx">SQL 2000</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Errorlog/default.aspx">Errorlog</category></item><item><title>Object references and SQL</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/09/25/Object-references-and-SQL.aspx</link><pubDate>Tue, 25 Sep 2007 12:04:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:12856</guid><dc:creator>BertrandR</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/12856.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=12856</wfw:commentRss><description>
&lt;p&gt;While it might seem strange or even impossible to work with objects in SQL it is possible. I stumbled upon this recently while I was investigating a way to automatically drop and recreate indexes on a SQL 2000 server.&lt;/p&gt;

&lt;p style="background-color:silver;"&gt;DECLARE @object INT&lt;br /&gt;
EXEC sp_OACreate &amp;#39;SQLDMO.SQLServer&amp;#39;, @object OUT&lt;br /&gt;
EXEC sp_OASetProperty @object, &amp;#39;LoginSecure&amp;#39;, TRUE&lt;/p&gt;

&lt;p&gt;With this statement an object is created and the reference to it is stored as an integer in @object. We also set the LoginSecure property to true. We can get and set properties and call methods of the object with the sp_OA..... functions&lt;/p&gt;

&lt;p style="background-color:silver;"&gt;SET @CmdStr = &amp;#39;Connect(&amp;#39;+@@SERVERNAME+&amp;#39;)&amp;#39;&lt;br /&gt;
EXEC sp_OAMethod @object,@CmdStr&lt;/p&gt;

&lt;p&gt;With this statement the Connect function on the object is called with the servername of the server you&amp;#39;re running the script on as the parameter. After connecting it&amp;#39;s possible to approach objects on the SQL server, this might not seem very usefull yet as SQL is the language to approach objects on a database server. However it is usefull in getting object definitions.&lt;/p&gt;

&lt;p style="background-color:silver;"&gt;SET @CmdStr = &amp;#39;Databases(&amp;quot;testdatabase&amp;quot;).Tables(&amp;quot;table1&amp;quot;).Indexes(&amp;quot;index1&amp;quot;).Script(5)&amp;#39;&lt;br /&gt;
EXEC sp_OAMethod @object, @CmdStr&lt;/p&gt;

&lt;p&gt;Now it gets a little more interesting, we approach the object named index1 in the collection indexes in the collection of tables in the collection of databases and call the Script() method on it. The number 5 is a bitpattern that indicates the objects and the deletion of the object if it exists need to be scripted.&lt;/p&gt;
&lt;p&gt;I wish I had some more time to dig into this, I am sure there are more gems to be found in this mechanism.&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=12856" width="1" height="1"&gt;</description></item><item><title>Writing better SQL scripts</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/09/13/Writing-better-SQL-scripts.aspx</link><pubDate>Thu, 13 Sep 2007 12:19:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:12818</guid><dc:creator>BertrandR</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/12818.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=12818</wfw:commentRss><description>&lt;p&gt;Many organisations that have a platform for application hosting that includes different environments for development, testing and production use SQL scripts to migrate between environments. As a DBA I see a lot of these scripts and a lot of them are written very poorly while others (usually the generated ones) are small pieces of art.&lt;/p&gt;

&lt;p&gt;The qualitity of scripts makes a huge difference in the time DBA&amp;#39;s spend executing these scripts and as a result of that it influences the timeframe in which a script will be ran.&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;So, how to produce good scripts ? I&amp;#39;ll give a few tips.&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt; Note that code samples are all SQL 2000 compaitible. If your database uses SQL 2005 see the comment under &amp;#39;Scripting other objects&amp;#39; on how to find out how to properly script your object(s) for that version.&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use a USE statement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A good script starts with a USE statement, this way you&amp;#39;re sure your script will be executed in the right database. The reason for this is simple: it prevents your mutations from happening to the wrong database (usually the master database ;) ). Another good practise is to set NOCOUNT to ON so the messages window isn&amp;#39;t filled with &amp;#39;rows affected&amp;#39; messages.&lt;br /&gt;
&lt;/p&gt;

&lt;p style="font-family:Courier New;background-color:silver;"&gt;SET NOCOUNT ON&lt;br /&gt;&lt;br /&gt;USE [&amp;lt;database name&amp;gt;]&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scripting Stored Procedures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most important thing with writing good scripts is that your script
is repeatable on every environment no matter what version of the
database it runs. In my experience most changes to a database will be to stored procedures. The easiest way to ensure the stored procedure code you provide will end up being the new code is to use drop and create procedure statements, never use alter statements (these won&amp;#39;t run if the procedure does not exist for some reason).&lt;/p&gt;

&lt;p style="font-family:Courier New;background-color:silver;"&gt;IF EXISTS (SELECT 1 FROM dbo.sysobjects WHERE id = OBJECT_ID(N&amp;#39;&amp;lt;stored procedure name&amp;gt;&amp;#39;) AND OBJECTPROPERTY(id, N&amp;#39;IsProcedure&amp;#39;) = 1) &lt;br /&gt;
&amp;nbsp; DROP PROCEDURE &amp;lt;stored procedure name&amp;gt;&lt;br /&gt;
GO&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br /&gt;&lt;br /&gt;
CREATE PROCEDURE &amp;lt;stored procedure name&amp;gt;&lt;br /&gt;
&amp;lt;parameters&amp;gt;&lt;br /&gt;
AS&lt;br /&gt;
BEGIN&lt;br /&gt;
&amp;nbsp; ......&lt;br /&gt;
END&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;It&amp;#39;s also a good practise to use BEGIN and END statement combined with indentation so it&amp;#39;s obvious where your procedure starts and ends in case there&amp;#39;s multiple stored procedures in scripts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scripting other objects&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you&amp;#39;re curious how to properly script other objects you can check easily by setting the &amp;#39;Include IF NOT EXISTS clause&amp;#39; option (Options-&amp;gt;Scripting) in SQL Server Management Studio to TRUE and right click an object of the type and select a Script ... as -&amp;gt; CREATE To option. There&amp;#39;s one important exception to the &amp;#39;don&amp;#39;t alter, but drop if exists before you create&amp;#39; guideline and that&amp;#39;s the TABLE object. Your tables hold data, you probaly do not want this data lost.&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use transactions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You probably want your update to succeeded as a whole or not at all. Using repeatable scripting will make it less important, but you still don&amp;#39;t want your system to be in some kind of version between version X and Y, you want it version X or Y. The solution is simple and native to a DBMS: use transactions ! If you&amp;#39;re using SQL 2005 it&amp;#39;s very easy to implement with TRY.. CATCH ROLLBACK constructions if you&amp;#39;re using SQL 2000 test the results of your operations with @@ERROR and end operation with a GOTO rollback block statement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indentation and comments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make your scripts readable by humans and not just for a SQL parser. Use comments so it&amp;#39;s obvious what is happening and use proper indentation.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finally if you want to show off....&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Give status updates using PRINT messages. Provide information on what objects were created,deleted or altered and give numbers on the affected records of insertions, deletions or updates using @@ROWCOUNT. It&amp;#39;s very helpful if something goes wrong, which won&amp;#39;t happen because you&amp;#39;ve tested your scripts thoroughly........ right ?&lt;br /&gt;&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=12818" width="1" height="1"&gt;</description></item><item><title>Installing multiple instances of SQL server without rebooting</title><link>http://blogs.infosupport.com/blogs/bertrand/archive/2007/09/11/Installing-multiple-instances-of-SQL-server-without-rebooting.aspx</link><pubDate>Tue, 11 Sep 2007 07:09:00 GMT</pubDate><guid isPermaLink="false">56f6167b-0c51-4839-ab2d-34653eeb5c9c:12803</guid><dc:creator>BertrandR</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.infosupport.com/blogs/bertrand/comments/12803.aspx</comments><wfw:commentRss>http://blogs.infosupport.com/blogs/bertrand/commentrss.aspx?PostID=12803</wfw:commentRss><description>&lt;p&gt;Figured I&amp;#39;d make my first post not just an introduction, but also give some usefull information on SQL cluster installations that isn&amp;#39;t documented very well. &lt;/p&gt;&lt;p&gt;Let&amp;#39;s start with the introduction. I am Bertrand Rohrbock, 25 years old and working for Info Support as a DBA (Database Administrator) with a large insurance company in the Netherlands. I am in the team that runs one of the largest if not the largest SQL server farm in the Netherlands with nearly 200 instances serving over 3900 databases. My daily work varies from monitoring the status and performance of our servers and designing and implementing structural fixes to working with internal clients to make sure their solutions run well on our platform.&lt;br /&gt;&lt;br /&gt;We currently run both SQL 2000 and SQL 2005 instances on our platform and are in the (slow) proces of migrating everything to SQL 2005. However as the release date of SQL 2008 is coming up pretty fast a lot of projects will skip the 2005 release and migrate directly to SQL 2008. Another product I work a lot with is &lt;a href="http://www.red-gate.com/products/sql_backup/" title="Red Gate SQL Backup Pro" target="_blank"&gt;Red Gate SQL Backup Pro&lt;/a&gt; and as we have some problems with this product and my colleagues like to dump all of them on me I&amp;#39;m likely to write about it some.&lt;/p&gt;&lt;p&gt;Beside all the technical aspects of the DBA life ( it&amp;#39;s not a job, it&amp;#39;s a way of life ;) ) there&amp;#39;s a lot of proces improvement going on as the organisation moves from &lt;a href="http://en.wikipedia.org/wiki/Capability_Maturity_Model" title="Capability Maturity Model" target="_blank"&gt;CMM&lt;/a&gt; level 2 to 3. It&amp;#39;s increasingly becoming a part of my job to make sure the proces is done right and as with all change this sometimes leads to frustrations for me or our clients which I might elaborate on occasionally on this blog.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Now for the usefull information: During the installation of two new instances on one of our production clusters the other day I ran into a problem. I am not sure if this problem exists in one form or the other with normal (non-clustered) installations ! &lt;/p&gt;&lt;p&gt;SQL Server 2005 wants you to reboot the system it&amp;#39;s installed on after installation, but I did not have this option at the time (even though the installation was during a maintenance window) and it works just fine without the reboot. However the installation puts the system in a &amp;#39;reboot pending&amp;#39; state which is detected when installing a new instance. The setup gives a nice red cross at installation ( Pending Reboot Requirement ), but still gives the option to move on. However at the point in the installation where the nodes are selected the nodes on which another instance has been installed will be in the unavailable listbox and give the error &amp;#39;a scc check failed on the node&amp;#39;.&lt;/p&gt;&lt;p&gt;The sollution is to delete (or rename if you&amp;#39;re uncomfortable with deleting) the following registry key &lt;strong&gt;on both nodes&lt;/strong&gt; and log out:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10pt;font-family:Arial;"&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\PendingFileRenameOperations&lt;/span&gt;&lt;/p&gt;&lt;p&gt;It&amp;#39;s a good idea to do this after every installation even after installing a single instance. The pending reboot state does not only affect SQL Server, but the entire system, there can be problems with rolling out security patches for example. Obviously it&amp;#39;s best to reboot the system after you&amp;#39;re done installing, but this option is not always available. It should be best practise to leave the system in the state it was in before the installation.&lt;br /&gt;&lt;/p&gt;&lt;img src="http://blogs.infosupport.com/aggbug.aspx?PostID=12803" width="1" height="1"&gt;</description><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Clustering/default.aspx">Clustering</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://blogs.infosupport.com/blogs/bertrand/archive/tags/Introduction/default.aspx">Introduction</category></item></channel></rss>