<?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>codegumbo &#187; Code</title>
	<atom:link href="http://codegumbo.com/index.php/category/development/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://codegumbo.com</link>
	<description>Laissez Les Bon Code Roulez!</description>
	<lastBuildDate>Fri, 03 Feb 2012 00:43:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quick and Easy SQL Script</title>
		<link>http://codegumbo.com/index.php/2012/02/02/quick-and-easy-sql-script/</link>
		<comments>http://codegumbo.com/index.php/2012/02/02/quick-and-easy-sql-script/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 00:43:59 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://codegumbo.com/?p=545</guid>
		<description><![CDATA[I haven’t been blogging enough lately, so I’m going to try something new to get past this mild case of writer’s block.&#160; Instead of trying to do a long, in-depth post on some esoteric subject, I’m going to just put out a simple SQL script.&#160; This one’s a bit of a hack, but you’ll see [...]]]></description>
			<content:encoded><![CDATA[<p>I haven’t been blogging enough lately, so I’m going to try something new to get past this mild case of writer’s block.&#160; Instead of trying to do a long, in-depth post on some esoteric subject, I’m going to just put out a simple SQL script.&#160; This one’s a bit of a hack, but you’ll see a lot of variations on it: <strong>Coalescing rows using for XML</strong>.&#160; For example, here’s a few questions from StackOverflow:</p>
<p><a href="http://stackoverflow.com/questions/7872507/cursor-in-stored-procedure">Cursor in stored procedure</a></p>
<p><a href="http://stackoverflow.com/questions/5536754/how-to-comma-separate-multiple-rows-obtained-from-a-sql-query">How to Comma separate multiple rows obtained from a SQL Query</a></p>
<p><a href="http://stackoverflow.com/questions/887628/convert-multiple-rows-into-one-with-comma-as-separator">Convert multiple rows into one with comma as separator</a></p>
<p>The basic challenge is to denormalize your resultset so that multiple rows get returned as a single delimited string; while there are several methods for solving this problem, the one that I like (as of SQL 2005) is to use FOR XML PATH, like so:</p>
<p> <code style="font-size: 12px"><span style="color: blue">BEGIN TRAN      </p>
<p>DECLARE </span><span style="color: #434343">@t </span><span style="color: blue">TABLE </span><span style="color: gray">( </span><span style="color: black">fruit </span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span><span style="color: black">10</span><span style="color: gray">) )      </p>
<p></span><span style="color: blue">INSERT&#160; INTO </span><span style="color: #434343">@t      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">( </span><span style="color: black">fruit      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">SELECT&#160; </span><span style="color: red">'apple'      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">UNION </span><span style="color: gray">ALL      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">SELECT&#160; </span><span style="color: red">'banana'      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">UNION </span><span style="color: gray">ALL      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">SELECT&#160; </span><span style="color: red">'tomato'      </p>
<p></span><span style="color: blue">SELECT&#160; </span><span style="color: red">',' </span><span style="color: gray">+ </span><span style="color: black">fruit      <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: #434343">@t      <br /></span><span style="color: blue">FOR&#160;&#160;&#160;&#160; XML </span><span style="color: black">PATH      </p>
<p></span><span style="color: blue">SELECT&#160; </span><span style="color: red">',' </span><span style="color: gray">+ </span><span style="color: black">fruit      <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: #434343">@t      <br /></span><span style="color: blue">FOR&#160;&#160;&#160;&#160; XML </span><span style="color: black">PATH</span><span style="color: gray">(</span><span style="color: red">''</span><span style="color: gray">)      </p>
<p></span><span style="color: blue">SELECT&#160; </span><span style="color: magenta">STUFF</span><span style="color: gray">(( </span><span style="color: blue">SELECT&#160; </span><span style="color: red">',' </span><span style="color: gray">+ </span><span style="color: black">fruit      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: #434343">@t      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">FOR      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XML </span><span style="color: black">PATH</span><span style="color: gray">(</span><span style="color: red">''</span><span style="color: gray">)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ), </span><span style="color: black">1</span><span style="color: gray">, </span><span style="color: black">1</span><span style="color: gray">, </span><span style="color: red">''</span><span style="color: gray">) </span><span style="color: blue">AS </span><span style="color: black">fruits      </p>
<p></span><span style="color: blue">ROLLBACK      <br /></span></code>
<p>&#160;</p>
<p>The multiple results sets are there to illustrate each step in the process; for example, the first output shows what happens when you specify FOR XML PATH with no indicators; SQL Server automatically assigns each row in the resultset to a node named &lt;row&gt;:</p>
<blockquote><p>&lt;row&gt;,apple&lt;/row&gt;      <br />&lt;row&gt;,banana&lt;/row&gt;       <br />&lt;row&gt;,tomato&lt;/row&gt;</p>
</blockquote>
<p>If you specify a tag name in the PATH function, each row will be replaced with that tag name; in the above example, we want an empty tag (‘’).&#160; The result is an XML fragment with no tags:</p>
<blockquote><p>,apple,banana,tomato</p>
</blockquote>
<p>That&#8217;s almost what we want, except we need to get rid of the leading comma.&#160; The STUFF command basically replaces the characters in the string supplied (the first parameter; our query FOR XML PATH) starting at a certain position (1 in the example above) and moving forward the specified number of character places (1, the third parameter) with the value of the last parameter (an empty space; the fourth parameter).&#160; The final output is a comma delimited string:</p>
<blockquote><p>apple,banana,tomato</p>
</blockquote>
<p>Straightforward; gotta return to writing.</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2012/02/02/quick-and-easy-sql-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presenting tonight&#8230;</title>
		<link>http://codegumbo.com/index.php/2011/11/01/presenting-tonight/</link>
		<comments>http://codegumbo.com/index.php/2011/11/01/presenting-tonight/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 15:12:23 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/11/01/presenting-tonight/</guid>
		<description><![CDATA[In a few minutes, I’m packing up to head to Greenville, SC to work from the first WiFi-enabled sandwich shop I can find.&#160; Tonight I’m presenting at the SQL Server Innovators Guild on the subject of Very Large DataBases, but I’ve still got a few hours of work ahead of me.&#160; If you’re in the [...]]]></description>
			<content:encoded><![CDATA[<p>In a few minutes, I’m packing up to head to Greenville, SC to work from the first WiFi-enabled sandwich shop I can find.&nbsp; Tonight I’m presenting at the <a href="http://ssig.sqlpass.org/" target="_blank">SQL Server Innovators Guild</a> on the subject of Very Large DataBases, but I’ve still got a few hours of work ahead of me.&nbsp; If you’re in the Greenville area, and you want to heckle me, come find me.</p>
<p><a title="http://www.eventbrite.com/org/20324281" href="http://www.eventbrite.com/org/20324281">http://www.eventbrite.com/org/20324281</a></p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/11/01/presenting-tonight/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stuff in the FROM clause: Virtual Structures</title>
		<link>http://codegumbo.com/index.php/2011/10/31/stuff-in-the-from-clause-virtual-structures/</link>
		<comments>http://codegumbo.com/index.php/2011/10/31/stuff-in-the-from-clause-virtual-structures/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 18:43:48 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Something New]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/10/31/stuff-in-the-from-clause-virtual-structures/</guid>
		<description><![CDATA[Continuing with my SQL Server basics series, I’m focusing this post on Stuff in the FROM clause: Virtual Structures.&#160; My last post talked about the only Base structure in a relational database, but I’m now moving on to a slightly more complicated concept.&#160; Virtual structures are database objects that don’t hold data in a tabular [...]]]></description>
			<content:encoded><![CDATA[<p>Continuing with my <a href="http://codegumbo.com/index.php/2011/10/17/stuff-in-the-from-clause-table/">SQL Server basics series</a>, I’m focusing this post on Stuff in the FROM clause: Virtual Structures.&#160; My last post talked about the only Base structure in a relational database, but I’m now moving on to a slightly more complicated concept.&#160; Virtual structures are database objects that don’t hold data in a tabular structure, but can interface with data in a tabular format.&#160; It’s probably best to start with the most common virtual structure, the VIEW:</p>
<h1>VIEWs</h1>
<p>According to <a href="http://msdn.microsoft.com/en-us/library/ms187956.aspx" target="_blank">Books Online</a>, VIEWs create &quot;a virtual table whose contents (columns and rows) are defined by a query. Use this statement to create a view of the data in one or more tables in the database.”&#160; A view encapsulates a SQL SELECT statement to return data, and can be used to provide an alternate representation of data from the original tables.&#160; For example, the following VIEW returns columns from both the Person and Employees tables in the AdventureWorks sample database:</p>
<p> <code style="font-size: 12px"><span style="color: black">     <br /></span><span style="color: blue">USE </span><span style="color: black">AdventureWorks2008R2 </span><span style="color: gray">;      <br /></span><span style="color: black">GO      <br /></span><span style="color: blue">IF </span><span style="color: magenta">OBJECT_ID </span><span style="color: gray">(</span><span style="color: red">'hiredate_view'</span><span style="color: gray">, </span><span style="color: red">'V'</span><span style="color: gray">) </span><span style="color: blue">IS </span><span style="color: gray">NOT NULL      <br /></span><span style="color: blue">DROP VIEW </span><span style="color: black">hiredate_view </span><span style="color: gray">;      <br /></span><span style="color: black">GO      <br /></span><span style="color: blue">CREATE VIEW </span><span style="color: black">hiredate_view      <br /></span><span style="color: blue">AS      <br />SELECT </span><span style="color: black">p.FirstName</span><span style="color: gray">, </span><span style="color: black">p.LastName</span><span style="color: gray">, </span><span style="color: black">e.BusinessEntityID</span><span style="color: gray">, </span><span style="color: black">e.HireDate      <br /></span><span style="color: blue">FROM </span><span style="color: black">HumanResources.Employee e      <br /></span><span style="color: blue">JOIN </span><span style="color: black">Person.Person </span><span style="color: blue">AS </span><span style="color: black">p </span><span style="color: blue">ON </span><span style="color: black">e.BusinessEntityID </span><span style="color: blue">= </span><span style="color: black">p.BusinessEntityID </span><span style="color: gray">;      <br /></span><span style="color: black">GO      </p>
<p></span></code>
<p>Views are not just read-only; in certain cases, VIEWS can be used to insert or update data into underlying tables.&#160; However, discussion of how this works is beyond the intent of this introduction; refer to Books Online fore more information.</p>
<h1>Table-Valued Functions (TVF)</h1>
<p>Views are not the only virtual structures available in SQL Server; a subset of a user-defined function known as table-valued functions (TVFs) also provide interfaces into the underlying base structures.&#160;&#160; <a href="http://msdn.microsoft.com/en-us/library/ms186755.aspx" target="_blank">Books Onlin</a>e defines table-valued functions as “a Transact-SQL or common language runtime (CLR) routine that accepts parameters, performs an action, such as a complex calculation, and returns the result of that action as… a table.”&#160; There are three types of TVF’s (arranged below in order of increasing complexity): <strong>simple</strong>, <strong>complex</strong>, and <strong>Common Language Runtime</strong>.</p>
<h2>Simple TVFs</h2>
<p>A simple (or inline) table-valued function is probably the easiest virtual structure to grasp beyond a view; in fact, it’s easily compared to a view with parameters.&#160; A simple TVF encapsulates a SQL statement (much like a view), but it allows for the use of parameters to filter the results returned.&#160; For example, the following simple TVF pulls data from multiple tables for a specific StoreID:</p>
<p> <code style="font-size: 12px"><span style="color: blue">USE </span><span style="color: black">AdventureWorks2008R2</span><span style="color: gray">;      <br /></span><span style="color: black">GO      <br /></span><span style="color: blue">IF </span><span style="color: magenta">OBJECT_ID </span><span style="color: gray">(</span><span style="color: red">N'Sales.ufn_SalesByStore'</span><span style="color: gray">, </span><span style="color: red">N'IF'</span><span style="color: gray">) </span><span style="color: blue">IS </span><span style="color: gray">NOT NULL      <br />&#160;&#160;&#160; </span><span style="color: blue">DROP FUNCTION </span><span style="color: black">Sales.ufn_SalesByStore</span><span style="color: gray">;      <br /></span><span style="color: black">GO      <br /></span><span style="color: blue">CREATE FUNCTION </span><span style="color: black">Sales.ufn_SalesByStore </span><span style="color: gray">(</span><span style="color: #434343">@storeid </span><span style="color: blue">INT</span><span style="color: gray">)      <br /></span><span style="color: blue">RETURNS TABLE      <br />AS       <br />RETURN       <br /></span><span style="color: gray">(      <br />&#160;&#160;&#160; </span><span style="color: blue">SELECT </span><span style="color: black">P.ProductID</span><span style="color: gray">, </span><span style="color: black">P.Name</span><span style="color: gray">, </span><span style="color: magenta">SUM</span><span style="color: gray">(</span><span style="color: black">SD.LineTotal</span><span style="color: gray">) </span><span style="color: blue">AS </span><span style="color: red">'Total'      <br />&#160;&#160;&#160; </span><span style="color: blue">FROM </span><span style="color: black">Production.Product </span><span style="color: blue">AS </span><span style="color: black">P      <br />&#160;&#160;&#160; </span><span style="color: blue">JOIN </span><span style="color: black">Sales.SalesOrderDetail </span><span style="color: blue">AS </span><span style="color: black">SD </span><span style="color: blue">ON </span><span style="color: black">SD.ProductID </span><span style="color: blue">= </span><span style="color: black">P.ProductID      <br />&#160;&#160;&#160; </span><span style="color: blue">JOIN </span><span style="color: black">Sales.SalesOrderHeader </span><span style="color: blue">AS </span><span style="color: black">SH </span><span style="color: blue">ON </span><span style="color: black">SH.SalesOrderID </span><span style="color: blue">= </span><span style="color: black">SD.SalesOrderID      <br />&#160;&#160;&#160; </span><span style="color: blue">JOIN </span><span style="color: black">Sales.Customer </span><span style="color: blue">AS </span><span style="color: black">C </span><span style="color: blue">ON </span><span style="color: black">SH.CustomerID </span><span style="color: blue">= </span><span style="color: black">C.CustomerID      <br />&#160;&#160;&#160; </span><span style="color: blue">WHERE </span><span style="color: black">C.StoreID </span><span style="color: blue">= </span><span style="color: #434343">@storeid      <br />&#160;&#160;&#160; </span><span style="color: blue">GROUP BY </span><span style="color: black">P.ProductID</span><span style="color: gray">, </span><span style="color: black">P.Name      <br /></span><span style="color: gray">);      <br /></span><span style="color: black">GO      </p>
<p></span><span style="color: green">--use the new TVF in a query      <br /></span><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: blue">FROM </span><span style="color: black">Sales.ufn_SalesByStore </span><span style="color: gray">(</span><span style="color: black">602</span><span style="color: gray">);      </p>
<p></span></code><br />
<h2>Complex TVFs</h2>
<p>Complex (or multi-statement) TVF’s are much like their simple counterparts, but allow for greater flexibility in T-SQL coding by adopting a procedural approach to returning tabular data.&#160; A complex TVF requires that a table variable (to be covered later) be defined within the function, and then populated by a series of SQL statements.&#160; The below example from Books Online shows how:</p>
<p> <code style="font-size: 12px"><span style="color: blue">USE </span><span style="color: black">AdventureWorks2008R2</span><span style="color: gray">;     <br /></span><span style="color: black">GO     <br /></span><span style="color: blue">IF </span><span style="color: magenta">OBJECT_ID </span><span style="color: gray">(</span><span style="color: red">N'dbo.ufn_FindReports'</span><span style="color: gray">, </span><span style="color: red">N'TF'</span><span style="color: gray">) </span><span style="color: blue">IS </span><span style="color: gray">NOT NULL     <br />&#160;&#160;&#160; </span><span style="color: blue">DROP FUNCTION </span><span style="color: black">dbo.ufn_FindReports</span><span style="color: gray">;     <br /></span><span style="color: black">GO     <br /></span><span style="color: blue">CREATE FUNCTION </span><span style="color: black">dbo.ufn_FindReports </span><span style="color: gray">(</span><span style="color: #434343">@InEmpID </span><span style="color: black">INTEGER</span><span style="color: gray">)     <br /></span><span style="color: blue">RETURNS </span><span style="color: #434343">@retFindReports </span><span style="color: blue">TABLE      <br /></span><span style="color: gray">(     <br />&#160;&#160;&#160; </span><span style="color: black">EmployeeID </span><span style="color: blue">INT PRIMARY KEY </span><span style="color: gray">NOT NULL,     <br />&#160;&#160;&#160; </span><span style="color: black">FirstName </span><span style="color: blue">NVARCHAR</span><span style="color: gray">(</span><span style="color: black">255</span><span style="color: gray">) NOT NULL,     <br />&#160;&#160;&#160; </span><span style="color: black">LastName </span><span style="color: blue">NVARCHAR</span><span style="color: gray">(</span><span style="color: black">255</span><span style="color: gray">) NOT NULL,     <br />&#160;&#160;&#160; </span><span style="color: black">JobTitle </span><span style="color: blue">NVARCHAR</span><span style="color: gray">(</span><span style="color: black">50</span><span style="color: gray">) NOT NULL,     <br />&#160;&#160;&#160; </span><span style="color: black">RecursionLevel </span><span style="color: blue">INT </span><span style="color: gray">NOT NULL     <br />)      <br /></span><span style="color: green">--Returns a result set that lists all the employees who report to the      <br />--specific employee directly or indirectly.*/      <br /></span><span style="color: blue">AS     <br />BEGIN      <br />WITH </span><span style="color: black">EMP_cte</span><span style="color: gray">(</span><span style="color: black">EmployeeID</span><span style="color: gray">, </span><span style="color: black">OrganizationNode</span><span style="color: gray">, </span><span style="color: black">FirstName</span><span style="color: gray">, </span><span style="color: black">LastName</span><span style="color: gray">, </span><span style="color: black">JobTitle</span><span style="color: gray">, </span><span style="color: black">RecursionLevel</span><span style="color: gray">) </span><span style="color: green">-- CTE name and columns     <br />&#160;&#160;&#160; </span><span style="color: blue">AS </span><span style="color: gray">(     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">SELECT </span><span style="color: black">e.BusinessEntityID</span><span style="color: gray">, </span><span style="color: black">e.OrganizationNode</span><span style="color: gray">, </span><span style="color: black">p.FirstName</span><span style="color: gray">, </span><span style="color: black">p.LastName</span><span style="color: gray">, </span><span style="color: black">e.JobTitle</span><span style="color: gray">, </span><span style="color: black">0 </span><span style="color: green">-- Get the initial list of Employees for Manager n     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">FROM </span><span style="color: black">HumanResources.Employee e      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">INNER JOIN </span><span style="color: black">Person.Person p      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">ON </span><span style="color: black">p.BusinessEntityID </span><span style="color: blue">= </span><span style="color: black">e.BusinessEntityID     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">WHERE </span><span style="color: black">e.BusinessEntityID </span><span style="color: blue">= </span><span style="color: #434343">@InEmpID     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">UNION </span><span style="color: gray">ALL     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">SELECT </span><span style="color: black">e.BusinessEntityID</span><span style="color: gray">, </span><span style="color: black">e.OrganizationNode</span><span style="color: gray">, </span><span style="color: black">p.FirstName</span><span style="color: gray">, </span><span style="color: black">p.LastName</span><span style="color: gray">, </span><span style="color: black">e.JobTitle</span><span style="color: gray">, </span><span style="color: black">RecursionLevel </span><span style="color: gray">+ </span><span style="color: black">1 </span><span style="color: green">-- Join recursive member to anchor     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">FROM </span><span style="color: black">HumanResources.Employee e      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">INNER JOIN </span><span style="color: black">EMP_cte     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">ON </span><span style="color: black">e.OrganizationNode.GetAncestor</span><span style="color: gray">(</span><span style="color: black">1</span><span style="color: gray">) </span><span style="color: blue">= </span><span style="color: black">EMP_cte.OrganizationNode     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">INNER JOIN </span><span style="color: black">Person.Person p      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">ON </span><span style="color: black">p.BusinessEntityID </span><span style="color: blue">= </span><span style="color: black">e.BusinessEntityID     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">)     <br /></span><span style="color: green">-- copy the required columns to the result of the function      <br />&#160;&#160; </span><span style="color: blue">INSERT </span><span style="color: #434343">@retFindReports     <br />&#160;&#160; </span><span style="color: blue">SELECT </span><span style="color: black">EmployeeID</span><span style="color: gray">, </span><span style="color: black">FirstName</span><span style="color: gray">, </span><span style="color: black">LastName</span><span style="color: gray">, </span><span style="color: black">JobTitle</span><span style="color: gray">, </span><span style="color: black">RecursionLevel     <br />&#160;&#160; </span><span style="color: blue">FROM </span><span style="color: black">EMP_cte      <br />&#160;&#160; </span><span style="color: blue">RETURN     <br />END</span><span style="color: gray">;     <br /></span><span style="color: black">GO     <br /></span><span style="color: green">-- Example invocation     <br /></span><span style="color: blue">SELECT </span><span style="color: black">EmployeeID</span><span style="color: gray">, </span><span style="color: black">FirstName</span><span style="color: gray">, </span><span style="color: black">LastName</span><span style="color: gray">, </span><span style="color: black">JobTitle</span><span style="color: gray">, </span><span style="color: black">RecursionLevel     <br /></span><span style="color: blue">FROM </span><span style="color: black">dbo.ufn_FindReports</span><span style="color: gray">(</span><span style="color: black">1</span><span style="color: gray">);      </p>
<p></span><span style="color: black">GO     </p>
<p></span></code>
<p>Note that code in a multi-statement TVF can involve several steps before returning the final result-set; caution should be used when using complex TVF’s because the optimizer can not determine the cost of these statements during plan estimation.&#160; In short, the more complex the TVF, the more likely that the plan used by SQL Server will be inaccurate.</p>
<h2>CLR TVF’s</h2>
<p>With the release of SQL Server 2005, Microsoft embedded a limited subset of the functionality from the .NET framework into SQL Server itself, calling it the Common Language Runtime (CLR).&#160; The CLR allows for .NET developers to write and deploy database objects in a managed language (like VB.NET or C#), and allows for very flexible logic for handling data.&#160; A CLR Function is invoked in a fashion similar to other table-valued functions, but the deployment is much more involved (see <a href="http://msdn.microsoft.com/en-us/library/ms186755.aspx" target="_blank">Books Online</a> for an example using the following steps):</p>
<ol>
<li>Code is written and assembled by a compiler (like Visual Studio).</li>
<li>The assembled code must be copied on to the SQL Server.</li>
<li>An ASSEMBLY reference is created in T-SQL, which points to the deployed .dll file, and</li>
<li>a FUNCTION is created which references the ASSEMBLY.</li>
</ol>
<h1>Next up…</h1>
<p>A two-fer: Temporary and Semi-Temporary structures!</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/10/31/stuff-in-the-from-clause-virtual-structures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stuff in the FROM clause: Base Structures</title>
		<link>http://codegumbo.com/index.php/2011/10/17/stuff-in-the-from-clause-table/</link>
		<comments>http://codegumbo.com/index.php/2011/10/17/stuff-in-the-from-clause-table/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 18:40:29 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/10/17/stuff-in-the-from-clause-table/</guid>
		<description><![CDATA[A few months ago, our user group started thinking about how we could get new members to start coming to our SQL Server user group meetings; we defined new user as one of two categories: 1: new to databases, or 2. new to SQL Server In both cases, we realized that we needed to start [...]]]></description>
			<content:encoded><![CDATA[<p>A few months ago, our user group started thinking about how we could get new members to start coming to our SQL Server user group meetings; we defined new user as one of two categories:</p>
<p>1: new to databases, or    <br />2. new to SQL Server</p>
<p>In both cases, we realized that we needed to start having new content in our monthly sessions that was targeted specifically for them, so we decided to start adding a brief 10-minute fundamental session to the beginning of each meeting. I chose to do the first one, and selected a topic called Stuff in the FROM clause. I quickly realized that this could be a nice little blog series, so I&#8217;m attempting to expand a 10-minute presentation into a four-part series. Below is the mind map for the presentation:</p>
<p>&#160;</p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://mail.google.com/mail/?attid=0.1&amp;disp=emb&amp;view=att&amp;th=13337641c75bd7cf" width="578" height="456" /></p>
<p><strong>Stuff in the FROM clause: Base Structures</strong></p>
<p>Base Structures as a category name is a bit misleading, because there&#8217;s really only one base structure in any relational database: the table.&#160; Tables are the core of any relational database; they provide storage for data in rows, arranged by columns.&#160; There’s lots of <a href="http://en.wikipedia.org/wiki/Database_table">background information</a> on table design, so I won’t spend too much time on it (even that’s too basic for this discussion), but I will highlight some key features about tables:</p>
<ul>
<li>From an entity design perspective, a table should represent a set of entities.</li>
<ul>
<li>Rows are the un-ordered members of that set</li>
<li>Columns are the attributes of the entity.</li>
</ul>
<li>Table attributes have basic types.</li>
<li>Tables should have a primary key constraint on one of the columns, which is used to uniquely identify a member of that set.</li>
<li>Microsoft SQL Server supports a syntax for computed columns, where data for an attribute can be calculated from other attributes.</li>
</ul>
<p>For Microsoft SQL Server, the CREATE TABLE syntax may be found at: <a title="http://msdn.microsoft.com/en-us/library/ms174979.aspx" href="http://msdn.microsoft.com/en-us/library/ms174979.aspx">http://msdn.microsoft.com/en-us/library/ms174979.aspx</a>&#160; The simplest table creation statement looks like the following:</p>
<blockquote><p>CREATE TABLE table_name (column_name column_type)</p>
</blockquote>
<p>Next: Virtual Structures</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/10/17/stuff-in-the-from-clause-table/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#TSQL2sDay Roundup</title>
		<link>http://codegumbo.com/index.php/2011/10/10/tsql2sday-roundup/</link>
		<comments>http://codegumbo.com/index.php/2011/10/10/tsql2sday-roundup/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 14:00:28 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Blogging is FUN!]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[TSQL2sDay]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/10/10/tsql2sday-roundup/</guid>
		<description><![CDATA[So the launch was early, and the write-up is delayed.&#160; Time has no meaning….&#160; Truthfully, I’m sorry I didn’t manage to squeeze this summary post in a bit sooner; I have the typical DBA excuse: too much to do, and too little time. One nice thing about this topic is that it seemed to resonate [...]]]></description>
			<content:encoded><![CDATA[<p>So the launch was early, and the write-up is delayed.&#160; Time has no meaning….&#160; Truthfully, I’m sorry I didn’t manage to squeeze this summary post in a bit sooner; I have the typical DBA excuse: too much to do, and too little time. </p>
<p>One nice thing about this topic is that it seemed to resonate with several bloggers who had either strayed away from T-SQL Tuesday or had never participated; hopefully, the bug to write will stick (and I’m pointing the finger at myself for this one as well).</p>
<h3>Beginning at the Beginning:</h3>
<p><img style="display: inline; float: left" alt="" align="left" src="http://1.gravatar.com/avatar/3ad80e5cd80033c4b574b34cc8ffe419?s=48&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://blog.sqlauthority.com">Pinal Dave</a> in his gentle teaching style covers several different <a href="http://blog.sqlauthority.com/2011/10/04/sql-server-quick-note-about-join-common-questions-and-simple-answers/" target="_blank">questions and answers</a> about JOIN techniques. Great way to review the basics and get conversations started with beginners.    </p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/ab17b5e1b1cbc40740e52336482b9807?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://kenj.blogspot.com">KenJ</a> is a bit esoteric, but a great reminder of what resources there are to learn more <a href="http://kenj.blogspot.com/2011/10/join-me.html">about SQL Server.</a></p>
<h3>&#160;</h3>
<h3>JOINs In The Real World:</h3>
<h2></h2>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/2007b7c6d81b6ed86710ece8e2d565e1?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://www.real-sql-guy.com">Tracy McKibben</a> demonstrated a very simple tuning tip based on real production experience: <a href="http://www.real-sql-guy.com/2011/09/t-sql-tuesday-23-nested-joins.html." target="_blank">the Nested JOIN</a></p>
<p>&#160;</p>
<p><a href="http://richbrownesq-sqlserver.blogspot.com">Rich Brown</a> reminds us that good query construction often involves understanding how the optimizer handles <a href="http://richbrownesq-sqlserver.blogspot.com/2011/10/t-sql-helping-optimiser-can-hinder.html">JOINs under the covers.</a></p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://1.gravatar.com/avatar/da3d144d9efe5d6b8e93aaaa2cc703a0?s=48&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://nebrasql.blogspot.com/">Andy Galbraith</a> (Yet Another SQL Andy!) reminds us to <a href="http://nebrasql.blogspot.com/2011/10/t-sql-tuesday-23-respect-your-joins.html">Respect Your JOINs</a>. It’s funny how often we assume that database queries are logically well-written when we start looking for performance problems.</p>
<p>&#160;</p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/e86f57ad09692dd6d39671898de98256?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://www.bobpusateri.com">Bob Pusateri</a> points out that <a href="http://www.bobpusateri.com/archive/2011/10/t-sql-tuesday-23-where-the-join-ends/">WHERE clauses influence JOIN behaviors</a>. You have to look at the entire SQL statement to make sure you’re getting what you’re supposed to be getting.    </p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/edceb5c6895ba54a06f1486dadeb7433?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://nelsonsweb.net">Matt Nelson</a> reminds us that <a href="http://nelsonsweb.net/2011/10/t-sql-tuesday-23-joins/">unnecessary JOINs are bad</a>, and sometimes you need to dig a little deeper when performance tuning.    </p>
<p>&#160;</p>
<h3>A Little Deeper:</h3>
<p><img style="display: inline; float: left" alt="" align="left" src="http://1.gravatar.com/avatar/94ee7f24a49e19b7779edcfe47a68a9e?s=48&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://sqlblog.com/blogs/rob_farley">Rob Farley</a> toasted my brain a little on this post about <a href="http://sqlblog.com/blogs/rob_farley/archive/2011/10/04/joins-without-join.aspx">Joins without JOINs</a>.&#160; It’s a well-written explanation of what an Ant-Semi JOIN is. </p>
<p>&#160;</p>
<p><a href="http://bradsruminations.blogspot.com">Brad Schulz</a> finished the cooking job with a <a href="http://bradsruminations.blogspot.com/2011/10/t-sql-tuesday-023-flip-side-of-join.html">take on Semi-JOINs</a>, among other things.&#160; Is Brad really Rob in reverse? </p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/a9569e09c9398884cd72db41a325154e?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /><a href="http://www.sqlserverblogforum.com/">Muthukkumaran Kaliyamoorthy</a> covered the internal join mechanisms, and why the optimizer chooses <a href="http://www.sqlserverblogforum.com/2011/10/merge-join-vs-hash-join-vs-nested-loop-join/">merge, hash, or nested loop joins</a>.    </p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/0edf4d76f04d52cdbb0532ce6f8298f2?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://www.sqlmashup.com">Robert Matthew Cook</a> has a couple of <a href="http://www.sqlmashup.com/t-sql-tuesday-23-joins-tsql2sday">great metaphors</a> for explaining Merge, Hash, and Nested Loop JOINs.</p>
<p>&#160;</p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://1.gravatar.com/avatar/bda2a5c5ba5d6ae5b1d3be3be6271224?s=48&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://blog.waynesheffield.com/wayne/">Wayne Sheffield</a> pointed out some <a href="http://blog.waynesheffield.com/wayne/archive/2011/10/t-sql-tuesday-23-joins/">interesting syntactical ways of writing</a> JOINs. I’m not sure if I’m comfortable with some of them, but they may be of some use in certain edge scenarios. Or, if you just want to mess with the guy who reviews your code.</p>
<p><img style="display: inline; float: left" alt="" align="left" src="http://1.gravatar.com/avatar/7a280962d7c684d86fa58a1c1c289bf5?s=48&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://SQL.RichardDouglas.co.uk">Richard Douglas</a> offers up a short-but-sweet explanation of the relationship of <a href="http://sql.richarddouglas.co.uk/archive/2011/10/t-sql-tuesday-23-key-lookups.html">Key Lookups to JOINs</a>. </p>
<p>     <!--EndFragment--><br />
<h3>&#160;</h3>
<h3>The Future is a Ticking Time Bomb…</h3>
<p><img style="display: inline; float: left" alt="" align="left" src="http://0.gravatar.com/avatar/68f3945bf478970197d593c700ed353f?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" /> <a href="http://thelonedba.wordpress.com">Thomas Rushton</a> points out that Denali may finally force us to <a href="http://thelonedba.wordpress.com/2011/10/04/t-sql-tuesday-23-non-ansi-joins-discontinued-in-denali/">clean up our code.</a></p>
<p>&#160;</p>
<p>&#160;</p>
<h3>My Portugese is Not Up To Par…</h3>
<p>&#160;<img style="display: inline; float: left" alt="" align="left" src="http://1.gravatar.com/avatar/1dea6ab124515201bfb24fd76d4e5228?s=48&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D48&amp;r=G" width="48" height="48" />     <br />Finally, <a href="http://leka.com.br">Ricardo Leka</a> wrote a post that I had to use Google Translate to interpret.&#160; I think I lost something in&#160; translation, because I’m not sure how the example relates to JOIN’s, but thought I would include it anyway.&#160; <a href="http://leka.com.br/2011/10/04/t-sql-tuesday-23-joins/">http://leka.com.br/2011/10/04/t-sql-tuesday-23-joins/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/10/10/tsql2sday-roundup/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>#TSQL2sDay T-SQL Tuesday 23&#8211;Early edition</title>
		<link>http://codegumbo.com/index.php/2011/09/27/tsql2sday-t-sql-tuesday-23early-edition/</link>
		<comments>http://codegumbo.com/index.php/2011/09/27/tsql2sday-t-sql-tuesday-23early-edition/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 16:59:13 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Blogging is FUN!]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[The Social Web]]></category>
		<category><![CDATA[TSQL2sDay]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/09/27/tsql2sday-t-sql-tuesday-23early-edition/</guid>
		<description><![CDATA[&#160; Time once again for another edition of T-SQL Tuesday!&#160; What’s that, you say?&#160; Early?&#160; Why yes, indeed.&#160; Due to the potential schedule of conflict of PASS’s Summit 2011 occurring on the second Tuesday of October (the normal date for T-SQL Tuesday), I’ve gotten special permission to bump it up a week.&#160; To participate in [...]]]></description>
			<content:encoded><![CDATA[<p><b><img style="display: inline; float: left" alt="T-SQL Tuesday Logo" align="left" src="http://www.pearlknows.com/sitebuildercontent/sitebuilderpictures/T-SQLLogo.JPG" width="145" height="150" /></b></p>
<p>&#160;</p>
<p>Time once again for another edition of T-SQL Tuesday!&#160; What’s that, you say?&#160; Early?&#160; Why yes, indeed.&#160; Due to the potential schedule of conflict of PASS’s Summit 2011 occurring on the second Tuesday of October (the normal date for T-SQL Tuesday), I’ve gotten special permission to bump it up a week.&#160; </p>
<p><strong>To participate in this month’s T-SQL Tuesday, your post must go live between midnight UTC on Tuesday, October 4, 2011 and midnight UTC on Wednesday, October 5.</strong></p>
<p>&#160;</p>
<p>Your post needs to link back to this blog, and if you use the image, anchor it to this post.&#160; Make sure you leave a comment or a trackback to this post (so I can find it later, when I write up the summary).</p>
<p>Topic d’jour?&#160; <strong>JOINS</strong> (I’m in a fundamentals mood lately).&#160; Note that I also like creative and esoteric posts, so if you can find a way to apply SQL as a metaphorical language for community activity, I’ll read it and enjoy it.&#160; If you just want to tell me in a simple fashion the difference between a HASH and MERGE join, I’m cool with that, too.</p>
<p>Do me a favor, though, and please spread the word about the early date.&#160; Looking forward to reading your submissions.</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/09/27/tsql2sday-t-sql-tuesday-23early-edition/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Three Myths about Agile Development</title>
		<link>http://codegumbo.com/index.php/2011/06/09/three-myths-about-agile-development/</link>
		<comments>http://codegumbo.com/index.php/2011/06/09/three-myths-about-agile-development/#comments</comments>
		<pubDate>Thu, 09 Jun 2011 13:37:56 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Good Habits]]></category>
		<category><![CDATA[Something New]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/06/09/three-myths-about-agile-development/</guid>
		<description><![CDATA[I recently attended Microsoft Tech Ed in Atlanta, and while there wasn’t much new being announced about SQL Server (I had heard about many of the features for Denali at PASS Summit 2010), I did find myself drawn to several sessions regarding Agile principles and development.&#160; My shop has been using the Scrum method for [...]]]></description>
			<content:encoded><![CDATA[<p>I recently attended <a href="http://northamerica.msteched.com" target="_blank">Microsoft Tech Ed</a> in Atlanta, and while there wasn’t much new being announced about SQL Server (I had heard about many of the features for Denali at <a href="http://www.agilemanifesto.org/" target="_blank">PASS Summit 2010</a>), I did find myself drawn to several sessions regarding Agile principles and development.&#160; My shop has been using the Scrum method for about 2 years now, and it was nice to have a refresher.&#160; I also participated in (and overheard) a lot of conversations about Agile methods, and it made me realize two very important things:</p>
<ol>
<li>Many people who claimed to be using Agile methods had never read the Agile Manifesto, and </li>
<li>There are several misconceptions in play regarding Agile development. </li>
</ol>
<p>The point of this blog post is dual-fold; first I want to encourage you to read the <a href="http://www.agilemanifesto.org/" target="_blank">Agile Manifesto</a>.&#160; If you’ve read it before, <a href="http://www.agilemanifesto.org/" target="_blank">read it again</a>.&#160; And then, read it a <a href="http://www.agilemanifesto.org/" target="_blank">third time</a> (it’s short, so easy to read).&#160; Done that?&#160; Good, because here’s the crux of my argument:</p>
<p><strong>If you want to do Agile development, you must adhere to the principles of the Agile Manifesto.</strong></p>
<p>It’s simple, really; you shouldn’t claim to be a SQL Server developer if you’ve never written a T-SQL statement.&#160; You can’t call yourself a cubist if you haven’t studied the works of Picasso.&#160; You shouldn’t claim to be doing Agile development if you don’t adhere to the principles of the Agile Manifesto. </p>
<p>And, that leads us to the second part of this post; I believe that lots of us think we’re adhering to the methods and principles of Agile development, but there are at least three basic myths about Agile development which keep development teams from being as agile as they can be; here’s my take on them:</p>
<h3>Myth 1: Daily meetings with business people are an impediment to rapid development.</h3>
<p>I actually got into a fervent discussion with gentleman at TechEd about this subject during a Birds of the Feather Session on Scrum.&#160; he claimed to be a Scrum Master for 6 teams (including several overseas), and that he barred business people from entering into the daily standup in order to keep them from dragging the meeting astray.&#160; I think that’s wrong, and here’s why (from the Agile Manifesto principles):</p>
<blockquote><p>Business people and developers must work together daily throughout the project. </p>
</blockquote>
<p>While it’s true that the daily standup in Scrum need not be the daily interaction, it makes sense that business people LISTEN (but not INTERACT) in that meeting in order to understand on what issues the development team is working, and how those issues interplay with each other (Note: scrum calls this the <a href="http://en.wikipedia.org/wiki/The_Chicken_and_the_Pig" target="_blank">chicken and the pig</a>; business people need to know what’s going on across the development team, but shouldn’t be involved at this point.&#160; However, the daily standup can spur additional conversations).&#160;&#160; If your development team chooses to have a daily standup without business people, your team members MUST interact with business people in order to handle changing requirements; they must also communicate at that time what the priorities of the development organization are, and why this particular project is not progressing because some other project takes priority.</p>
<p>Agile development depends on the interaction between developers and business people; to isolate half of the team from the other half of the team will cause disruption to the process.&#160; That leads us to our second myth:</p>
<h3>Myth 2: Your development team can be agile in a vacuum.</h3>
<p>I call this the Agile-Waterfall mindset; your business organization is separate from your development team.&#160; Your developers are practicing some form of Agile development, but the organization is used to handing off a set of requirements to the developers, and then having them return a product at periodic intervals.&#160; Think of this as the complement to Myth 1; Business people aren’t deemed to be an impediment, but the organization hasn’t endorsed agile development throughout.&#160; Daily meetings with developers aren’t deemed to be a priority by the business people; the organization has developed a culture of handing off responsibilities, and expecting them to be fulfilled without daily guidance.</p>
<p><strong>By definition, you can not have an agile team without input from both developers and business people.</strong>&#160;&#160; If you want to respond to changing requirements (as frustrating as that can be to developers), you must have input from business people as soon as those requirements change.&#160; Again, you need to handle prioritization, as changing requirements do not necessarily merit immediate priority.</p>
<h3>Myth 3: Self-organizing teams self-manage efficiently.</h3>
<p>A couple of great principles from the Agile Manifesto deal with communication:</p>
<blockquote><p>The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.</p>
<p>The best architectures, requirements, and designs emerge from self-organizing teams. </p>
</blockquote>
<p>While I believe in the wisdom of these two principles, I don’t want to de-emphasize the need for good, basic software design principles.&#160; Most enterprise development consists of intertwined projects and resources; in order to minimize maintenance issues, adherence to consistent programming standards is a must.&#160; Developers have different naming standards, procedural methodology, and architectural perspectives; a good team has a playbook that ALL members of the development team (regardless of what project team they serve) follow. If you have one database developer that makes heavy use of schemas, and another one that doesn’t, maintaining each other’s code requires some additional effort on their parts.&#160; Furthermore, when teams are self-formed of roughly equally-experienced developers, resolution of architectural decisions can be difficult.</p>
<p>Development teams need an enforcer; a good manager goes a long way toward resolving interpersonal conflicts before they get started.&#160; Just because teams communicate well (and good communication includes conflict), it does not necessarily mean that those same teams will develop quality code in an efficient manner.&#160; Good teams need good direction.</p>
<h3></h3>
<h3>Summing Up.</h3>
<p>If you’ve made it this far, I hope I’ve given you some food for thought, as well as encouraged you to go back and revisit the Agile Manifesto, as well as your own organizational processes.&#160; Let me sum up with a final thought from the Agile Manifesto:</p>
<blockquote><p>At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/06/09/three-myths-about-agile-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#msteched Columnstore indexes unveiled&#8211;DBI312</title>
		<link>http://codegumbo.com/index.php/2011/05/17/msteched-columnstore-indexes-unveileddbi312/</link>
		<comments>http://codegumbo.com/index.php/2011/05/17/msteched-columnstore-indexes-unveileddbi312/#comments</comments>
		<pubDate>Tue, 17 May 2011 13:41:36 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/05/17/msteched-columnstore-indexes-unveileddbi312/</guid>
		<description><![CDATA[Live blogging again; hope you find my notes useful (scattered though they are).&#160; I’ve been waiting on this session because it’s a very specific area of interest.&#160; I work a lot with VLDB’s, and performance is always a concern; claims are that Denali’s columnstore may boost performance of certain queries hundred-fold.&#160; Let’s see how they [...]]]></description>
			<content:encoded><![CDATA[<p>Live blogging again; hope you find my notes useful (scattered though they are).&#160; I’ve been waiting on this session because it’s a very specific area of interest.&#160; I work a lot with VLDB’s, and performance is always a concern; claims are that Denali’s columnstore may boost performance of certain queries hundred-fold.&#160; Let’s see how they work, and I’m hoping I can convince my boss to set up a test bed to try this out.</p>
<p>Presenter is Eric N Hanson from Microsoft (<a href="http://twitter.com/#!/enh_sqlserver" target="_blank">Twitter</a>).&#160; </p>
<p>We start off with a story; I like story-time.&#160; Actually, it’s a very effective way to break out user cases.</p>
<p>Buzzphrase for Columnstore: “Enabling interaction with data”.&#160; Supposed to be super efficient, and get large amounts of data back from SQL Server Denali.&#160; Internal project name is Apollo; columnstore is only part of the picture.</p>
<p>Area of focus is BI &amp; DW: load large amounts of data, high-read, incremental loads.&#160; Partitioning is mandatory for this feature.</p>
<p>Curious as to why the examples join tables in the WHERE clause, and not the more accepted syntax of JOIN.</p>
<p>K, here comes the magic: example uses a Fact Table with 100 million rows in it.&#160; Clustered on a date column, and a columnstore index.&#160; Clustered index is still B-TREE; columnstore indexes are nonclustered.</p>
<p>Running duplicate queries; using index hint to force optimizer to use the clustered index in one example.&#160; Wow; 100,000,000 rows of data aggregated in a second on a two-year old laptop.&#160; 50x speedup on this particular hardware.&#160; According to presenter: “this is the biggest enhancement to SQL Server since we bought the code from Sybase&quot;.</p>
<p>And here’s the meat and potatoes; how does this work?&#160; Vertical partitioning stores each column in a separate page.&#160; Columnstore is based on the same code as PowerPivot and the BI engine;&#160; Vertipaq if you want to do more reading on this.&#160; Columnstore data is highly compressed, so smaller footprint to read from disk and can be stored in main memory.</p>
<p>New query execution plan: batch processing.&#160; “the edsel is the way of the future”.&#160; Actually, the idea is that batches of vectors are stored in query plan; highly efficient data representation.&#160; We can also scale to more cores: tests are showing linear acceleration up to 32 cores.</p>
<p>Instead of storing data as a page, data is stored as a column segment which represents about 1,000,000 rows.</p>
<p>Questions have begun; some questions are good, but this is a 300 level session, folks.&#160; If you don’t understand basic SQL syntax (like how to create an index), this may not be the session for you.&#160; Great question about the relevance of traditional indexes after this is unveiled, and Hanson’s response: in most Decision Support Applications, columnstore is the way to go particularly for scans.</p>
<p>Some index hints for choosing the columnstore or ignoring it:</p>
<p>WITH (index(index_name))</p>
<p>OPTION (ignore_nonclustered_columnstore_index) &lt;—use for bad plan selection if necessary.</p>
<p>Same traditional rules for index hints: trust the optimizer first, rewrite second, and then use hints last.</p>
<p>A couple of new icons for query execution plans: columnstore scan, and batch hash table processing.&#160; Each execution operator now operates in either batch mode or row mode; batch mode is what you want for speed.&#160; </p>
<p>New term of interest: dictionary.&#160; A dictionary is storage for unique values with a lookup so that a column can stores highly compressed information.</p>
<p>Most things just work with SQL Server; Backup and Restore, Mirroring, SSMS, etc.</p>
<p>Lots of datatypes don’t work with column store: long decimals, binary, BLOB, uniqueidentifier, long datetimes, CLR,&#160; (n)varchar(max).</p>
<p>query performance restrictions: outer joins, Unions; Stick with Inner Joins, Star Joins (need to look this one up) Aggregation.&#160; About to show a query which doesn’t benefit from batch processing.&#160; Essence is below:</p>
<p>SELECT t.ID, COUNT(t2.ID)   <br />FROM t LEFT JOIN t2 ON t.ID=t2.ID    <br />GROUP BY t.ID</p>
<p>Left Join knocks it out of batch processing; need to rewrite as an INNER JOIN, but note that you lose the NULL values, so you have to use a CTE; need to get slides for his sample, but you do an INNER JOIN in the CTE, and then do an OUTER JOIN.&#160; </p>
<p>WITH CTE( INNER JOIN)   <br />SELECT blah    <br />FROM t OUTER JOIN CTE ON t.ID yada yada.</p>
<p>Adding data to columnstore; basic methods:</p>
<p>1.&#160; Drop and re-add the index before load.&#160; Expensive, but works well with traditional daily builds</p>
<p>2.&#160; Partition switching.&#160; Sweet spot needs to be tested, but easy one is the hour.&#160; NOLOCK queries pre-empt the ability to do paritioned queries.&#160; Need to read up on this, but may be fixed in future version</p>
<p>3&#160; trickle load can be done, but needs to be tested.</p>
<p>Very awesome; I cannot wait until this is actually released in CTP 3, so I can play around with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/05/17/msteched-columnstore-indexes-unveileddbi312/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#TSQL2sday: Emulating a FIRST aggregation</title>
		<link>http://codegumbo.com/index.php/2011/03/08/tsql2sday-emulating-a-first-aggregation/</link>
		<comments>http://codegumbo.com/index.php/2011/03/08/tsql2sday-emulating-a-first-aggregation/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 21:58:58 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[TSQL2sDay]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/03/08/tsql2sday-emulating-a-first-aggregation/</guid>
		<description><![CDATA[Jes Borland is hosting this month’s T-SQL Tuesday, and it’s all about aggregations.&#160; Here’s an old coding trick of mine to emulate a FIRST aggregation in T-SQL.&#160; Say we have a table that has three columns: ID, a uniqueidentifier Name, a varchar that represents something, and DateStored, a datetime that is set when the row [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/come-one-come-all-to"></a>
<p><a href="http://http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/come-one-come-all-to" target="_blank"><img style="border-right-width: 0px; margin: 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="tsql2sday" border="0" alt="tsql2sday" src="http://codegumbo.com/images/TSQL2sdayEmulatingaFIRSTaggregation_EEC4/tsql2sday.jpg" width="154" height="154" /></a></p>
<p><a href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/come-one-come-all-to" target="_blank">Jes Borland</a> is hosting this month’s T-SQL Tuesday, and it’s all about aggregations.&#160; Here’s an old coding trick of mine to emulate a FIRST aggregation in T-SQL.&#160; Say we have a table that has three columns:</p>
<ul>
<li>ID, a uniqueidentifier </li>
<li>Name, a varchar that represents something, and </li>
<li>DateStored, a datetime that is set when the row is written to the table </li>
</ul>
<p>And we populate that table like so:</p>
<p> <code style="font-size: 12px"><span style="color: blue">CREATE TABLE </span><span style="color: black">TSQL2sDay_FirstAgg      <br />&#160;&#160;&#160; </span><span style="color: gray">(      <br />&#160;&#160;&#160;&#160;&#160; </span><span style="color: black">ID </span><span style="color: blue">UNIQUEIDENTIFIER      <br />&#160;&#160;&#160; </span><span style="color: gray">, </span><span style="color: black">NAME </span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span><span style="color: black">20</span><span style="color: gray">)      <br />&#160;&#160;&#160; , </span><span style="color: black">DateStored </span><span style="color: blue">DATETIME DEFAULT </span><span style="color: magenta">GETUTCDATE</span><span style="color: gray">()      <br />&#160;&#160;&#160; )       <br />&#160;&#160;&#160;&#160; <br /></span><span style="color: blue">INSERT&#160; INTO </span><span style="color: black">TSQL2sDay_FirstAgg      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">( </span><span style="color: black">ID</span><span style="color: gray">, </span><span style="color: black">NAME </span><span style="color: gray">)      <br /></span><span style="color: blue">VALUES&#160; </span><span style="color: gray">( </span><span style="color: magenta">NEWID</span><span style="color: gray">(), </span><span style="color: red">'Peanut' </span><span style="color: gray">)      </p>
<p></span><span style="color: blue">WAITFOR </span><span style="color: black">DELAY </span><span style="color: red">'00:00:01'      </p>
<p></span><span style="color: blue">INSERT&#160; INTO </span><span style="color: black">TSQL2sDay_FirstAgg      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">( </span><span style="color: black">ID</span><span style="color: gray">, </span><span style="color: black">NAME </span><span style="color: gray">)      <br /></span><span style="color: blue">VALUES&#160; </span><span style="color: gray">( </span><span style="color: magenta">NEWID</span><span style="color: gray">(), </span><span style="color: red">'Peanut' </span><span style="color: gray">)      </p>
<p></span><span style="color: blue">WAITFOR </span><span style="color: black">DELAY </span><span style="color: red">'00:00:01'      </p>
<p></span><span style="color: blue">INSERT&#160; INTO </span><span style="color: black">TSQL2sDay_FirstAgg      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">( </span><span style="color: black">ID</span><span style="color: gray">, </span><span style="color: black">NAME </span><span style="color: gray">)      <br /></span><span style="color: blue">VALUES&#160; </span><span style="color: gray">( </span><span style="color: magenta">NEWID</span><span style="color: gray">(), </span><span style="color: red">'Orange' </span><span style="color: gray">)      <br /></span></code>
<p>&#160;</p>
<p>It’s easy to figure out the number of rows associated with each name:</p>
<p> <code style="font-size: 12px"><span style="color: green">-- SELECT data to verify order of DateStored      <br /></span><span style="color: blue">SELECT&#160; </span><span style="color: black">ID      <br />&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">, </span><span style="color: black">NAME      <br />&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">, </span><span style="color: black">DateStored      <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: black">TSQL2sDay_FirstAgg&#160;&#160;&#160;&#160;&#160;&#160; </p>
<p></span><span style="color: green">-- Basic Row Count by Name      <br /></span><span style="color: blue">SELECT&#160; </span><span style="color: black">NAME      <br />&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">, </span><span style="color: black">RowCnt </span><span style="color: blue">= </span><span style="color: magenta">COUNT</span><span style="color: gray">(*)      <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: black">TSQL2sDay_FirstAgg      <br /></span><span style="color: blue">GROUP BY </span><span style="color: black">NAME      <br /></span></code>
<p>&#160;</p>
<p>but how do we figure out what the first ID was for each name along with the number of rows?&#160; You could work something out using the HAVING clause of the SELECT statement, or you could do something like the following:</p>
<p> <code style="font-size: 12px"><span style="color: green">--SELECT first ID and count of rows by Name     <br /></span><span style="color: blue">SELECT&#160; </span><span style="color: black">FirstID </span><span style="color: blue">= </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">UNIQUEIDENTIFIER</span><span style="color: gray">, </span><span style="color: magenta">RIGHT</span><span style="color: gray">(</span><span style="color: magenta">MIN</span><span style="color: gray">(</span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span><span style="color: black">24</span><span style="color: gray">), </span><span style="color: black">DateStored</span><span style="color: gray">, </span><span style="color: black">121</span><span style="color: gray">) + </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span><span style="color: black">36</span><span style="color: gray">), </span><span style="color: black">ID</span><span style="color: gray">)),     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: black">36</span><span style="color: gray">))     <br />&#160;&#160;&#160;&#160;&#160; , </span><span style="color: black">NAME     <br />&#160;&#160;&#160;&#160;&#160; </span><span style="color: gray">, </span><span style="color: black">RowCnt </span><span style="color: blue">= </span><span style="color: magenta">COUNT</span><span style="color: gray">(*)     <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: black">TSQL2sDay_FirstAgg     <br /></span><span style="color: blue">GROUP BY </span><span style="color: black">NAME     </p>
<p></span></code>
<p>&#160;</p>
<p>It looks complicated, but it’s not; let’s step through it.</p>
<ol>
<li>We have to know some basic information about our data; in this case, we know that the datetime value associated with each row with a common name is different.&#160; In other words, there are no two Peanuts with the same DateStored value.&#160; This is important, because in order for there to be a first value, there must be some method of ALWAYS determining which one WAS first.&#160; If two Peanuts showed up at the same time, the model is broken.</li>
<li>The first thing we do is to <a href="http://msdn.microsoft.com/en-us/library/ms187928.aspx" target="_blank">CONVERT</a> the DateStored value to a varchar; this allows us to concatenate it with other values.&#160; The format of that varchar string is important; it must be precise, and it must sort in an ascending order.&#160; The ODBC canonical format (with milliseconds) is a good candidate for this.</li>
<li>We then CONVERT the uniqueidentifer to a varchar, and append it to the DateStored varchar value.&#160; This gives us a lengthy string which can be sorted by the first 24 characters.</li>
<li>We find the MIN of the string we constructed; this MIN value is determined by the optimizer based on the sorting value of the numbers in the DateStored value.</li>
<li>We then take the RIGHT-most 36 characters (the length of a uniqueidentifier), and convert it back to a uniqueidentifier (so that we have our type back).</li>
</ol>
<p>There are probably better solutions for this, but this is a simple trick that works under certain circumstances and is portable to several flavors of SQL.</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/03/08/tsql2sday-emulating-a-first-aggregation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple codebuilder for parsing in T-SQL</title>
		<link>http://codegumbo.com/index.php/2011/02/22/a-simple-codebuilder-for-parsing-in-t-sql/</link>
		<comments>http://codegumbo.com/index.php/2011/02/22/a-simple-codebuilder-for-parsing-in-t-sql/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 18:22:51 +0000</pubDate>
		<dc:creator>stuart</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://codegumbo.com/index.php/2011/02/22/a-simple-codebuilder-for-parsing-in-t-sql/</guid>
		<description><![CDATA[If you’ve ever tried to parse a wide character column in T-SQL, you know two things: It’s a pain to do, and It’s a pain to do. A lot of the data I deal with comes in syslog format, which can come in one of two formats: positional (the location of the data element is [...]]]></description>
			<content:encoded><![CDATA[<p>If you’ve ever tried to parse a wide character column in T-SQL, you know two things:</p>
<ol>
<li>It’s a pain to do, and </li>
<li>It’s a pain to do. </li>
</ol>
<p>A lot of the data I deal with comes in syslog format, which can come in one of two formats: positional (the location of the data element is related to the type of data), and named attributes (which usually only include delimiters for complex strings).&#160; Although I haven’t had much luck automating positional parsing, I’ve recently begun using Excel to help me with the named attributes.&#160; </p>
<p>Here’s an example; I have a table with a message column that is pulling over syslog data from a firewall.&#160; In a given day, I may have millions of rows like the following:</p>
<blockquote><p>sn=AA17D5028EAA time=&quot;2011-01-26 13:40:14 UTC&quot; fw=10.1.100.1 pri=1 c=512 m=522 msg=&quot;Malformed or unhandled IP packet dropped&quot; n=1 src=10.1.1.23:32795:X1: dst=10.1.1.1:514:: proto=udp/17</p>
</blockquote>
<p>Note that each attribute of this particular syslog message is identified with an attribute name (eg, sn, time, fw, etc).&#160; In order to break out each of the elements in T-SQL, we can split the string using a combination of SUBSTRING and CHARINDEX, like so:</p>
<p> <code style="font-size: 12px"><span style="color: blue">SELECT TOP </span><span style="color: black">1      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; m </span><span style="color: blue">= </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">INT</span><span style="color: gray">, </span><span style="color: magenta">SUBSTRING</span><span style="color: gray">(</span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' m='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">3</span><span style="color: gray">,      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' '</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' m='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">3</span><span style="color: gray">) - ( </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' m='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; + </span><span style="color: black">3 </span><span style="color: gray">)))      <br />&#160;&#160;&#160;&#160;&#160; , </span><span style="color: black">time </span><span style="color: blue">= </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">DATETIME</span><span style="color: gray">, </span><span style="color: magenta">SUBSTRING</span><span style="color: gray">(</span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' time=&quot;'</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">7</span><span style="color: gray">,      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">'UTC&quot;'</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' time=&quot;'</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">7</span><span style="color: gray">)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; - ( </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' time=&quot;'</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">7 </span><span style="color: gray">)))      <br />&#160;&#160;&#160;&#160;&#160; , </span><span style="color: black">fw </span><span style="color: blue">= </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span><span style="color: black">20</span><span style="color: gray">), </span><span style="color: magenta">SUBSTRING</span><span style="color: gray">(</span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' fw='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">4</span><span style="color: gray">,      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' '</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' fw='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">4</span><span style="color: gray">) - ( </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' fw='</span><span style="color: gray">,      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">4 </span><span style="color: gray">)))      <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: black">syslogng </span><span style="color: gray">(</span><span style="color: black">NOLOCK</span><span style="color: gray">)      </p>
<p></span></code>
<p>Note the repetition for each column; you need to find the position of a starting delimiter, the position of an ending delimiter, and supply to the SUBSTRING function the position of the starting delimiter, and the difference between the two.&#160; You also need to determine the lingth of the starting identifier, and then I CONVERT to a specific data type.&#160; Whee!</p>
<p>It gets even more fun when the attributes are optional; some syslog messages may have a proto code, and some may not.&#160;&#160; When faced with this, you need to include a CASE option, like so:</p>
<p> <code style="font-size: 12px"><span style="color: blue">SELECT TOP </span><span style="color: black">1      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; proto </span><span style="color: blue">= </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span><span style="color: black">20</span><span style="color: gray">), </span><span style="color: magenta">CASE </span><span style="color: blue">WHEN CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' proto='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) </span><span style="color: blue">= </span><span style="color: black">0 </span><span style="color: blue">THEN </span><span style="color: gray">NULL      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">ELSE </span><span style="color: magenta">SUBSTRING</span><span style="color: gray">(</span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' proto='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">7</span><span style="color: gray">,      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' '</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">, </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' proto='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">7</span><span style="color: gray">)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; - ( </span><span style="color: blue">CHARINDEX</span><span style="color: gray">(</span><span style="color: red">' proto='</span><span style="color: gray">, </span><span style="color: blue">MESSAGE</span><span style="color: gray">) + </span><span style="color: black">7 </span><span style="color: gray">))      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="color: blue">END</span><span style="color: gray">)      <br /></span><span style="color: blue">FROM&#160;&#160;&#160; </span><span style="color: black">syslogng </span><span style="color: gray">(</span><span style="color: black">NOLOCK</span><span style="color: gray">)      <br /></span></code>
<p>&#160;</p>
<p>One of our developers is working on a syslog parser in .NET code, but I needed a proof-of-concept, and I didn’t want to keep cutting and pasting to see if it was working.&#160; Looking at the parsing, it’s very formulaic SQL.&#160; When I think formulas, I think Excel, and so I whipped out the following:</p>
<p><a href="http://codegumbo.com/images/AsimplecodebuilderforparsinginTSQL_BC21/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://codegumbo.com/images/AsimplecodebuilderforparsinginTSQL_BC21/image_thumb.png" width="623" height="236" /></a> </p>
<p>Note that I have several input columns:</p>
<ul>
<li>start, the starting delimiter</li>
<li>end, the ending delimiter (usually a space)</li>
<li>colname, the column name I want to use; usually the same as start, but stripped of extra characters.</li>
<li>type, the SQL type I want to convert the data to, and</li>
<li>optional, a column to decide if the attribute is optional per row or not.</li>
</ul>
<p>I also have a hidden column (column F), which generates most of the SQL code:</p>
<blockquote><p>=CONCATENATE(&quot;SUBSTRING(message, CHARINDEX(&#8216;&quot;, A2, &quot;&#8217;, message)+ &quot;, LEN(A2), &quot;, CHARINDEX(&#8216;&quot;, B2, &quot;&#8217;, message, CHARINDEX(&#8216;&quot;, A2, &quot;&#8217;, message)+&quot;, LEN(A2), &quot;) &#8211; (CHARINDEX(&#8216;&quot;, A2, &quot;&#8217;, message)+&quot;, LEN(A2), &quot;))&quot;)</p>
</blockquote>
<p>This takes the starting and ending delimiters, the length of the starting delimiter, and plugs those values into a valid SQL statement.&#160; I then create a SQL column, using the following formula:</p>
<blockquote><p>=CONCATENATE(&quot;, &quot;, C2,&quot;CONVERT(&quot;, D2, &quot;, &quot;,&#160; IF(E2=&quot;Y&quot;, CONCATENATE(&quot;CASE WHEN CHARINDEX(&#8216;&quot;, A2, &quot;&#8217;, message) = 0 THEN NULL ELSE &quot;,F2, &quot; END&quot;), F2), &quot;)&quot;)</p>
</blockquote>
<p>If I were better at Excel, I’d use named ranges, but for my purposes, this is OK.&#160;&#160; I append a column to the beginning, specify the type, and include a CASE statement based on whether or not my optional column includes a “Y”.</p>
<p>It took me longer to write this blog post than it did to generate a proof-of-concept, parsing each of the named attributes out from a syslog message.</p>
]]></content:encoded>
			<wfw:commentRss>http://codegumbo.com/index.php/2011/02/22/a-simple-codebuilder-for-parsing-in-t-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

