<?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>The Art of Software &#187; SQL Server</title>
	<atom:link href="http://orionseven.com/blog/category/sql-server/feed/" rel="self" type="application/rss+xml" />
	<link>http://orionseven.com/blog</link>
	<description>It takes a lot more than code to make software.</description>
	<lastBuildDate>Thu, 06 Oct 2011 14:06:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Starting and Stopping SQL Server with Windows PowerShell 2.0</title>
		<link>http://orionseven.com/blog/2010/10/18/starting-and-stopping-sql-server-with-windows-powershell-2-0/</link>
		<comments>http://orionseven.com/blog/2010/10/18/starting-and-stopping-sql-server-with-windows-powershell-2-0/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 23:40:42 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=116</guid>
		<description><![CDATA[If you&#8217;re like me you don&#8217;t always need SQL Server running in a local development environment. Because of this I wanted a quick and easy way to start and stop SQL Server which immediately made me think of Windows PowerShell. This script is for PowerShell 2.0 and is pretty simple, you could get much more [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re like me you don&#8217;t always need SQL Server running in a local development environment. Because of this I wanted a quick and easy way to start and stop SQL Server which immediately made me think of Windows PowerShell. This script is for PowerShell 2.0 and is pretty simple, you could get much more fancy but it suffices for my setup on my home development box.</p>
<p>Here&#8217;s the script:</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$service</span> <span class="sy0">=</span> <span class="kw1">get-service</span> <span class="st0">&quot;MSSQLSERVER&quot;</span> <span class="kw5">-ErrorAction</span> SilentlyContinue</p>
<p><span class="kw3">if</span><span class="br0">&#40;</span> <span class="re0">$service</span>.status <span class="kw4">-eq</span> <span class="st0">&quot;Running&quot;</span> <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Stopping Dependent Services&#8230;&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$depServices</span> <span class="sy0">=</span> <span class="kw1">get-service</span> <span class="re0">$service</span>.name <span class="sy0">-</span>dependentservices <span class="sy0">|</span> <span class="kw1">Where-Object</span> <span class="br0">&#123;</span><a href="about:blank"><span class="kw6">$_</span></a>.Status <span class="kw4">-eq</span> <span class="st0">&quot;Running&quot;</span><span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">if</span><span class="br0">&#40;</span> <span class="re0">$depServices</span> <span class="kw4">-ne</span> <span class="re0">$null</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">foreach</span><span class="br0">&#40;</span><span class="re0">$depService</span> <span class="kw3">in</span> <span class="re0">$depServices</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">stop-service</span> <span class="re0">$depService</span>.name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Stopping Service&#8230;&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">stop-service</span> <span class="re0">$service</span>.name <span class="kw5">-force</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Service Stopped&quot;</span><br />
<span class="br0">&#125;</span><br />
<span class="kw3">elseif</span> <span class="br0">&#40;</span> <span class="re0">$service</span>.status <span class="kw4">-eq</span> <span class="st0">&quot;Stopped&quot;</span> <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Starting Service&#8230;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">start-service</span> <span class="re0">$service</span>.name<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Service Started&quot;</span><br />
<span class="br0">&#125;</span><br />
<span class="kw3">else</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;The specified service does not exist&quot;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>I had wanted to use Try/Catch but the service commands (e.g. get-service) issue non-stopping errors which PowerShell 2.0 doesn&#8217;t catch.</p>
<p>Really this works on just about any service, but my use was for SQL Server, just change the name of the service to anything you like, or even better yet pass it in as a parameter. You could also have it start dependent services if you like.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2010/10/18/starting-and-stopping-sql-server-with-windows-powershell-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>T-SQL Tuesday: Spot Relationship&#8217;s with Database Diagrams</title>
		<link>http://orionseven.com/blog/2010/02/08/t-sql-tuesday-spot-relationships-with-database-diagrams/</link>
		<comments>http://orionseven.com/blog/2010/02/08/t-sql-tuesday-spot-relationships-with-database-diagrams/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 05:25:56 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[T-SQL Tuesday]]></category>
		<category><![CDATA[Foreign Keys]]></category>
		<category><![CDATA[Relational Database]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=91</guid>
		<description><![CDATA[As part of this months  T-SQL Tuesday on &#8220;relationships&#8221; I thought I&#8217;d post about a handy feature in SQL Server Management Studio. As the title of the article implies I&#8217;m going to discuss how database diagrams in SSMS can be handy to visually see the relationship&#8217;s in a database. But I think I could have [...]]]></description>
			<content:encoded><![CDATA[<p>As part of this months  <a href="http://msmvps.com/blogs/robfarley/archive/2010/02/02/invitation-for-t-sql-tuesday-003-relationships.aspx">T-SQL Tuesday</a> on &#8220;relationships&#8221; I thought I&#8217;d post about a handy feature in SQL Server Management Studio.</p>
<p>As the title of the article implies I&#8217;m going to discuss how database diagrams in SSMS can be handy to visually see the relationship&#8217;s in a database. But I think I could have also named the article &#8220;T-SQL Tuesday: Spot Relationship&#8217;s with Database Diagrams, or the Lack of Them&#8221;.</p>
<p>Out of the box and with a deployed database you may get a warning about trying to use a database diagram and that they&#8217;re not accessible. Quite often this is because the database does not have a valid owner. As always Books Online is our hero, you can <a href="http://msdn.microsoft.com/en-us/library/ms178630.aspx">use sp_changedbowner to change the owner</a>. While you&#8217;re at BoL <a href="http://msdn.microsoft.com/en-us/library/ms186345.aspx">read this too, it explains database diagram ownership</a>.</p>
<p>With that out of the way we can move on to the point of this article. Relationships!</p>
<p>SSMS&#8217;s database diagram&#8217;s when first made will ask you what tables you want to add to the diagram. Go ahead and add them all, you&#8217;ll end up with a nicely formatted diagram showing you your tables all lined up nicely with each other. Your results will vary but will likely be a mixture of the tables neatly arrayed with lines drawn between them &#8230; or &#8230; tables neatly arrayed one after another after another with nary a line to be seen. As they say, &#8220;Hope for the best but prepare for the worst.&#8221;</p>
<p>If you&#8217;re lucky and you have lines between tables rest assured that at least some tables have foreign keys between tables. But don&#8217;t rest too long because just because there are lines doesn&#8217;t mean there are enough of them (or there might be too many). It&#8217;s now time to look at each table neatly arrayed and familiarize yourself with the schema. I find that visually it is quite easy this way to spot likely candidates for FK&#8217;s. You&#8217;re also likely to spot other things, such as PK candidates, better normalization strategies, moments of sheer database schema genius, or pure database depravity. If you find the latter then&#8230;</p>
<p>Database diagrams are also great for spotting everything that&#8217;s missing as well. Orphaned tables are quite obvious sitting all by themselves, and again I find it visually easy to quickly tell if that&#8217;s the way it should be or shouldn&#8217;t be. If you find everything is missing you can start adding FK&#8217;s right there in your diagram. Simply right click on a table and you&#8217;re given quite a few options to start updating your schema. (See the warning below!)</p>
<p>Anyhow, I hope everyone gives SSMS&#8217;s diagrams a try. It does not replace sitting down and verifying your database&#8217;s relationship&#8217;s one by one. But it does make a great aid in doing so.</p>
<p>A couple of additional points to keep in mind when looking using database diagrams:</p>
<ul>
<li>Remember there are times you might not want a foreign key. FK&#8217;s do imply overhead and in a performance consideration there may be a valid reason to not have them.</li>
<li>The diagram resizing isn&#8217;t really all that great, 75% means that the text is 25% less legible. Not very handy unless you want to get a REALLY high level view.</li>
<li>Go ahead and drag things around. I do all the time.</li>
<li>Try printing these out! Print to a PDF with something like CutePDF or if you&#8217;re lucky like I am with a large format printer print it out on a 3&#8242; x 3&#8242; piece of paper and start drawing all over it.</li>
</ul>
<p>And finally a word of warning!</p>
<p>The changes you make in a database diagram can be committed! So don&#8217;t go trying to drop database objects in a production environment. I think it&#8217;s best practice to just not use them in production. Unless you&#8217;ve practiced your disaster recovery recently and feel quite confident in it.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2010/02/08/t-sql-tuesday-spot-relationships-with-database-diagrams/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Is your Disaster Recovery Plan Complete?</title>
		<link>http://orionseven.com/blog/2009/12/16/63/</link>
		<comments>http://orionseven.com/blog/2009/12/16/63/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 22:28:07 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[Disaster Recovery]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=63</guid>
		<description><![CDATA[There has been much talk lately about backups. Thankfully I have not had to face this too. Since backups are on a lot of people’s minds lately, and more importantly as Joel restates it’s not really the backup that’s important, but the restore which is! Do you have everything backed up you’ll need? Have you actually [...]]]></description>
			<content:encoded><![CDATA[<p>There has been <a href="http://www.codinghorror.com/blog/archives/001315.html">much</a> <a href="http://haacked.com/archive/2009/12/14/back-in-business-again.aspx">talk</a> <a href="http://joelonsoftware.com/items/2009/12/14.html">lately</a> about backups. Thankfully I have not had to face this too.</p>
<p>Since backups are on a lot of people’s minds lately, and more importantly as Joel restates it’s not really the backup that’s important, but the restore which is!</p>
<p>Do you have everything backed up you’ll need? Have you actually tried to restore from your backups lately?</p>
<p>Or how about this? Is your DR Plan actually up to date? Sure you just did a full restore of your DR Plan two months ago, but what’s changed since then? Optimally you should be updating your DR Plan whenever there are any system changes. But quite likely something was forgotten, that something won’t be pointed out till the next attempt to do a test restore or the real deal hits.</p>
<p>That’s why I suggest doing a review of your DR Plan monthly. I personally set a reminder for the last Monday of every month. I haven’t always been perfect in this. But I have noticed that when I do a scan through it that’s not related to a specific new update that I tend to flesh out the DR Plan more. So that after a few months not only do I have the basics in, but a lot of extra stuff that might be really helpful to standup the system should the proverbial shit hit the fan.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2009/12/16/63/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server Build Links</title>
		<link>http://orionseven.com/blog/2009/12/09/sql-server-build-links/</link>
		<comments>http://orionseven.com/blog/2009/12/09/sql-server-build-links/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 22:59:13 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[Links]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL Server 2000]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=47</guid>
		<description><![CDATA[I&#8217;m always trying to find out what the latest build, cumulative update, hot-fix is available for SQL Server. Unfortunately the SQL Server TechCenter page never seems to stay up to date on what the latest Cumulative Update is. There are however support pages that do stay up to date. In the effort to help save you [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m always trying to find out what the latest build, cumulative update, hot-fix is available for SQL Server. Unfortunately the SQL Server TechCenter page never seems to stay up to date on what the latest Cumulative Update is. There are however support pages that do stay up to date. In the effort to help save you and me from having to search for the latest build, cumulative update, or hot-fix for SQL Server here are the links to the relevant support pages.</p>
<p><strong>SQL Server 2008 SP1 Builds:</strong> <a href="http://support.microsoft.com/kb/970365/en-us">http://support.microsoft.com/kb/970365/en-us</a></p>
<p><strong>SQL Server 2008 Builds:</strong> <a href="http://support.microsoft.com/kb/956909/en-us">http://support.microsoft.com/kb/956909/en-us</a></p>
<p><strong>SQL Server 2005 SP3 Builds:</strong> <a href="http://support.microsoft.com/kb/960598">http://support.microsoft.com/kb/960598</a></p>
<p><strong>SQL Server 2005 SP2 Builds: </strong><a href="http://support.microsoft.com/kb/937137">http://support.microsoft.com/kb/937137</a></p>
<p>I don&#8217;t have any links for anything prior to 2005 SP2, if you&#8217;re not on SP2 though yet you really should be, it was a great service pack.</p>
<p><strong>SQL Server 2000 SP4 Builds:</strong> <a href="http://support.microsoft.com/kb/894905">http://support.microsoft.com/kb/894905</a></p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2009/12/09/sql-server-build-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Followup: DBCC CHECKFILEGROUP Bug Fixed!</title>
		<link>http://orionseven.com/blog/2009/12/09/followup-dbcc-checkfilegroup-bug-fixed/</link>
		<comments>http://orionseven.com/blog/2009/12/09/followup-dbcc-checkfilegroup-bug-fixed/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 22:43:47 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=45</guid>
		<description><![CDATA[In November I was quite disappointed. The DBCC CHECKFILEGROUP bugI had come across in September had made it into the Cumulative Update 8 for SQL Server 2008, but not in the Cumulative Update 5 for SQL 2008 SP1 branch. Being that I prefer to keep up on the service packs I was out of luck. Apparently it [...]]]></description>
			<content:encoded><![CDATA[<p>In November I was quite disappointed. The <a href="http://orionseven.com/blog/2009/09/22/dbcc-checkfilegroup-bug-in-sql-server-2008/">DBCC CHECKFILEGROUP bug</a>I had come across in September had made it into the Cumulative Update 8 for SQL Server 2008, but not in the Cumulative Update 5 for SQL 2008 SP1 branch. Being that I prefer to keep up on the service packs I was out of luck. Apparently it had not passed quality control for the SP1 branch.</p>
<p>However, I was told at the time that it would be a forth coming commulative update in January. Not wanting to wait another two months I put forth my business need for it and now a <a href="http://support.microsoft.com/kb/970365/en-us">Hotfix is available for it</a>!</p>
<p>If you&#8217;ve been stuck without being able to do DBCC CHECKFILEGROUP&#8217;s I hope you go grab this and get back to having that warm feeling inside knowing your data files are in good shape.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2009/12/09/followup-dbcc-checkfilegroup-bug-fixed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Table-Valued Parameters in SQL Server 2008 and C#</title>
		<link>http://orionseven.com/blog/2009/09/30/using-table-valued-parameters-in-sql-server-2008-and-c/</link>
		<comments>http://orionseven.com/blog/2009/09/30/using-table-valued-parameters-in-sql-server-2008-and-c/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 20:28:22 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=20</guid>
		<description><![CDATA[Until recently I had not had an opportunity to use Table-Valued Parameters a new feature in SQL Server 2008. I had looked at them briefly, thought they were a nice addition, and then moved on. Finally though, I found a chance to use them. The intended use for Table-Valued Parameters is of course to send [...]]]></description>
			<content:encoded><![CDATA[<p>Until recently I had not had an opportunity to use <a href="http://msdn.microsoft.com/en-us/library/bb510489.aspx">Table-Valued Parameters</a> a new feature in SQL Server 2008. I had looked at them briefly, thought they were a nice addition, and then moved on. Finally though, I found a chance to use them.</p>
<p>The intended use for Table-Valued Parameters is of course to send multiple rows of data to SQL Server from the client. Previous ways to do this involved calling a single stored procedure repeatedly, using XML, using SQLBulkCopy, or my least favorite, creating a stored procedure with many parameters. Each of these methods had draw backs. Calling a single stored procedure over and over works just fine (and was my preferred method) but you are creating a lot of traffic for something that should be simple. XML was nice too, but depending on the complexity of what you are sending you will need a lot of XQuery in your stored procedure; making something simple much more complex. SQLBulkCopy works great, I’ve used it before, but sometimes you may want to do more to your data once it is at the database. Thankfully table-valued parameters solve many of these short comings.</p>
<p>You can use table-valued parameters from your application with DataTables, DbDataReader, or IEnumerable objects. The majority of examples for table-valued parameters are done using DataTables. The problem I have with DataTables is that this seems like too much of an ad-hoc method with more overhead then is needed. Whereas going the IEnumerable route lets you create and use objects that you would likely already be using. This is the route I prefer, and the one I will demonstrate.</p>
<p>For this example assume we have a database of people and each of the people may have one or more aliases. They must be rather shady people. Here is the table for storing the people:</p>
<blockquote>
<pre>CREATE TABLE tbl_Person
(
      [ID] INT IDENTITY(1,1) NOT NULL,
      [FirstName] VARCHAR(20) NOT NULL,
      [LastName] VARCHAR(20) NOT NULL
)</pre>
</blockquote>
<p>It is quite simple, an identity field called ID to give everyone a unique number and a first and last name.</p>
<p>Now we have a table to store their aliases:</p>
<blockquote>
<pre>CREATE TABLE tbl_Alias
(
      [ID] INT NOT NULL,
      [FirstName] VARCHAR(20) NOT NULL,
      [LastName] VARCHAR(20) NULL
)</pre>
</blockquote>
<p>Another simple table to keep our shady people’s aliases; let’s pretend for ease of use there are primary keys and foreign keys shall we?</p>
<p>To add to this table we will use a stored procedure, my favorite mechanism to get data to the database. Why? Because you give the DBA something concrete upon which they can optimize your database, among other reasons. But that’s another post.</p>
<p>Our stored procedure will be an inserting stored procedure which will add our new shady person and their aliases in one call. Thus we will need to<a href="http://msdn.microsoft.com/en-us/library/ms175007.aspx"> create our user-defined table type</a>  first.</p>
<blockquote>
<pre>CREATE TYPE udt_tbl_Alias AS TABLE
(
      [FirstName] VARCHAR(20) NOT NULL,
      [LastName] VARCHAR(20) NULL
)</pre>
</blockquote>
<p>Again, nothing complicated. You will see why I left off the ID field in a bit.</p>
<p>You should note that you cannot use ALTER commands on user-defined table types. So if you want to update the table type later you will have drop it and create it. But if it is being used by a stored procedure you will have to temporarily comment that out of your stored procedure first, then drop the UDT, create the UDT again, and uncomment the UDT in your stored procedure. So plan ahead! Having planned ahead, here is our stored procedure for inserting:</p>
<blockquote>
<pre>CREATE PROCEDURE usp_ins_Person
      @FirstName VARCHAR(20),
      @LastName VARCHAR(20),
      @Aliases udt_tbl_Alias READONLY
AS
BEGIN
      SET NOCOUNT ON

      INSERT INTO tbl_Person VALUES (@FirstName, @LastName)

      INSERT INTO tbl_Alias (ID, FirstName, LastName)
            SELECT @@IDENTITY [ID], FirstName, LastName FROM @Aliases
END</pre>
</blockquote>
<p>The stored procedure requires three parameters: a first name, a last name and the user-defined table-valued parameter. The table type must be marked as READONLY and thus you will not be able to update the table within the stored procedure, only select from it. Otherwise, the stored procedure is rather straight forward. The person is added to tbl_Person and the aliases are added to tbl_Alias. You can see why I chose not to have the ID part of the user-defined table type, since we will not the ID till the person has been inserted.</p>
<p>To use the stored procedure in SQL Server Management Studio you can do the following.</p>
<blockquote>
<pre>DECLARE @Aliases udt_tbl_Alias
DECLARE @FirstName VARCHAR(20) = 'Bryan'
DECLARE @LastName VARCHAR(20) = 'Smith'
 
INSERT INTO @Aliases VALUES ('Database', 'Guy'), ('DBA', NULL)
 
EXEC usp_ins_Person @FirstName, @LastName, @Aliases
 
SELECT * FROM tbl_Person
SELECT * FROM tbl_Alias</pre>
</blockquote>
<p>The output should look like this.</p>
<div id="attachment_19" class="wp-caption alignnone" style="width: 203px"><img class="size-full wp-image-19" title="udt_output" src="http://orionseven.com/blog/wp-content/uploads/2009/09/udt_output.png" alt="Output" width="193" height="139" /><p class="wp-caption-text">Output</p></div>
<p>Great, we’re halfway there! The database side of things is taken care of, now we will need to take care of our client. Within the client code we will create a Person class. The class will have a property for the first name, last name, and aliases. This is why I like the IEnumerable route; it makes sense to store the aliases for a person with the person, and doing so as a list makes sense.</p>
<p>Person Class:</p>
<blockquote>
<pre>
namespace TestUDTApplication
{
    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public AliasCollection Aliases { get; set; }
 
        public Person(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
            Aliases = new AliasCollection();
        }
    }
}</pre>
</blockquote>
<p>Alias Class:</p>
<blockquote>
<pre>
namespace TestUDTApplication
{
    class Alias
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
 
        public Alias(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    }
}</pre>
</blockquote>
<p>AliasCollection Class:</p>
<blockquote>
<pre>
using System.Collections.Generic;
using System.Data;
using Microsoft.SqlServer.Server;
 
namespace TestUDTApplication
{
    class AliasCollection : List&lt;Alias&gt;, IEnumerable&lt;SqlDataRecord&gt;
    {
        IEnumerator&lt;SqlDataRecord&gt; IEnumerable&lt;SqlDataRecord&gt;.GetEnumerator()
        {
            SqlDataRecord ret = new SqlDataRecord(
                new SqlMetaData("FirstName", SqlDbType.VarChar, 20),
                new SqlMetaData("LastName", SqlDbType.VarChar, 20)
                );
 
            foreach (Alias alias in this)
            {
                ret.SetString(0, alias.FirstName);
                ret.SetString(1, alias.LastName);
                yield return ret;
            }
        }
    }
}</pre>
</blockquote>
<p>Let’s look over this code. First off the Person class has three public properties. FirstName, LastName, and Aliases. The Aliases property is an instance of the AliasCollection class, which inherits the Alias class as a List and then implements the IEnumerable interface. The List&lt;Alias&gt; turns our Alias into a List, which is perfect for handling our aliases within the client code.</p>
<p>The implementation IEnumerable&lt;SqlDataRecord&gt; is what will let us use our List as the input to our user-defined table. Specifically we are implementing IEnumerable with <a href="http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqldatarecord.aspx">SqlDataRecord</a>, this represents a single row of data and its associated metadata. This is what ADO.Net and SQL Server will need to map our list of aliases to our user-defined table. The <a href="http://msdn.microsoft.com/en-us/library/bb675163.aspx">documentation</a> is not really clear on this part unfortunately, it leads you to believe that anything that implements IEnumerable should suffice, however; what you must have is IEnumerable with SqlDataReader. This does not come out of the box with List&lt;Alias&gt; so we create our own, otherwise we’ll get an InvalidCastException.</p>
<p>Finally, from our client, using the <a href="http://msdn.microsoft.com/en-us/library/cc467894.aspx">Enterprise Library Data Access</a>, we can load people and aliases using a user-defined table type.</p>
<blockquote>
<pre>
Person person = new Person("Bryan", "Smith");
person.Aliases.Add(new Alias("DBA", "Dude"));
person.Aliases.Add(new Alias("Database", "Guy"));
 
SqlDatabase db = (SqlDatabase)DatabaseFactory.CreateDatabase("UDTTest");
DbCommand cmd = db.GetStoredProcCommand("usp_ins_Person");
 
db.AddInParameter(cmd, "@FirstName", DbType.String, person.FirstName);
db.AddInParameter(cmd, "@LastName", DbType.String, person.LastName);
db.AddInParameter(cmd, "@Aliases", SqlDbType.Structured, person.Aliases);
 
db.ExecuteNonQuery(cmd);</pre>
</blockquote>
<p>I know personally, I’ll be using this method from now one whenever possible over using user-defined tables with ad-hoc DataTables to load data, or heaven forbid calling the same stored procedure repeatedly.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2009/09/30/using-table-valued-parameters-in-sql-server-2008-and-c/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>DBCC CHECKFILEGROUP bug in SQL Server 2008</title>
		<link>http://orionseven.com/blog/2009/09/22/dbcc-checkfilegroup-bug-in-sql-server-2008/</link>
		<comments>http://orionseven.com/blog/2009/09/22/dbcc-checkfilegroup-bug-in-sql-server-2008/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 18:26:08 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=16</guid>
		<description><![CDATA[I noticed Cumulative Update 4 for SQL Server 2008 is out now. In it I found not one but two issues fixed that affect me. Thankfully, both issues have a relatively minor impact on my systems. 

However, the fix that I want to see, is not in this Cumulative Update. It’s a fix for DBCC CHECKFILEGROUP not working on file groups that are part of a partitioned table.

DBCC CHECKFILEGROUP runs the normal DBCC CHECKDB commands, but only on the specified file group. This is quite handy when you’re dealing with a very large database (VLDB); say one in the multi terabyte range, because a CHECKDB command can take an awful long time to run on huge files. Thus one common practice, championed by Paul Randal is to run DBCC CHECKFILEGROUP regularly on each file group. This lets you break up a really long process into manageable chunks. 

Of course, what I did not know until recently is that DBCC CHECKFILEGROUP doesn’t work in right in SQL Server 2008. In fact it just skips the specified file if it is part of a partition. In my case I have a 13TB database that uses partitioning heavily. After conversion from 2005 to 2008 I went to run my DBCC checks, as I normally do, to find that it wasn’t doing the check. File groups that would take 40 minute returned in seconds and upon examination of the output the file group was being skipped. 

So blissfully thinking that someone else must have seen this I did some Google Kung-Fu … and found nothing. 

Then I did some posting on forums ... and found nothing (well I did find some nice MVP’s). 

So then I called up Microsoft Premier Support, gave them my repro script and found out that I had found a bug.
]]></description>
			<content:encoded><![CDATA[<p><strong>Update 2009-12-09: </strong>Commulative Update 8 for SQL Server 2008 and a subsequent Hotfix after Commulative Update 5 for SQL Server 2008 SP1 have corrected this issue. So if you haven&#8217;t been able to run DBCC CHECKFILEGROUP&#8217;s go grab these!</p>
<p>I noticed <a href="http://support.microsoft.com/kb/973602">Cumulative Update 4 for SQL Server 2008 is out now</a>. In it I found not <a href="http://support.microsoft.com/kb/973204/">one</a> but <a href="http://support.microsoft.com/kb/973255/">two</a> issues fixed that affect me. Thankfully, both issues have a relatively minor impact on my systems. </p>
<p>However, the fix that I want to see, is not in this Cumulative Update. It’s a fix for DBCC CHECKFILEGROUP not working on file groups that are part of a partitioned table.</p>
<p>DBCC CHECKFILEGROUP runs the normal DBCC CHECKDB commands, but only on the specified file group. This is quite handy when you’re dealing with a very large database (VLDB); say one in the multi terabyte range, because a CHECKDB command can take an awful long time to run on huge files. Thus one common practice, championed by <a href="http://www.sqlskills.com/BLOGS/PAUL/post/CHECKDB-From-Every-Angle-Consistency-Checking-Options-for-a-VLDB.aspx">Paul Randal</a> is to run DBCC CHECKFILEGROUP regularly on each file group. This lets you break up a really long process into manageable chunks. </p>
<p>Of course, what I did not know until recently is that DBCC CHECKFILEGROUP doesn’t work in right in SQL Server 2008. In fact it just skips the specified file if it is part of a partition. In my case I have a 13TB database that uses partitioning heavily. After conversion from 2005 to 2008 I went to run my DBCC checks, as I normally do, to find that it wasn’t doing the check. File groups that would take 40 minute returned in seconds and upon examination of the output the file group was being skipped. </p>
<p>So blissfully thinking that someone else must have seen this I did some Google Kung-Fu … and found nothing. </p>
<p>Then I did some posting on forums &#8230; and found nothing (well I did find some nice MVP’s). </p>
<p>So then I called up Microsoft Premier Support, gave them my repro script and found out that I had found a bug.</p>
<p>Here’s the script in question, so you can try it out. This is for SQL Server 2008 RTM and SP1, Enterprise and Developer editions, and I’ve tried it out on Windows 7, Server 2003 and Server 2008. </p>
<blockquote><p>USE [master]</p>
<p>GO</p>
<pre>-- -------------------------------------------------------------</pre>
<p>&#8211; Create the test database</p>
<pre>-- -------------------------------------------------------------</pre>
<p>CREATE DATABASE [TestFileGroup] ON  PRIMARY (</p>
<p>      NAME = N&#8217;TestFileGroup&#8217;,</p>
<p>      FILENAME = N&#8217;J:\Data_Staging\MSSQL10.STAGING\MSSQL\Data\TestFileGroup.mdf&#8217; , &#8212; Update the path</p>
<p>      SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB</p>
<p>),</p>
<p>FILEGROUP [FG_1]</p>
<p>(</p>
<p>      NAME = N&#8217;FG_1&#8242;,</p>
<p>      FILENAME = N&#8217;J:\Data_Staging\MSSQL10.STAGING\MSSQL\Data\FG_1.ndf&#8217; , &#8212; Update the path</p>
<p>      SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB</p>
<p>),</p>
<p>FILEGROUP [FG_2]</p>
<p>(</p>
<p>      NAME = N&#8217;FG_2&#8242;,</p>
<p>      FILENAME = N&#8217;J:\Data_Staging\MSSQL10.STAGING\MSSQL\Data\FG_2.ndf&#8217; , &#8212; Update the path</p>
<p>      SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB</p>
<p>)</p>
<p>LOG ON</p>
<p>(</p>
<p>      NAME = N&#8217;TestFileGroup_log&#8217;,</p>
<p>      FILENAME = N&#8217;J:\Logs_Staging\MSSQL10.STAGING\MSSQL\Data\TestFileGroup_log.ldf&#8217; , &#8212; Update the path</p>
<p>      SIZE = 2048KB , MAXSIZE = 2048GB , FILEGROWTH = 10%</p>
<p>)</p>
<p>GO</p>
<p> USE [TestFileGroup]</p>
<p>GO</p>
<p> &#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>&#8211; Create the partition function</p>
<p>&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>CREATE PARTITION FUNCTION [myRangePF](int)</p>
<p>AS RANGE LEFT FOR VALUES (5)</p>
<p>GO</p>
<p> &#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>&#8211; Create the partition scheme</p>
<p>&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>CREATE PARTITION SCHEME [myRangePS]</p>
<p>AS PARTITION [myRangePF]</p>
<p>TO ([FG_1], [FG_2])</p>
<p>GO</p>
<p> &#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>&#8211; Create a partitioned table on myRangePS</p>
<p>&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>CREATE TABLE [dbo].[myPartitionTest]</p>
<p>(</p>
<p>      [Id] [int] IDENTITY(1,1) NOT NULL,</p>
<p>      [Data] [varchar](10) NULL</p>
<p>) ON myRangePS (Id)</p>
<p> &#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>&#8211; Insert Test Data, Enough to cross both partitions</p>
<p>&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 1&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 2&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 3&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 4&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 5&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 6&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 7&#8242;)</p>
<p> INSERT INTO myPartitionTest</p>
<p>VALUES (&#8216;Test 8&#8242;)</p>
<p> SELECT * FROM myPartitionTest</p>
<p> &#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>&#8211; Run DBCC CHECKFILEGROUP</p>
<p>&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>DBCC CHECKFILEGROUP (&#8216;FG_1&#8242;)</p>
<p>/*</p>
<p>      Expect it to show it found 5 rows on the object myPartitionTest and also to say it couldn&#8217;t check FG_2.</p>
<p>*/</p>
<p> DBCC CHECKFILEGROUP (&#8216;FG_2&#8242;)</p>
<p>/*</p>
<p>      Expect it to show it found 3 rows on the object myPartitionTest and also to say it couldn&#8217;t check FG_1.</p>
<pre>*/</pre>
</blockquote>
<p>As you can see, the script is fairly simple. It creates a database with a couple of extra file groups, then proceeds to make a partition function and scheme with a table to go use them. Then it adds some data to the table, so data will reside on both partitions. Finally it does a DBCC CHECKFILEGROUP command and this is where it gets interesting.</p>
<p>What should happen when you run CHECKFILEGROUP (‘FG_1’) is that it will say it cannot check data on FG_2, Primary, etc, but will return results for the checks it ran on FG_1. But what actually happens is it returns what it can’t check and doesn’t do any checks on FG_1.</p>
<p>So there you have it, I’m hoping that Cumulative Update 5 will have the fix I need. I know a few others who run VLDB’s and this is disappointing news for them as well. Hopefully, this will get enough attention and will warrant a quick fix.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2009/09/22/dbcc-checkfilegroup-bug-in-sql-server-2008/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Do you certify?</title>
		<link>http://orionseven.com/blog/2009/09/21/do-you-certify/</link>
		<comments>http://orionseven.com/blog/2009/09/21/do-you-certify/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 17:31:35 +0000</pubDate>
		<dc:creator>Bryan Smith</dc:creator>
				<category><![CDATA[Certification]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Microsoft Certification]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://orionseven.com/blog/?p=12</guid>
		<description><![CDATA[I’m currently preparing to take the test to become a Microsoft Certified Technology Specialist. More specifically I’m taking exam 70-432 to achieve the “MCTS: SQL Server 2008, Implementation and Maintenance” certification. The title is quite a mouthful. I’ve followed the Microsoft database certs for quite a while now and have watched them grow and become [...]]]></description>
			<content:encoded><![CDATA[<p>I’m currently preparing to take the test to become a Microsoft Certified Technology Specialist. More specifically I’m taking exam 70-432 to achieve the “MCTS: SQL Server 2008, Implementation and Maintenance” certification. The title is quite a mouthful.</p>
<p>I’ve followed the Microsoft database certs for quite a while now and have watched them grow and become more specialized as many other MS certs have as well. As it currently stands there are six certifications for SQL Server 2008. Not counting the Microsoft Certified Master and Microsoft Certified Architect tracts. The six core tests are divided into three tracts: Implementation and Maintenance, Development, Business Intelligence. Each of these tracks are divided into the Technology Specialist (MCTS) level and the “Pro” level the “Microsoft Certified IT Professional”.</p>
<p>Thus if you are a pure-DBA, only playing in the Implementation and Maintenance realm of SQL Server you can get your MCTS and then MCITP in just that realm. Or if like myself you are both a developer, dba and do work in BI you may end up wanting to go the full gauntlet.</p>
<p>As it stands though, that’s six tests. I’m committed to the MCTS for Implementation and Maintenance as well as 70-433, MCTS in Database Development. After that I plan to evaluate whether to continue on.</p>
<p>In fact, those two certifications will be my first. I toyed with the idea of getting certified in SQL 2005 but never bit the bullet. After some contemplation, I’ve found that I want to become certified in SQL Server 2008.</p>
<p>I’m using the certification process to be sure I’m up to snuff in all areas concerning SQL 2008, as my primary environment is now SQL 2008 and I expect that I’ll have my entire environment upgraded to SQL 2008 by the end of the year. I feel quite lucky in this, as I know many people who are still in SQL 2000, just looking to go to 2005 or have quite a mix of 2000, 2005 and 2008.</p>
<p>Others use certifications as a statement for their resume. Which is nice, but I think it is commonly known that certification does not make an expert. Certification is simply another litmus test of someone’s proficiency.</p>
<p>For me though, I’ll become certified, and that’s quite nice I suppose, but more importantly I’ll have a nice focused avenue to be sure I’m up to date fully on the new capabilities of SQL Server 2008. I like nice concise packages and with how Microsoft certifications are now done this fits the billet.</p>
]]></content:encoded>
			<wfw:commentRss>http://orionseven.com/blog/2009/09/21/do-you-certify/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

