<?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/"
	>

<channel>
	<title>Coding Obsession</title>
	<atom:link href="http://techblog.julianhidalgo.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://techblog.julianhidalgo.com</link>
	<description></description>
	<pubDate>Tue, 02 Jun 2009 05:12:13 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Don&#8217;t trust SQL Server 2005 &#8220;Deferred Name Resolution&#8221;</title>
		<link>http://techblog.julianhidalgo.com/2009/05/29/dont-trust-sql-server-2005-deferred-name-resolution/</link>
		<comments>http://techblog.julianhidalgo.com/2009/05/29/dont-trust-sql-server-2005-deferred-name-resolution/#comments</comments>
		<pubDate>Fri, 29 May 2009 07:20:31 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/05/29/dont-trust-sql-server-2005-deferred-name-resolution/</guid>
		<description><![CDATA[Take a look at the following stored procedure (as always, meant to be created against the AdventureWorks database):

CREATE PROCEDURE MyProcedure
AS
&#160;&#160;&#160; IF 1 = 0
&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT TOP 10 * FROM Person.WrongTable
&#160;&#160;&#160; ELSE
&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT TOP 10 * FROM Person.Address

As I’ve mentioned before, this stored procedure will be created by SQL Server 2005 without throwing any error message [...]]]></description>
			<content:encoded><![CDATA[<p>Take a look at the following stored procedure (as always, meant to be created against the AdventureWorks database):</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE PROCEDURE </span>MyProcedure</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">IF </span>1 = 0</p>
<p style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">SELECT TOP </span>10 * <span style="color: blue">FROM </span>Person.WrongTable</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">ELSE</span></p>
<p style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">SELECT TOP </span>10 * <span style="color: blue">FROM </span>Person.Address</p>
</p></div>
<p>As <a href="http://techblog.julianhidalgo.com/2009/05/12/follow-up-to-strange-bug-in-sql-server-2005/">I’ve mentioned before</a>, this stored procedure will be created by SQL Server 2005 without throwing any error message or warning. The Person.WrongTable table will be treated as a missing reference, and “<a href="http://msdn.microsoft.com/en-us/library/ms190686(SQL.90).aspx">Deferred Name Resolution and Compilation</a>” will come into play. What will happen then? The names will be resolved upon execution:</p>
<blockquote><p>When a stored procedure is executed for the first time, the query processor reads the text of the stored procedure from the sys.sql_modules catalog view and checks that the names of the objects used by the procedure are present. This process is called deferred name resolution because table objects referenced by the stored procedure need not exist when the stored procedure is created, but only when it is executed.</p>
</blockquote>
<p>According to the Books Online, then, the stored procedure should fail upon execution on the resolution stage. But it doesn’t! - try it out yourself. It seems as if the query processor realizes the first statement is unreachable and doesn’t bother to resolve the names there.</p>
<p>Now, what happens when the condition in the IF statement depends on a parameter? Let’s see:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE PROCEDURE </span>MyProcedure2</p>
<p style="margin: 0px">&#160;&#160;&#160; @flag <span style="color: blue">bit</span></p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">IF </span>@flag = 1</p>
<p style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">SELECT TOP </span>10 * <span style="color: blue">FROM </span>Person.WrongTable</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">ELSE</span></p>
<p style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">SELECT TOP </span>10 * <span style="color: blue">FROM </span>Person.Address</p>
</p></div>
<p>This stored procedure only fails when executed with @flag equal to 1. But this behavior is not documented.</p>
<p>Let’s see another interesting case: instead of a parameter, the condition will depend of a value stored in a table. We need to create a test table first:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE TABLE </span>TestTable</p>
<p style="margin: 0px">(</p>
<p style="margin: 0px">&#160;&#160;&#160; id <span style="color: blue">int IDENTITY</span>(1,1), flag <span style="color: blue">bit</span></p>
<p style="margin: 0px">)</p>
<p style="margin: 0px"><span style="color: blue">INSERT INTO </span>TestTable(flag) <span style="color: blue">VALUES</span>(0)</p>
<p style="margin: 0px"><span style="color: blue">INSERT INTO </span>TestTable(flag) <span style="color: blue">VALUES</span>(1)</p>
</p></div>
<p>Now we can create the following stored procedure:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE PROCEDURE </span>MyProcedure3</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">DECLARE </span>@flag <span style="color: blue">bit</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>@flag = flag <span style="color: blue">FROM </span>TestTable <span style="color: blue">WHERE </span>id = 1</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">IF </span>@flag = 1</p>
<p style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">SELECT TOP </span>10 * <span style="color: blue">FROM </span>Person.WrongTable</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">ELSE</span></p>
<p style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">SELECT TOP </span>10 * <span style="color: blue">FROM </span>Person.Address</p>
</p></div>
<p>We are setting @flag to a value stored on the first row of our TestTable table. The execution succeeds and returns the 10 first rows of the Person.Address table. Let’s change the procedure to read the flag from the second row instead:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">SELECT </span>@flag = flag <span style="color: blue">FROM </span>TestTable <span style="color: blue">WHERE </span>id = 2</p>
</p></div>
<p>Now the execution fails (finally!):</p>
<blockquote><p><font color="#ff0000">Msg 208, Level 16, State 1, Procedure MyProcedure3, Line 6       <br />Invalid object name &#8216;Person.WrongTable’.</font></p>
</blockquote>
<p>What’s going on here? Again, this behavior is not consistent to what the documentation says. I doubt SQL Server is fetching the data from the TestTable table in advance to determine how the execution will go, so it must be resolving the names on the fly on a per-statement basis. I’ll check my books to see if I find more information about this “feature”.</p>
<p>This surely looks like a valid and even desirable optimization in most cases, but again, it’s not consistent with the documentation. According to the Books Online, <a href="http://msdn.microsoft.com/en-us/library/ms190686(SQL.90).aspx">the optimization of the query and the creation of the execution plan occur after the resolution stage</a>:</p>
<blockquote><p>If procedure execution successfully passes the resolution stage, the Microsoft SQL Server query optimizer analyzes the Transact-SQL statements in the stored procedure and creates an execution plan.</p>
</blockquote>
<p>The final conclusion here is that you can’t be sure your stored procedures (or functions or any executable object for that matter) are correct until you test them with values that exercise all the possible execution paths (this has been a pain in the neck at work the last couple of days). This makes a good argument for unit testing at the database level.</p>
<p>Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/05/29/dont-trust-sql-server-2005-deferred-name-resolution/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SQL Server 2005 error handling gotcha</title>
		<link>http://techblog.julianhidalgo.com/2009/05/17/sql-server-2005-error-handling-gotcha/</link>
		<comments>http://techblog.julianhidalgo.com/2009/05/17/sql-server-2005-error-handling-gotcha/#comments</comments>
		<pubDate>Sun, 17 May 2009 00:56:37 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/05/17/sql-server-2005-error-handling-gotcha/</guid>
		<description><![CDATA[One of the cool features introduced in SQL Server 2005 was the improved error handling capabilities in Transact-SQL through the try/catch construct. I’m not going to talk about it here since there is plenty of material on the subject on the web, I just want to point out a gotcha I found a few days [...]]]></description>
			<content:encoded><![CDATA[<p>One of the cool features introduced in SQL Server 2005 was the improved error handling capabilities in Transact-SQL through the <a title="TRY...CATCH" href="http://technet.microsoft.com/en-us/library/ms175976(SQL.90).aspx">try/catch</a> construct. I’m not going to talk about it here since there is plenty of material on the subject on the web, I just want to point out a gotcha I found a few days ago at work.</p>
<p>Take the following stored procedure:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE PROCEDURE </span>MyProcedure</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>x <span style="color: blue">FROM </span>Person.Address</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>y <span style="color: blue">FROM </span>Person.Contact</p>
</p></div>
<p>&#160;</p>
<p>If you try to create the procedure in the AdventureWorks database it will fail because the x and y columns don’t exist:</p>
<blockquote><p><font color="#ff0000">Msg 207, Level 16, State 1, Procedure MyProcedure, Line 3        <br />Invalid column name &#8216;x&#8217;.         <br />Msg 207, Level 16, State 1, Procedure MyProcedure, Line 4         <br />Invalid column name &#8216;y&#8217;.</font></p>
</blockquote>
<p>If you execute the same query as dynamic SQL (through the <a href="http://msdn.microsoft.com/en-us/library/ms188001(SQL.90).aspx">sp_executesql</a> stored procedure) you get the same 2 errors:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">DECLARE </span>@Command nvarchar(2000)</p>
<p style="margin: 0px"><span style="color: blue">SET </span>@Command = <span style="color: #a31515">&#8216;CREATE PROCEDURE MyProcedure</span></p>
<p style="margin: 0px"><span style="color: #a31515">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: #a31515">SELECT x FROM Person.Address</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: #a31515">SELECT y FROM Person.Contact&#8217;</span></p>
<p style="margin: 0px"><span style="color: blue">EXEC </span>sp_executesql @Command</p>
</p></div>
<p>&#160;</p>
</p>
<p>Now let’s use a try/catch construct to handle the error:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">DECLARE </span>@Command nvarchar(2000)</p>
<p style="margin: 0px"><span style="color: blue">SET </span>@Command = <span style="color: #a31515">&#8216;CREATE PROCEDURE MyProcedure</span></p>
<p style="margin: 0px"><span style="color: #a31515">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: #a31515">SELECT x FROM Person.Address</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: #a31515">SELECT y FROM Person.Contact&#8217;</span></p>
<p style="margin: 0px"><span style="color: blue">BEGIN </span>TRY</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">EXEC </span>sp_executesql @Command</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">PRINT </span><span style="color: #a31515">&#8216;Procedure MyProcedure created.&#8217;</span></p>
<p style="margin: 0px"><span style="color: blue">END </span>TRY</p>
<p style="margin: 0px"><span style="color: blue">BEGIN </span>CATCH</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">PRINT </span><span style="color: #a31515">&#8216;Procedure MyProcedure couldn&#8221;t be created: &#8216; </span>+ <font color="#ff00ff">ERROR_MESSAGE</font>()</p>
<p style="margin: 0px"><span style="color: blue">END </span>CATCH</p>
</p></div>
<p>&#160;</p>
<p>This time the <font color="#ff00ff">ERROR_MESSAGE</font> function only returns the first error message:</p>
<blockquote><p>Procedure MyProcedure couldn&#8217;t be created:Invalid column name &#8216;x&#8217;.</p>
</blockquote>
<p>It looks you can only get information about the first error hat occurred in a try block. I believe the reason is that control is immediately transferred to the catch block after the first error occurs because when you execute the naked sp_execute procedure it shows the 2 errors.</p>
<p>Most of the time this is not an issue, unless you want to execute DDL statements (since SQL Server may report several errors). This was the case for me, I was working on a script that drops all the database objects and creates them again (to check if any of them got broken by some changes in the schema), and I wanted to report all the errors, but I had to give up and just report the objects that had errors.</p>
<p>If I discover a way to get around this limitation I&#8217;ll post about it, but I doubt there’s one. Over and out!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/05/17/sql-server-2005-error-handling-gotcha/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dynamic SQL and square brackets in SQL Server identifiers</title>
		<link>http://techblog.julianhidalgo.com/2009/05/15/dynamic-sql-and-square-brackets-in-sql-server-identifiers/</link>
		<comments>http://techblog.julianhidalgo.com/2009/05/15/dynamic-sql-and-square-brackets-in-sql-server-identifiers/#comments</comments>
		<pubDate>Fri, 15 May 2009 08:34:19 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/05/15/dynamic-sql-and-square-brackets-in-sql-server-identifiers/</guid>
		<description><![CDATA[All the following identifiers are valid column names (the resulting name is shown in the comments):

CREATE TABLE Table1
(
&#160;&#160;&#160; [[MyColumn] int, &#8211; [MyColumn
&#160;&#160;&#160; [My[Column] int, &#8211; My[Column
&#160;&#160;&#160; [[[MyColumn] int, &#8211; [[MyColumn
&#160;&#160;&#160; [MyColumn]]] int, &#8211; MyColumn]
&#160;&#160;&#160; []]MyColumn] int, &#8211; ]MyColumn
&#160;&#160;&#160; [[]]MyColumn] int &#8211; []MyColumn
)

These are called delimited identifiers are also valid for other kind of objects like [...]]]></description>
			<content:encoded><![CDATA[<p>All the following identifiers are valid column names (the resulting name is shown in the comments):</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE TABLE </span>Table1</p>
<p style="margin: 0px">(</p>
<p style="margin: 0px">&#160;&#160;&#160; [[MyColumn] <span style="color: blue">int</span>, <span style="color: green">&#8211; [MyColumn</span></p>
<p style="margin: 0px">&#160;&#160;&#160; [My[Column] <span style="color: blue">int</span>, <span style="color: green">&#8211; My[Column</span></p>
<p style="margin: 0px">&#160;&#160;&#160; [[[MyColumn] <span style="color: blue">int</span>, <span style="color: green">&#8211; [[MyColumn</span></p>
<p style="margin: 0px">&#160;&#160;&#160; [MyColumn]]] <span style="color: blue">int</span>, <span style="color: green">&#8211; MyColumn]</span></p>
<p style="margin: 0px">&#160;&#160;&#160; []]MyColumn] <span style="color: blue">int</span>, <span style="color: green">&#8211; ]MyColumn</span></p>
<p style="margin: 0px">&#160;&#160;&#160; [[]]MyColumn] <span style="color: blue">int </span><span style="color: green">&#8211; []MyColumn</span></p>
<p style="margin: 0px">)</p>
</div>
<p>These are called delimited identifiers are also valid for other kind of objects like tables, constraints and so on. Obviously they should be avoided, but it’s good to be aware that they may exist in case you have to work with legacy databases or dynamic SQL. <a href="http://msdn.microsoft.com/en-us/library/ms176027(SQL.90).aspx">SQL Server allows any character in the current code page to be used in a delimited identifier</a>, but square brackets in particular can break that beautiful dynamic SQL script you are working on. For example, let’s write a script that drops all the columns in the Table1 table (an artificial example but it serves to illustrate the point):</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">DECLARE </span>@Command nvarchar(2000), @ColumnName <span style="color: blue">sysname</span></p>
<p style="margin: 0px"><span style="color: blue">DECLARE </span>ColumnsCursors <span style="color: blue">CURSOR FOR</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>c.name</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">FROM </span>sys.tables t</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">INNER JOIN </span>sys.columns c <span style="color: blue">ON </span>c.object_id = t.object_id</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">WHERE </span>t.name = <span style="color: #a31515">&#8216;Table1&#8242;</span></p>
<p style="margin: 0px">&#160;</p>
<p style="margin: 0px"><span style="color: blue">OPEN </span>ColumnsCursors</p>
<p style="margin: 0px"><span style="color: blue">FETCH NEXT FROM </span>ColumnsCursors <span style="color: blue">INTO </span>@ColumnName;</p>
<p style="margin: 0px"><span style="color: blue">WHILE </span>(@@FETCH_STATUS = 0)</p>
<p style="margin: 0px"><span style="color: blue">BEGIN</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SET </span>@Command = <span style="color: #a31515">&#8216;ALTER TABLE Table1 DROP COLUMN &#8216; </span>+ @ColumnName</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">PRINT </span>@Command</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">EXEC </span>sp_executesql @Command</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">FETCH NEXT FROM </span>ColumnsCursors <span style="color: blue">INTO </span>@ColumnName;</p>
<p style="margin: 0px"><span style="color: blue">END</span>;</p>
<p style="margin: 0px"><span style="color: blue">CLOSE </span>ColumnsCursors;</p>
<p style="margin: 0px"><span style="color: blue">DEALLOCATE </span>ColumnsCursors;</p>
</div>
<p>The script will fail with all sorts of errors:</p>
<blockquote><p>ALTER TABLE Table1 DROP COLUMN [MyColumn     <br /><font color="#ff0000">Msg 105, Level 15, State 1, Line 1       <br />Unclosed quotation mark after the character string 'MyColumn'.        <br />Msg 102, Level 15, State 1, Line 1        <br />Incorrect syntax near 'MyColumn'.        <br /></font>ALTER TABLE Table1 DROP COLUMN My[Column      <br /><font color="#ff0000">Msg 105, Level 15, State 1, Line 1       <br />Unclosed quotation mark after the character string 'Column'.        <br /></font>ALTER TABLE Table1 DROP COLUMN [[MyColumn      <br /><font color="#ff0000">Msg 105, Level 15, State 1, Line 1       <br />Unclosed quotation mark after the character string '[MyColumn'.        <br />Msg 102, Level 15, State 1, Line 1        <br />Incorrect syntax near '[MyColumn'.        <br /></font>ALTER TABLE Table1 DROP COLUMN MyColumn]      <br /><font color="#ff0000">Msg 102, Level 15, State 1, Line 1       <br />Incorrect syntax near &#8216;]&#8217;.</font>      <br />ALTER TABLE Table1 DROP COLUMN ]MyColumn      <br /><font color="#ff0000">Msg 102, Level 15, State 1, Line 1       <br />Incorrect syntax near &#8216;]&#8217;.</font>      <br />ALTER TABLE Table1 DROP COLUMN []MyColumn      <br /><font color="#ff0000">Msg 1038, Level 15, State 4, Line 1       <br />An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as &quot;&quot; or [] are not allowed. Add a name or single space as the alias name.         <br />Msg 102, Level 15, State 1, Line 1        <br />Incorrect syntax near &#8216;MyColumn&#8217;.</font></p>
</blockquote>
<p>Enclosing all the identifiers with square brackets (using ‘[‘ + @ColumnName + ‘]’) is not enough, the drop of the last 3 columns will still fail:</p>
<blockquote><p>ALTER TABLE Table1 DROP COLUMN [MyColumn]]     <br /><font color="#ff0000">Msg 105, Level 15, State 1, Line 1       <br />Unclosed quotation mark after the character string &#8216;MyColumn]&#8217;.        <br />Msg 102, Level 15, State 1, Line 1        <br />Incorrect syntax near &#8216;MyColumn]&#8217;.        <br /></font>ALTER TABLE Table1 DROP COLUMN []MyColumn]      <br /><font color="#ff0000">Msg 1038, Level 15, State 4, Line 1       <br />An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as &quot;&quot; or [] are not allowed. Add a name or single space as the alias name.         <br />Msg 102, Level 15, State 1, Line 1        <br />Incorrect syntax near &#8216;MyColumn&#8217;.</font>      <br />ALTER TABLE Table1 DROP COLUMN [[]MyColumn]      <br /><font color="#ff0000">Msg 102, Level 15, State 1, Line 1       <br />Incorrect syntax near &#8216;MyColumn&#8217;.</font></p>
</blockquote>
<p>To be completely safe, you also need to escape any occurrence of “]” in the identifier with “]]”:</p>
<p style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: courier new" align="left">&#160;&#160;&#160; <span style="color: blue">SET </span>@Command = <span style="color: #a31515">&#8216;ALTER TABLE Table1 DROP COLUMN [' </span>+ <font color="#ff00ff">REPLACE</font>(@ColumnName, <span style="color: #a31515">']&#8216;</span>, <span style="color: #a31515">&#8216;]]&#8217;</span>) + <span style="color: #a31515">&#8216;]&#8217;</span></p>
<p>Note that the script will still fail on the last step because you can’t drop all the columns of a table, but you get the idea. Hope it helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/05/15/dynamic-sql-and-square-brackets-in-sql-server-identifiers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Follow-up to “Strange bug in SQL Server 2005”</title>
		<link>http://techblog.julianhidalgo.com/2009/05/12/follow-up-to-strange-bug-in-sql-server-2005/</link>
		<comments>http://techblog.julianhidalgo.com/2009/05/12/follow-up-to-strange-bug-in-sql-server-2005/#comments</comments>
		<pubDate>Tue, 12 May 2009 13:07:42 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/05/12/follow-up-to-strange-bug-in-sql-server-2005/</guid>
		<description><![CDATA[My friend Michael Dorman left the following comment on my post about a bug in SQL Server 2005:
Stored Procedure creation in T-SQL doesn’t guarantee to check to see that the dependent objects exist. That’s not a bug, it’s by design.

According to the SQL Server 2005 Books Online, Deferred Name Resolution and Compilation:
Deferred name resolution can [...]]]></description>
			<content:encoded><![CDATA[<p>My friend Michael Dorman left the following comment on my post about a bug in <a href="http://techblog.julianhidalgo.com/2009/05/10/strange-bug-in-sql-server-2005/">SQL Server 2005</a>:</p>
<blockquote><p>Stored Procedure creation in T-SQL doesn’t guarantee to check to see that the dependent objects exist. That’s not a bug, it’s by design.</p>
</blockquote>
<p>According to the SQL Server 2005 Books Online, <a title="Deferred Name Resolution and Compilation" href="http://msdn.microsoft.com/en-us/library/ms190686(SQL.90).aspx">Deferred Name Resolution and Compilation</a>:</p>
<blockquote><p>Deferred name resolution can only be used when you reference nonexistent table objects. All other objects must exist at the time the stored procedure is created. For example, when you reference an existing table in a stored procedure you cannot list nonexistent columns for that table.</p>
</blockquote>
<p>Based on this the creation of the following stored procedure should fail (since the CustomerTypeX column doesn’t exist):</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE </span><span style="color: blue">PROCEDURE </span>[dbo].MyProcedure</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">CREATE TABLE </span>#temp (id uniqueidentifier)</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>Customer.CustomerTypeX</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">FROM </span>Sales.Customer</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">WHERE EXISTS </span>(<span style="color: blue">SELECT </span>* <span style="color: blue">FROM </span>#temp)</p>
<p style="margin: 0px">GO</p>
</p></div>
<p>But SQL Server 2005 creates it without any warning or error. The reference to the temporary table on the nested query seems to make it quit any effort to resolve the identifiers (either table names or column names anywhere in the query), and I see no reason of why it should.</p>
<p>The behavior is also not consistent to what happens when no temporary tables are involved in the nested query. If I remove the nested query and keep everything else from the example in my previous post (I could also keep the nested query and refer to another table, say Person.Contact):</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE </span><span style="color: blue">PROCEDURE </span>[dbo].MyProcedure</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">CREATE TABLE </span>#temp (id uniqueidentifier)</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>CustomerXXX.CustomerType</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">FROM </span>Sales.Customer</p>
<p style="margin: 0px">GO</p>
</p></div>
<p>I get the following error message upon creation:</p>
<blockquote><p><font color="#ff0000">Msg 4104, Level 16, State 1, Procedure MyProcedure, Line 4       <br />The multi-part identifier &quot;CustomerXXX.CustomerType&quot; could not be bound.</font></p>
</blockquote>
<p>Why is it different? For me this is a bug.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/05/12/follow-up-to-strange-bug-in-sql-server-2005/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Exporting SQL Server 2005 database objects to files</title>
		<link>http://techblog.julianhidalgo.com/2009/05/11/exporting-sql-server-2005-database-objects-to-files/</link>
		<comments>http://techblog.julianhidalgo.com/2009/05/11/exporting-sql-server-2005-database-objects-to-files/#comments</comments>
		<pubDate>Mon, 11 May 2009 14:21:05 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/05/11/exporting-sql-server-2005-database-objects-to-files/</guid>
		<description><![CDATA[Last week I wrote a Transact-SQL script for SQL Server 2005 that exports all database objects (stored procedures, triggers, views and so on) to individual files, grouped by object type, and I decided I’d blog about it because it was trickier than I thought at first. These are the things I had to deal with [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I wrote a Transact-SQL script for SQL Server 2005 that exports all database objects (stored procedures, triggers, views and so on) to individual files, grouped by object type, and I decided I’d blog about it because it was trickier than I thought at first. These are the things I had to deal with to make the script work:</p>
<ul>
<li>Writing text to files in SQL Server </li>
<li>Getting the definition of a SQL Server database object </li>
<li>Getting around the security restrictions of SQL Server </li>
</ul>
<p>I’ll review each of them in order (if you just want to download the script skip to the end of the post).</p>
<p><strong>Writing text to files in SQL Server</strong></p>
<p>I didn’t have to think too much about this since <a href="http://www.simple-talk.com/sql/t-sql-programming/the-tsql-of-text-files/">someone already wrote a script to do it</a>. The script basically inserts the text on a global temporary table and uses bulk copy to dump it into a file. However, I did have to modify it to make it work:</p>
<ul>
<li>The script was calling the bcp command with @@servername as the server name parameter. This was causing it to fail on my work machine (but not on my personal laptop), so I changed it to use &#8216;’localhost’ instead. </li>
<li>I modified it to use consistent case for all identifiers so it would work on case-sensitive installations of SQL Server. </li>
</ul>
<p>I also renamed a number of variables and formatted it a little to make it easier to read (at least in my opinion).</p>
<p><strong>Getting the definition of a database object</strong></p>
<p>There are a number of ways to obtain the definition (that is, the Transact-SQL source text) of a database object in SQL Server. Here are the ones I know of:</p>
<ol>
<li>Call the <a href="http://msdn.microsoft.com/en-us/library/ms176112(SQL.90).aspx">sp_helptext</a> stored procedure </li>
<li>Use the <a href="http://msdn.microsoft.com/en-us/library/ms186293(SQL.90).aspx">sys.syscomments</a> system table (deprecated) </li>
<li>Call the <a href="http://msdn.microsoft.com/en-us/library/ms176090(SQL.90).aspx">OBJECT_DEFINITION</a> function </li>
<li>Use the <a href="http://msdn.microsoft.com/en-us/library/ms175081(SQL.90).aspx">sys.sql_modules</a> catalog view </li>
</ol>
<p>It turns out <a href="http://blog.beyondrelational.com/2008/09/be-careful-when-renaming.html">you can only trust the 4th option</a>, as the others can return outdated results. I always use sys.sql_modules anyway, because it’s the way SQL Server Management Studio does it (something I discovered <a href="http://techblog.julianhidalgo.com/2009/03/04/little-trick-to-query-a-sql-server-databases-schema/">by spying on it</a>). </p>
<p><strong>Getting around the security restrictions</strong></p>
<p>SQL Server 2005 disables the ‘<a href="http://msdn.microsoft.com/en-us/library/ms175046(SQL.90).aspx">xp_cmdshell</a>’ extended stored procedure by default (SQL Server 2000 doesn’t), so the initial script was failing with many messages like the following:</p>
<blockquote><p><font color="#ff0000">Msg 15281, Level 16, State 1, Procedure xp_cmdshell, Line 1        <br />SQL Server blocked access to procedure &#8217;sys.xp_cmdshell&#8217; of component &#8216;xp_cmdshell&#8217; because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of &#8216;xp_cmdshell&#8217; by using sp_configure. For more information about enabling &#8216;xp_cmdshell&#8217;, see &quot;Surface Area Configuration&quot; in SQL Server Books Online.</font> </p>
</blockquote>
<p>The good thing is that the message tells you everything you need to know to solve the issue. I modified the script to enable the use of xp_cmdshell using sp_configure, and to restore the setting back to what it was after it’s finished (here I’m assuming that if you are able to run the script at all then you have the permissions to change the setting).</p>
<p><strong>Special considerations for case-sensitive installations of SQL Server</strong></p>
<p>I wrote the initial version of this script in a SQL Server installation that was case sensitive, and something strange happened when I tested it. The output would tell you X stored procedures were found, but there were only X-1 files in the output folder. It turned out that 2 of those stored procedures had a name that differed on the case only. Since the file system in Windows is not case-sensitive the file for one of them ended up replacing the other. I thought of modifying the script to handle this case too, but I decided it was not worth the effort.</p>
<p><strong>Final notes and the script</strong></p>
<p>The final script is divided into 4 stored procedures, to make things easier to understand. They are dropped at the end of execution, but end up as files in the SQL_STORED_PROCEDURE folder (I figured it was easier to just remove them from there than to make the script exclude them). You should make sure the script doesn’t overwrite any stored procedure you may already have in your database before running it.</p>
<p>You can <a href="http://www.julianhidalgo.com/files/ExportDatabaseObjects.sql">grab the final script here</a>. I hope you find it useful, but please note that I make no guarantees, so use it at your own risk! As always, I welcome all suggestions and comments about it. Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/05/11/exporting-sql-server-2005-database-objects-to-files/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Strange bug in SQL Server 2005</title>
		<link>http://techblog.julianhidalgo.com/2009/05/10/strange-bug-in-sql-server-2005/</link>
		<comments>http://techblog.julianhidalgo.com/2009/05/10/strange-bug-in-sql-server-2005/#comments</comments>
		<pubDate>Sun, 10 May 2009 18:02:17 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/05/10/strange-bug-in-sql-server-2005/</guid>
		<description><![CDATA[Take a look to the following stored procedure (which is meant to be run against the AdventureWorks database):

CREATE PROCEDURE [dbo].MyProcedure
AS
&#160;&#160;&#160; CREATE TABLE #temp (id uniqueidentifier)
&#160;&#160;&#160; SELECT Customer.CustomerType
&#160;&#160;&#160; FROM Sales.Customer
&#160;&#160;&#160; WHERE EXISTS (SELECT * FROM #temp)
GO

Although it doesn’t make too much sense, it looks quite simple and straightforward, isn’t it? But try changing “Customer.CustomerType” in the [...]]]></description>
			<content:encoded><![CDATA[<p>Take a look to the following stored procedure (which is meant to be run against the AdventureWorks database):</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE </span><span style="color: blue">PROCEDURE </span>[dbo].MyProcedure</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">CREATE TABLE </span>#temp (id uniqueidentifier)</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>Customer.CustomerType</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">FROM </span>Sales.Customer</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">WHERE EXISTS </span>(<span style="color: blue">SELECT </span>* <span style="color: blue">FROM </span>#temp)</p>
<p style="margin: 0px">GO</p>
</p></div>
<p>Although it doesn’t make too much sense, it looks quite simple and straightforward, isn’t it? But try changing “Customer.CustomerType” in the SELECT clause to “CustomerABCDE.CustomerType” and run it (dropping it first of course). SQL Server will happily create the stored procedure without ever complaining that the identifier doesn’t exist. You can also try changing “Sales.Customer” to “Sales.CustomerWhatever” and SQL Server will not complain either.</p>
<p>This is something that showed up at work, in a much bigger and complex query. By removing lots of code I nailed the problem down to what you see above: using nested queries in the WHERE clause involving temporary tables seems to confuse SQL Server. I don’t see the reason of why this should happen, since the outer query has nothing to do with the inner query.</p>
<p>A friend suggested it could be due to the use of the “EXISTS” keyword, but it’s not (and it shouldn’t). If you change the WHERE clause to the following the stored procedure it’s still created:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: blue">CREATE </span><span style="color: blue">PROCEDURE </span>[dbo].MyProcedure</p>
<p style="margin: 0px"><span style="color: blue">AS</span></p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">CREATE TABLE </span>#temp (id uniqueidentifier)</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">SELECT </span>CustomerXXX.CustomerType</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">FROM </span>Sales.Customer</p>
<p style="margin: 0px">&#160;&#160;&#160; <span style="color: blue">WHERE </span>Customer.CustomerType = (<span style="color: blue">SELECT TOP </span>1 * <span style="color: blue">FROM </span>#temp)</p>
<p style="margin: 0px">GO</p>
</p></div>
<p>I searched to see if this was a known bug, but I didn’t find anything. The stored procedure will still fail when executed, but it’s a weird bug anyway.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/05/10/strange-bug-in-sql-server-2005/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting the source table of output columns for a SQL Server 2005 stored procedure</title>
		<link>http://techblog.julianhidalgo.com/2009/03/25/getting-the-source-table-of-output-columns-for-a-sql-server-2005-stored-procedure/</link>
		<comments>http://techblog.julianhidalgo.com/2009/03/25/getting-the-source-table-of-output-columns-for-a-sql-server-2005-stored-procedure/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 12:49:24 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/03/25/getting-the-source-table-of-output-columns-for-a-sql-server-2005-stored-procedure/</guid>
		<description><![CDATA[Today&#8217;s tip is a relatively simple (but limited) way to programmatically extract the output columns of a SQL Server stored procedure or query along with the tables they come from.
This is something that came up at work. I didn&#8217;t want to do it by hand because there were many stored procedures to check, but it [...]]]></description>
			<content:encoded><![CDATA[<p>Today&#8217;s tip is a relatively simple (but limited) way to programmatically extract the output columns of a SQL Server stored procedure or query along with the tables they come from.</p>
<p>This is something that came up at work. I didn&#8217;t want to do it by hand because there were <em>many</em> stored procedures to check, but it was difficult to automate because they could be (and were indeed) quite complex, with many selects and joins, computed columns, aliases and so on, and to make things worse the SQL code had no standard indentation or structure, so string searching and regular expressions were not reliable options. Parsing the Transact-SQL code would have been way harder than anything else, so it was out of discussion too. Unfortunately, the limitations of this solution (that I&#8217;ll mention later) stopped us from using and we had to do the job by hand.</p>
<p>Lazy as I am, I wanted to make SQL Server itself give me the information I needed. After meditating about it for a while an idea came to my mind: I could try to extract the information from the execution plan.</p>
<p>You probably know it, but the query execution plan that you can see in <a href="http://msdn.microsoft.com/en-us/library/ms174173.aspx">Microsoft SQL Server Management Studio</a> (SSMS from now on) comes from the SQL Server engine in XML format -SSMS just displays it in a graphical form. This XML is a real gem that provides lots of information about the query (even things that aren&#8217;t displayed in the execution plan tab), and you can see it by setting the &#8220;<a href="http://technet.microsoft.com/en-us/library/ms176107.aspx">SET STATISTICS XML</a>&#8221; option to ON before you run your query. For example, let&#8217;s run the following query (just a plain SQL query so you can see what it&#8217;s going on, but remember that it&#8217;s the same for stored procedures) that joins the Product and ProductSubcategory tables of the AdventureWorks sample database:</p>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms-012.png" alt="ssms 01" width="631" height="368" /></div>
<p>Notice that I got two result sets. The first is the query&#8217;s result, and the second is the execution plan in XML format (if you don&#8217;t see it, make sure the &#8220;Include Actual Execution Plan&#8221; option isn&#8217;t turned on). If you click on the link SSMS will open the XML in a new window:</p>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms-02.png" alt="ssms 02" width="632" height="290" /></div>
<p>Look at the <strong>OutputList</strong> node in there. It contains all the columns that appear in the result, each one within a ColumnReference element:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #0000ff;">          &lt;</span><span style="color: #a31515;">ColumnReference</span><span style="color: #0000ff;"> </span><span style="color: #ff0000;">Database</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[AdventureWorks]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Schema</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Production]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Table</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Product]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Alias</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[p]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Column</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">ProductID</span>&#8220;<span style="color: #0000ff;"> /&gt;</span></p>
<p style="margin: 0px"><span style="color: #0000ff;">          &lt;</span><span style="color: #a31515;">ColumnReference</span><span style="color: #0000ff;"> </span><span style="color: #ff0000;">Database</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[AdventureWorks]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Schema</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Production]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Table</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Product]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Alias</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[p]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Column</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">Name</span>&#8220;<span style="color: #0000ff;"> /&gt;</span></p>
<p style="margin: 0px"><span style="color: #0000ff;">          &lt;</span><span style="color: #a31515;">ColumnReference</span><span style="color: #0000ff;"> </span><span style="color: #ff0000;">Database</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[AdventureWorks]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Schema</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Production]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Table</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Product]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Alias</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[p]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Column</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">ProductNumber</span>&#8220;<span style="color: #0000ff;"> /&gt;</span></p>
<p style="margin: 0px"><span style="color: #0000ff;">          &lt;</span><span style="color: #a31515;">ColumnReference</span><span style="color: #0000ff;"> </span><span style="color: #ff0000;">Database</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[AdventureWorks]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Schema</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Production]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Table</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Product]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Alias</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[p]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Column</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">Color</span>&#8220;<span style="color: #0000ff;"> /&gt;</span></p>
<p style="margin: 0px"><span style="color: #0000ff;">          &lt;</span><span style="color: #a31515;">ColumnReference</span><span style="color: #0000ff;"> </span><span style="color: #ff0000;">Database</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[AdventureWorks]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Schema</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Production]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Table</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Product]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Alias</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[p]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Column</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">StandardCost</span>&#8220;<span style="color: #0000ff;"> /&gt;</span></p>
<p style="margin: 0px"><span style="color: #0000ff;">          &lt;</span><span style="color: #a31515;">ColumnReference</span><span style="color: #0000ff;"> </span><span style="color: #ff0000;">Database</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[AdventureWorks]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Schema</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[Production]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Table</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[ProductSubcategory]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Alias</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">[psc]</span>&#8220;<span style="color: #0000ff;"> </span><span style="color: #ff0000;">Column</span><span style="color: #0000ff;">=</span>&#8220;<span style="color: #0000ff;">Name</span>&#8220;<span style="color: #0000ff;"> /&gt;</span></p>
</div>
<p>As you can see the information is quite detailed: for each column you have the database, the table and the schema it belongs to. A non-intuitive thing to keep in mind is that the <strong>Alias</strong> attribute is not the column&#8217;s alias, but the table&#8217;s.</p>
<p>Armed with this knowledge we can now create a tool to extract the information automatically: it&#8217;s just a matter of executing the stored procedure and retrieving the execution plan to process it. But let&#8217;s do one last thing before jumping to the code. I don&#8217;t know about you, but I <em>really</em> hate to work with XML -I&#8217;d rather work against an object model. It turns out that we can do just that: the <a href="http://schemas.microsoft.com/sqlserver/2004/07/showplan/">ShowPlan&#8217;s schema is publicly available for download</a>, and with it and the <a href="http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.80).aspx">XML Schema Definition Tool</a> (xsd.exe, located at C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\xsd.exe on my machine) we can create the classes needed to take the execution plan&#8217;s XML and deserialize into an object graph. Run this command to generate the classes (I renamed the showplanxml.xml.xsd file I downloaded to showplanxml.xsd):</p>
<blockquote><p>xsd C:\showplanxml.xsd /classes /o:C:\</p></blockquote>
<p>This will create a file in C: called showplan.cs with several classes within it (the root being ShowPlanXML) that we can now include in a new project in Visual Studio (you may want to add a namespace to the generated classes). The code required to get a ShowPlanXML instance from the execution plan is really simple:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">XmlReader</span> reader = <span style="color: #2b91af;">XmlReader</span>.Create(<span style="color: #a31515;">&#8220;ExecutionPlan.xml&#8221;</span>, <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">XmlReaderSettings</span>()))</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">XmlSerializer</span> serializer = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">XmlSerializer</span>(<span style="color: #0000ff;">typeof</span>(<span style="color: #2b91af;">ShowPlanXML</span>));</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ShowPlanXML</span> plan = (<span style="color: #2b91af;">ShowPlanXML</span>)serializer.Deserialize(reader);</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(plan.Version);</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;}</p>
</div>
<p>In the code snippet above I&#8217;m loading the XML from a local file just for demo purposes. In the real application I read it from a SqlDataReader after executing the stored procedure. I&#8217;m printing the version just to make sure the deserialization worked. But let&#8217;s do something more interesting:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<div style="font-size: 10pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">StmtBlockType</span>[] blocks <span style="color: #0000ff;">in</span> plan.BatchSequence)</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">StmtBlockType</span> block <span style="color: #0000ff;">in</span> blocks)</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">BaseStmtInfoType</span> item <span style="color: #0000ff;">in</span> block.Items)</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">StmtSimpleType</span> statement = item <span style="color: #0000ff;">as</span> <span style="color: #2b91af;">StmtSimpleType</span>;</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span> (statement != <span style="color: #0000ff;">null</span>)</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">foreach </span>(<span style="color: #2b91af;">ColumnReferenceType </span>columnReference <span style="color: #0000ff;">in</span> statement.QueryPlan.RelOp.OutputList)</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(columnReference.Table + <span style="color: #a31515;">&#8221; - &#8220;</span> + columnReference.Column);</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p style="margin: 0px">&nbsp;&nbsp;&nbsp;&nbsp;}</p>
</div>
</div>
<p>Here I go through all the batches and statements until I reach the column references. The <strong>BaseStmtInfoType</strong> class has 4 derived classes: <strong>StmtCursorType</strong>, <strong>StmtReceiveType</strong>, <strong>StmtSimpleType</strong>, and <strong>StmtUseDbType</strong> (all these types are generated by xsd.exe too). You can tell more or less what case each one stands for based on the names. Since I&#8217;m looking for statements I only handle the case when the item is a StmtSimpleType instance. When I compile and run the code I get the following output:</p>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/console-output.png" alt="console output" width="388" height="132" /></div>
<p>Voilà! This is just what I wanted. Now some things to consider about the structure of the execution plan:</p>
<ul>
<li>For each step in the execution plan you&#8217;ll see a RelOp node (with its corresponding OutputList node). These nodes are nested according to the order they were executed. In our case:<br />
<img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms-03.png" alt="ssms 03" width="464" height="218" /><br />
We&#8217;ll have 3 RelOp nodes: the outermost one will be a Hash Match, containing two others, an Index Scan and a Clustered Index Scan (this is probably easier to understand if you see the graphical execution plan and the XML document side by side).<br />
The good news is that for our purposes we only need to worry about the first RelOp node, since it corresponds to the last operation (the Hash Match).</li>
<li>If you have more than one SQL statement in your stored procedure you&#8217;ll get execution plans for each of them. If you just care about the last result set you only need to process the last execution plan:<br />
<img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms-04.png" alt="ssms 04" width="477" height="361" /></li>
<li><a href="http://technet.microsoft.com/en-us/library/ms176107.aspx">SET STATISTICS XML ON</a> will execute the query. The benefit of this is that you can extract the columns aliases from the SqlDataReader and match them by position with columns in the XML execution plan, provided you don&#8217;t have computed columns (see &#8220;Limitations&#8221; later). If you don&#8217;t need the aliases you can use the <a href="http://technet.microsoft.com/en-us/library/ms187757.aspx">SET SHOWPLAN_XML</a> option instead, which will generate the execution plan but will not actually execute the query, and therefore should be faster.</li>
</ul>
<p><strong>Limitations</strong></p>
<p>This technique has 3 big limitations:</p>
<ul>
<li>If you have computed columns the resulting XML will be much more complex. For example, let&#8217;s add a new column computed with a CASE statement to our query:<br />
<img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms05.png" alt="ssms05" width="653" height="188" /><br />
Now the execution plan will look like this:<br />
<img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms06.png" alt="ssms06" width="503" height="83" /><br />
As you can see the column is referred to as &#8220;Expr1004&#8243;. To actually find the expression you will have to navigate (possibly deep) into the document:<br />
<img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/ssms07.png" alt="ssms07" width="612" height="334" /><br />
The entire CASE expression is in the XML, and you can get to the actual column used (MakeFlag) but it can be tedious (and this is intended to be a simple trick).</li>
<li>You can&#8217;t determine the column aliases. The XML document doesn&#8217;t contain the aliases. At first I thought I could match the column references in the OuputList node to the column names from the query result by position, but unfortunately the columns in the XML are not necessarily in the same order. I was quite disappointed when I saw this because it makes this technique far less powerful (I&#8217;ve only checked in SQL Server 2005, perhaps things are better in SQL Server 2005 SP2 or SP3, or SQL Server 2008, but I don&#8217;t have any of them handy to check).</li>
<li>If you have conditional logic the parameters that you pass to the stored procedure <em>matter</em>. This what you would expect since we are working with an execution plan anyway.</li>
</ul>
<p>Well that&#8217;s all. I&#8217;m planning to upload a sample application for all this, but I&#8217;m too tired to do it tonight, so wait for the next post if you are interested. Hope this helps, happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/03/25/getting-the-source-table-of-output-columns-for-a-sql-server-2005-stored-procedure/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Article Summary: &#8220;What Every Dev Must Know About Multithreaded Apps&#8221;</title>
		<link>http://techblog.julianhidalgo.com/2009/03/11/article-summary-what-every-dev-must-know-about-multithreaded-apps/</link>
		<comments>http://techblog.julianhidalgo.com/2009/03/11/article-summary-what-every-dev-must-know-about-multithreaded-apps/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 17:08:32 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/?p=37</guid>
		<description><![CDATA[There is a great MSDN Magazine article about multithreading applications called &#8220;What Every Dev Must Know About Multithreaded Apps&#8220;, written by Vance Morrison, an architect on the .NET Runtime Team.
I read the article a long time ago, but I decided to re-read it and to post a short summary here, just to make sure I remember the [...]]]></description>
			<content:encoded><![CDATA[<p>There is a great MSDN Magazine article about multithreading applications called &#8220;<a title="What Every Dev Must Know About Multithreaded Apps" href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx">What Every Dev Must Know About Multithreaded Apps</a>&#8220;, written by <a title="Vance Morrison's blog" href="http://blogs.msdn.com/vancem/">Vance Morrison</a>, an architect on the .NET Runtime Team.</p>
<p>I read the article a long time ago, but I decided to re-read it and to post a short summary here, just to make sure I remember the important points of it. The summary has links to the corresponding sections in Vance&#8217;s article. </p>
<hr />
<p><strong><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx">Introduction</a></strong></p>
<ul>
<li>The fundamental requirement for writing correct programs is the same whether the program is sequential or multithreaded: all code in the program must protect any invariants that other parts of the program need, but preserving program invariants is much more difficult in the multithreaded case.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S1"><strong>Threads and Memory</strong></a></p>
<ul>
<li>The tricky part of multithreaded programming is how threads communicate with one another.</li>
<li>The most commonly deployed multithreaded communication model is called the shared memory model:
<ul>
<li>In this model all threads have access to the same pool of shared memory.</li>
<li>Its advantage and also its biggest problem is that multithreaded programs are programmed in much the same way as sequential programs.</li>
<li>The model does not distinguish between memory that is being used strictly for thread local use (like most locally declared variables), and memory that is being used to communicate with other threads (like some global variables and heap memory).</li>
</ul>
</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S2"><strong>Races</strong></a></p>
<ul>
<li>There are four conditions needed for a race to be possible:
<ul>
<li>There are memory locations (typically global/static variables or heap memory reachable from global/static variables) that are accessible from more than one thread.</li>
<li>There is a property associated with these shared memory locations that is needed for the program to function correctly. Typically, the property needs to hold true before an update occurs for the update to be correct.</li>
<li>The property does not hold during some part of the actual update.</li>
<li>Another thread accesses the memory when the invariant is broken, thereby causing incorrect behavior.</li>
</ul>
</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S3"><strong>Locks</strong></a></p>
<ul>
<li>The most common way of preventing races is to use locks to prevent other threads from accessing memory associated with an invariant while it is broken. This removes the fourth condition required for a race, thus making it impossible to happen.</li>
<li>In the Microsoft .NET Framework locks are implemented by the <a href="http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx">System.Threading.Monitor</a> class.</li>
<li>The <a href="http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx">lock statement</a> in C# is a shortcut for the following:
<div style="font-size: 10pt; background: white; color: black; font-family: Courier New;">
<p style="margin: 0px;">        System.Threading.<span style="color: #2b91af;">Monitor</span>.Enter(someObject);</p>
<p style="margin: 0px;">        <span style="color: #0000ff;">try</span></p>
<p style="margin: 0px;">        {</p>
<p style="margin: 0px;">            <span style="color: #008000;">// body</span></p>
<p style="margin: 0px;">        }</p>
<p style="margin: 0px;">        <span style="color: #0000ff;">finally</span></p>
<p style="margin: 0px;">        {</p>
<p style="margin: 0px;">            System.Threading.<span style="color: #2b91af;">Monitor</span>.Exit(someObject);</p>
<p style="margin: 0px;">        }</p>
</div>
<p><!--EndFragment--></li>
<li>Exceptions in a lock block must be properly handled. The lock is there to ensure an invariant, so it&#8217;s important to make sure that the invariant wasn&#8217;t broken as a result of the exception.</li>
<li>A simple lock statement is appropriate if there is no useful cleanup to do or if everything in its body is read-only.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S4"><strong>Using locks properly</strong></a></p>
<ul>
<li>Locks provide mutual exclusion for regions of code, but generally programmers want to protect <strong>regions of memory</strong>.</li>
<li>For a lock to provide mutual exclusion for a region of memory, no writes to that memory can occur without entering the same lock. In a properly designed program, associated with every lock is a region of memory for which it provides mutual exclusion. There is no obvious artifact of the code that makes this association clear, and yet this information is absolutely critical for anyone reasoning about the multithreaded behavior of the program.</li>
<li>Every lock should have a specification associated with it that documents the precise region of memory (set of data structures) for which it provides mutual exclusion.</li>
<li>While having memory regions protected by different locks that overlap is not strictly incorrect, it should be avoided because it is not useful.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S5"><strong>How many locks?</strong></a></p>
<ul>
<li>The main disadvantage of having more than one lock is the complexity involved. The program has more parts associated with it so there is more opportunity for programmer error.</li>
<li>It is best to have few locks that protect large regions of memory and only split them when lock contention is shown to be a bottleneck on performance.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S6"><strong>Taking Locks on Reads</strong></a></p>
<ul>
<li>A lock should always be entered before writing a memory location. When memory is read the case is a little more complicated because it depends on the programmer&#8217;s expectations.</li>
<li>In general, when code needs a program invariant, all locks associated with any memory involved with the invariant must be taken.</li>
<li>For multithreaded applications the programmer&#8217;s mindset should change from believing that nothing changes unless it is explicitly changed to believing that everything changes unless locks are used to prevent it.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S7"><strong>What Memory Needs Lock Protection?</strong></a></p>
<ul>
<li>An easy and correct answer would be that all memory needs to be protected by a lock, but this would be overkill for most apps.</li>
<li>Memory can be made safe for multithreaded use in one of several ways:
<ul>
<li>Memory that is only accessed by a single thread is safe because other threads are unaffected by it. This includes most local variables and all heap-allocated memory before it is published (made reachable to other threads). Once memory is published, however, it falls out of this category and some other technique must be used.</li>
<li>Memory that is read-only after publication does not need a lock because any invariants associated with it must hold for the rest of the program (since the value does not change).</li>
<li>Memory that is actively updated from multiple threads generally uses locks to ensure that only one thread has access while a program invariant is broken.</li>
<li>In certain specialized cases where the program invariant is relatively weak, it is possible to perform updates that can be done without locks. Typically, specialized compare-and-exchange instructions are used. These techniques are best thought of as special, lightweight implementations of locks. </li>
</ul>
</li>
<li>A general rule should be that all program memory should fall into one of three buckets: thread exclusive, read-only, or lock protected.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S8"><strong>Methodical Locking</strong> </a></p>
<ul>
<li>In a well-designed class, clients only access its internal state by calling its instance methods. If a lock is taken on entry to any instance method, and released on exit, there is a systematic way of ensuring that all accesses to internal data (instance fields) only occur when the lock is held. Classes that follow this protocol are called <strong>monitors</strong> (<strong>NOTE</strong>: So in essence monitors are classes that thread-safe because they synchronize access to their internal data. See <a href="http://en.wikipedia.org/wiki/Monitor_(synchronization)">this Wikipedia article about monitors</a> for a better explanation of the concept).</li>
<li>The concept of a monitor is one of the simplest and most useful techniques for methodical locking.</li>
<li>The name of a lock in the .NET Framework is <a href="http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx">System.Threading.Monitor</a>, a type specifically tailored to support the monitor concept.</li>
<li>.NET locks operate on System.Object to make the creation of monitors easier.</li>
<li>Every object has a built-in lock that can be used to protect its instance data. By embedding the body of every instance method in a lock(this) statement, a monitor can be formed (<strong>NOTE</strong>: <a title="Jeffrey Richter's blog" href="http://www.wintellect.com/cs/blogs/jeffreyr/default.aspx">Jeffrey Richter</a>, in his &#8220;<a href="http://www.microsoft.com/learning/en/us/Books/6522.aspx">CLR via C#, Second edition</a>&#8220; book, explains why using lock(this) or lock(typeof(ClassName)) isn&#8217;t a good idea. See [1] in the footnotes).</li>
<li>There is a special attribute, [<a href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimplattribute.aspx">MethodImpl(MethodImplAttributes.Synchronized)</a>], that can be placed on instance methods to automatically insert the lock(this) statement (<strong>NOTE</strong>: Since this attribute will surround the method&#8217;s code with a lock(this) is it&#8217;s an instance methof or a lock(typeof(<em>typename</em>)) if it&#8217;s a static method, you should never use this attribute either. Again, see [1] in the footnotes).</li>
<li>.NET locks are reentrant, meaning that the thread that has entered the lock can enter the lock again without blocking. This allows methods to call other methods on the same class without causing the deadlock that would normally occur.</li>
<li>Indiscriminate use of monitors can result in either too little or too much locking.</li>
<li>An important weakness with the monitor concept is that it provides no protection if the class gives out updatable pointers to its data.</li>
<li>Monitors don&#8217;t address the more complicated situation when multiple locks need to be taken.</li>
<li>Generally speaking, most reusable code (like container classes) should not have locks built into it because it can only protect itself, and it is likely that whatever code uses it will need a stronger lock anyway. The exception to this rule is when it is important that the code works even with high-level program errors. The global memory heap and security-sensitive code are examples of exceptional cases.</li>
<li>It is less error prone and more efficient to have just a few locks that protect large amounts of memory. A single lock that protects many data structures is a good design if it allows the desired amount of concurrency. If the work each of the threads will do doesn&#8217;t require many updates to shared memory, consider taking this principle to the extreme and having one lock that protects all shared memory. It works well for applications whose worker threads don&#8217;t interact much.</li>
<li>In cases where threads read shared structures frequently, but write to them infrequently, reader-writer locks such as <a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx">System.Threading.ReaderWriterLock</a> can be used to keep the number of locks in the system low (<strong>NOTE</strong>: Jeffrey Richter also says in his &#8220;CLR via C#, Second edition&#8221; book that he doesn&#8217;t recommend that anyone <strong><em>ever </em></strong>use this class, see [2] in the footnotes). This type of lock has one method for entering for reading and one for entering for writing. The lock will allow multiple readers to enter concurrently, but writers get exclusive access. Since readers now don&#8217;t block one another, the system can be made simpler (containing fewer locks) and still achieve the necessary concurrency.</li>
<li>Lock usage can often be at odds with normal object-oriented program abstraction because locking is really another independent dimension of the program that has its own design criteria (other such dimensions include lifecycle management, transactional behavior, real-time constraints, and exception-handling behavior).</li>
<li>If some method does not take locks itself, but expects its caller to provide that mutual exclusion, then that requirement is a precondition of calling that method and should be in its interface contract.</li>
<li>If a data abstraction might take a lock or call client (virtual) methods while holding a lock, that also needs to be part of the interface contract. </li>
<li>There is little that class library designers can do to make the library friendlier to multithreading, because locking just one data structure is rarely useful. It is only when the threading structure of program is designed that locks can be usefully added.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S9"><strong>Deadlock</strong></a></p>
<ul>
<li>Once a program has more than one lock deadlock becomes a possibility, which is another reason to avoid having many locks in the system.</li>
<li>Deadlocks can only occur if there is a circular chain of threads such that each thread in the chain is waiting on a lock already acquired by the next in line. For example, if one thread tries to enter Lock A and then Lock B, while simultaneously another thread tries to enter Lock B and then Lock A, it is possible for them to deadlock if each enters the lock that the other owns before attempting to enter the second lock.</li>
<li>Deadlocks are generally prevented in one of two ways:
<ul>
<li>The best way to prevent deadlock is to have few enough locks in the system that it is never necessary to take more than one lock at a time.</li>
<li>If the former is impossible, deadlock can also be prevented by having a convention on the order in which locks are taken. Each lock in the system is assigned a &#8220;level&#8221;, and the program is designed so that threads always take locks only in strictly descending order by level. This protocol makes cycles involving locks, and therefore deadlock, impossible. If this strategy does not work (can&#8217;t find a set of levels), it is likely that the lock-taking behavior of the program is so input-dependent that it is impossible to guarantee that deadlock cannot happen in every case. Typically, this type of code falls back on timeouts or some kind of deadlock detection scheme.</li>
</ul>
</li>
<li>An analysis must be made to determine why more than one lock has to be taken simultaneously.</li>
<li>Taking multiple locks is only necessary when code needs to get exclusive access to memory protected by different locks. This analysis typically either yields a trivial lock ordering that will avoid deadlock or shows that complete deadlock avoidance is impossible.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S10"><strong>The Cost of Locks</strong></a></p>
<ul>
<li>Another reason to avoid having many locks in a system is the cost of entering and leaving a lock.</li>
<li>The lightest locks use a special compare/exchange instruction to check whether the lock is taken, and if it isn&#8217;t, they enter the lock in a single atomic action. This special instruction is relatively expensive (typically ten to hundreds of times longer than an ordinary instruction).</li>
<li>There are two main reasons for this expense, and they both have to do with issues arising on a true multiprocessor system:
<ul>
<li>The compare/exchange instruction must ensure that no other processor is also trying to do the same thing. Fundamentally, this requires one processor to coordinate with all other processors in the system. This is a slow operation and accounts for the lower bound of the cost of a lock (dozens of cycles).</li>
<li>The other reason for the expense is the effect inter-process communication has on the memory system. After a lock has been taken, the program is very likely to access memory that may have been recently modified by another thread. If this thread ran on another processor, it is necessary to ensure that all pending writes on all other processors have been flushed so that the current thread sees the updates. The cost of doing this largely depends on how the memory system works and how many writes need to be flushed. This cost can be pretty high in the worst case (possibly hundreds of cycles or more).</li>
</ul>
</li>
<li>The cost of a lock is can be significant. If a frequently called method needs to take a lock and only executes a hundred or so instructions, lock overhead is likely to be an issue. The program generally needs to be redesigned so that the lock can be held for a larger unit of work.</li>
<li>As the number of processors in the system grows locks become the main impediment in using all the processors efficiently:
<ul>
<li>If there are too few locks in the program, it is impossible to keep all the processors busy since they are waiting on memory that is locked by another processor.</li>
<li>If there are many locks in the program, it is easy to have a &#8220;hot&#8221; lock that is being entered and exited frequently by many processors. This causes the memory-flushing overhead to be very high, and throughput again does not scale linearly with the number of processors. The only design that scales well is one in which worker threads can do significant work without interacting with shared data.</li>
</ul>
</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S11"><strong>A Quick Word on Synchronization</strong></a></p>
<ul>
<li>Locks don&#8217;t really provide a mechanism for threads to synchronize.</li>
<li>The principles for synchronizing threads without introducing races are not much different from the principles for proper locking.</li>
<li>In the .NET Framework synchronization functionality is implemented in the <a href="http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx">ManualResetEvent</a> and <a href="http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx">AutoResetEvent</a> classes. These classes provide Set, Reset, and WaitOne methods: the WaitOne method causes a thread to block as long as the event is in the reset state. When another thread calls the Set method, AutoResetEvents will allow one thread that called WaitOne to unblock, while ManualResetEvents will unblock all waiting threads.</li>
<li>Generally, events are used to signal that a more complicated program property holds.</li>
<li>In general, it&#8217;s a bad idea to hold locks while waiting on events.</li>
</ul>
<p><a href="http://msdn.microsoft.com/en-us/magazine/cc163744.aspx#S12"><strong>Conclusion</strong></a></p>
<ul>
<li>The difference between sequential and multithreaded programs is that protecting program invariants is more complicated in the multithreaded case. </li>
<li>It requires a significantly higher degree of discipline to build a correct multithreaded program:
<ul>
<li>Ensuring through tools like monitors that all thread-shared, read-write data is protected by locks.</li>
<li>Carefully design which memory is protected by which lock.</li>
<li>Controlling the extra complexity that locks inevitably add to the program.</li>
</ul>
</li>
<li>Good designs are typically the simplest, and for multithreaded programs this means having the fewest number of locks that achieve the needed concurrency.</li>
</ul>
<p> </p>
<hr /><strong>Footnotes</strong></p>
<p>[1] Simply stated, when you lock on the <strong>this </strong>pointer or the object&#8217;s type, you open the possibility for malicious code to deadlock threads that use that type. For a complete explanation see pages 636-639 of &#8220;<a href="http://www.microsoft.com/learning/en/us/Books/6522.aspx">CLR via C#, Second Edition</a>&#8220;.</p>
<p>[2] The ReaderWriterLock class has three flaws: its performance is awful, even when there is not contention on the lock, it has a policy of favoring readers over writers, &#8220;writers get starved for time and do not complete their work in a timely fashion&#8221;, and finally it supports recursion, meaning that the thread that enters the lock must be the thread that exits it (Richter consider this a bug because it&#8217;s becoming commonplace to have a thread enter a lock and start an operation to access some data and have another thread to complete the operation and exit the lock, specially likely in a asynchronous programming model). See pages 642-643 of &#8220;<a href="http://www.microsoft.com/learning/en/us/Books/6522.aspx">CLR via C#, Second Edition</a>&#8220;.</p>
<p>So that&#8217;s it. If you are new to multithreading programming I strongly suggest you to read the original article. Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/03/11/article-summary-what-every-dev-must-know-about-multithreaded-apps/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Little trick to query a SQL Server database&#8217;s schema</title>
		<link>http://techblog.julianhidalgo.com/2009/03/04/little-trick-to-query-a-sql-server-databases-schema/</link>
		<comments>http://techblog.julianhidalgo.com/2009/03/04/little-trick-to-query-a-sql-server-databases-schema/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 13:06:31 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[SQL Server]]></category>

		<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/?p=31</guid>
		<description><![CDATA[This is the easiest way to query the schema of a database I know of:

First go to SQL Server Management Studio, expand the databases node and go to the list of tables. In this example I&#8217;m using the AdventureWorks database:



Launch the SQL Profiler and start a new trace.
Right-click the tables node and select &#8220;Refresh&#8221;:



Now you can [...]]]></description>
			<content:encoded><![CDATA[<p>This is the easiest way to query the schema of a database I know of:</p>
<ul>
<li>First go to SQL Server Management Studio, expand the databases node and go to the list of tables. In this example I&#8217;m using the AdventureWorks database:</li>
</ul>
<p style="text-align: center;"><a href="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/01-sql-management-studio.jpg"><img class="alignnone size-medium wp-image-32" title="01-sql-management-studio" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/01-sql-management-studio-300x245.jpg" alt="" width="300" height="245" /></a></p>
<ul>
<li>Launch the SQL Profiler and start a new trace.</li>
<li>Right-click the tables node and select &#8220;Refresh&#8221;:</li>
</ul>
<p style="text-align: center;"><a href="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/02-sql-management-studio.jpg"><img class="alignnone size-medium wp-image-33" title="02-sql-management-studio" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/02-sql-management-studio.jpg" alt="" width="233" height="193" /></a></p>
<ul>
<li style="text-align: left;">Now you can see the the query that the SSMS used in the SQL Profiler:</li>
</ul>
<p style="text-align: center;"><a href="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/03-sql-profiler1.jpg"><img class="alignnone size-medium wp-image-35" title="03-sql-profiler1" src="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/03-sql-profiler1-300x227.jpg" alt="" width="300" height="227" /></a></p>
<p style="text-align: left;">And that&#8217;s it, you just have to customize it to fit your needs. You can apply this to query other type of objects of course, like indexes, keys and so on (basically anything you see in SSMS). For example, the following query will list all the columns and the table they belong to:</p>
<p style="text-align: left;"><span style="font-size: x-small; color: #0000ff;">SELECT<br />
</span><span style="font-size: x-small;">tbl</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">name </span><span style="font-size: x-small; color: #0000ff;">as</span><span style="font-size: x-small;"> TableName</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small;">clmns </span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">name </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [Name]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small; color: #ff00ff;">CAST </span><span style="font-size: x-small; color: #808080;">(</span><span style="font-size: x-small; color: #ff00ff;">ISNULL</span><span style="font-size: x-small; color: #808080;">(</span><span style="font-size: x-small;">cik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">index_column_id</span><span style="font-size: x-small; color: #808080;">,</span><span style="font-size: x-small;"> 0</span><span style="font-size: x-small; color: #808080;">)</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">bit</span><span style="font-size: x-small; color: #808080;">)</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [InPrimaryKey]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small; color: #ff00ff;">CAST </span><span style="font-size: x-small; color: #808080;">(</span><span style="font-size: x-small; color: #ff00ff;">ISNULL</span><span style="font-size: x-small; color: #808080;">((</span><span style="font-size: x-small; color: #0000ff;">select</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">TOP</span><span style="font-size: x-small;"> 1 1 </span><span style="font-size: x-small; color: #0000ff;">from</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #008000;">sys.foreign_key_columns</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> colfk </span><span style="font-size: x-small; color: #0000ff;">where</span><span style="font-size: x-small;"> colfk</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">parent_column_id </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">column_id </span><span style="font-size: x-small; color: #808080;">and</span><span style="font-size: x-small;"> colfk</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">parent_object_id </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id</span><span style="font-size: x-small; color: #808080;">),</span><span style="font-size: x-small;"> 0</span><span style="font-size: x-small; color: #808080;">)</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">bit</span><span style="font-size: x-small; color: #808080;">)</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [IsForeignKey]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small;">usrt</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">name </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [DataType]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small; color: #ff00ff;">CAST </span><span style="font-size: x-small; color: #808080;">(</span><span style="font-size: x-small;">clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">precision </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">int</span><span style="font-size: x-small; color: #808080;">)</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [NumericPrecision]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small; color: #ff00ff;">CAST </span><span style="font-size: x-small; color: #808080;">(</span><span style="font-size: x-small;">clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">scale </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">int</span><span style="font-size: x-small; color: #808080;">)</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [NumericScale]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small;">clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">is_nullable </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [Nullable]</span><span style="font-size: x-small; color: #808080;">,<br />
</span><span style="font-size: x-small;">clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">is_computed </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> [Computed]<br />
</span><span style="font-size: x-small; color: #0000ff;">FROM<br />
</span><span style="font-size: x-small; color: #008000;">sys.tables</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> tbl<br />
</span><span style="font-size: x-small; color: #808080;">INNER </span><span style="font-size: x-small; color: #808080;">JOIN</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #008000;">sys.all_columns</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> clmns </span><span style="font-size: x-small; color: #0000ff;">ON</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id</span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;">tbl</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id<br />
</span><span style="font-size: x-small; color: #808080;">LEFT</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">OUTER</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">JOIN</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #008000;">sys.indexes</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> ik </span><span style="font-size: x-small; color: #0000ff;">ON</span><span style="font-size: x-small;"> ik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">and</span><span style="font-size: x-small;"> 1</span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;">ik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">is_primary_key<br />
</span><span style="font-size: x-small; color: #808080;">LEFT </span><span style="font-size: x-small; color: #808080;">OUTER</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">JOIN</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #008000;">sys.index_columns</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> cik </span><span style="font-size: x-small; color: #0000ff;">ON</span><span style="font-size: x-small;"> cik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">index_id </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> ik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">index_id </span><span style="font-size: x-small; color: #808080;">and</span><span style="font-size: x-small;"> cik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">column_id </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">column_id </span><span style="font-size: x-small; color: #808080;">and</span><span style="font-size: x-small;"> cik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #ff00ff;">object_id</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">and</span><span style="font-size: x-small;"> 0 </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> cik</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">is_included_column<br />
</span><span style="font-size: x-small; color: #808080;">LEFT</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">OUTER</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #808080;">JOIN</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #008000;">sys.types</span><span style="font-size: x-small;"> </span><span style="font-size: x-small; color: #0000ff;">AS</span><span style="font-size: x-small;"> usrt </span><span style="font-size: x-small; color: #0000ff;">ON</span><span style="font-size: x-small;"> usrt</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">user_type_id </span><span style="font-size: x-small; color: #808080;">=</span><span style="font-size: x-small;"> clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">user_type_id<br />
</span><span style="font-size: x-small; color: #0000ff;">ORDER </span><span style="font-size: x-small; color: #0000ff;">BY <span style="color: #000000;">tbl</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small; color: #000000;">name, </span></span><span style="font-size: x-small;">clmns</span><span style="font-size: x-small; color: #808080;">.</span><span style="font-size: x-small;">name</span></p>
<p style="text-align: left;">To obtain it I refreshed the list of columns in a table, and from the resulting query I removed a couple of joins and the where clause, and added a different ORDER BY clause.</p>
<p>An extra bonus of this trick is that by examining the queries SSMS uses you&#8217;ll learn more about SQL Server itself.</p>
<p>Hope it helps :)</p>
<p> </p>
<p><a href="http://techblog.julianhidalgo.com/wp-content/uploads/2009/03/03-sql-profiler.jpg"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/03/04/little-trick-to-query-a-sql-server-databases-schema/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Improving the blog</title>
		<link>http://techblog.julianhidalgo.com/2009/02/10/improving-the-blog/</link>
		<comments>http://techblog.julianhidalgo.com/2009/02/10/improving-the-blog/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 00:01:42 +0000</pubDate>
		<dc:creator>Julián Hidalgo</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.julianhidalgo.com/2009/02/10/improving-the-blog/</guid>
		<description><![CDATA[I&#8217;m trying to improve the content of the blog, so I added 3 new and so far quite incomplete sections:

Books
Selected Links
Video Courses

It&#8217;s also a way of organizing the content in a better way and saving links to the stuff I like without cluttering the blog (I hate posts that just link to other&#8217;s people work [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m trying to improve the content of the blog, so I added 3 new and so far quite incomplete sections:</p>
<ul>
<li><a href="http://techblog.julianhidalgo.com/books/">Books</a></li>
<li><a href="http://techblog.julianhidalgo.com/selected-links/">Selected Links</a></li>
<li><a href="http://techblog.julianhidalgo.com/video-courses/">Video Courses</a></li>
</ul>
<p>It&#8217;s also a way of organizing the content in a better way and saving links to the stuff I like without cluttering the blog (I hate posts that just link to other&#8217;s people work or content). I hope it can be useful for some of you out there. See you next time!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.julianhidalgo.com/2009/02/10/improving-the-blog/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
