<?xml version="1.0" encoding="utf-8"?><!-- generator="b2evolution/7.2.5-stable" -->
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Mark Clerget's Blog</title>
		<link>http://blogs.consultantsguild.com/index.php?blog=6</link>
		<atom:link rel="self" type="application/rss+xml" href="http://blogs.consultantsguild.com/index.php?blog=6&#38;tempskin=_rss2" />
		<description></description>
		<language>en-US</language>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<admin:generatorAgent rdf:resource="http://b2evolution.net/?v=7.2.5-stable"/>
		<ttl>60</ttl>
				<item>
			<title>Excellent Consultants...or Why Technology Kingdoms Rise and Fall</title>
			<link>http://blogs.consultantsguild.com/index.php/excellent_consultants?blog=6</link>
			<pubDate>Sun, 20 Feb 2005 01:19:34 +0000</pubDate>			<dc:creator>Mark</dc:creator>
			<category domain="alt">General</category>
<category domain="main">Best Practices</category>			<guid isPermaLink="false">70@http://blogs.consultantsguild.com/</guid>
						<description>&lt;p&gt;The experience of a recent Consultants Guild blog reader drives home the key factors that cause projects and engineering organizations to fail.  It also is a good reminder of what is necessary in order to be an Excellent Consultant.  So indulge me for a moment and let me tell a little story of Excellent Consultants...or Why Technology Kingdoms Rise and Fall.  &lt;/p&gt;

&lt;p&gt;His experience was being confronted with &lt;a href=&quot;http://blogs.consultantsguild.com/index.php/wayne/2005/02/18/extracting_column_name_for_a_table_in_sq#comments&quot;&gt; antagonistic interviewers&lt;/a&gt; that didn’t understand a technically superior solution.  I had a very similar experience trying to do a Sybase port of the &lt;a href=&quot;http://blogs.consultantsguild.com/index.php/mclerget/2005/01/31/dynamic_t_sql_in_just_minutes&quot;&gt;dynamic inline T-SQL aggregation&lt;/a&gt; construct that I&#039;ve used numerous times in SQL Server.  I&#039;m first and foremost a SQL Server implementation expert, but very proficient in other database products.  We were forced to implement a SQL Server database on Sybase.  I used this construct extensively to avoid laborious and expensive CURSORS.  Then the unthinkable happened (well not really for Sybase), they released a patch which broke the &lt;a href=&quot;http://blogs.consultantsguild.com/index.php/mclerget/2005/01/31/dynamic_t_sql_in_just_minutes&quot;&gt;dynamic inline T-SQL aggregation&lt;/a&gt; construct in Sybase.  Once we finally tracked down why critical portions of our system were broken, Sybase’s response was first disbelief that this approach even worked.  When I proved that it did they responded…“Well, that never should have worked in the first place, so we aren’t going to support it going forward.”  &lt;/p&gt;

&lt;p&gt;Hmmm.  That doesn’t seem too intelligent to me.  Am I having a nightmare here?  Let me do a reality check.  So I asked myself a question…”Mark, I asked…Who is paying Sybase here?”.  Yep, the answer is me and the customer that I’m implementing Sybase for.  &lt;/p&gt;

&lt;p&gt;That lack of disrespect for the basic customer-vendor food chain required about 2 weeks of redesign of some key backend stored procedures and processes.  Needless to say, it didn’t serve to improve my perspective of Sybase.  The customer spent between $100k-$200k in the original port from Sybase to SQL Server.  What value did it add….ZERO.  It cost more, took longer and performed poorer.  Fast forward...now the customer decided that their strategic direction is to migrate all Sybase applications to Microsoft SQL Server.  So, it will cost Sybase millions of dollars from this customer and any customer that I do business with in the future that is willing to listen to my experience.  &lt;/p&gt;

&lt;p&gt;Nope, it wasn’t a nightmare after all.  At least not mine (maybe Sybase’s though).  Whew!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.haacked.com&quot;&gt;Haacked’s&lt;/a&gt; experience of &lt;a href=&quot;http://blogs.consultantsguild.com/index.php/wayne/2005/02/18/extracting_column_name_for_a_table_in_sq#comments&quot;&gt;interviewers that think they know it all&lt;/a&gt;, like my experience, taught me an important lesson.  As technicians, we need to continually remind ourselves that fear, pride and ignorance are the greatest barriers to success.  There is almost always a more elegant, more simplistic, more cost effective and higher performing way to solve a problem.   Furthermore, I have found that fear, pride and ignorance are the hallmarks of project failure.  It can have enormous cost implications to us as consultants, to the tool vendors we utilize and ultimately the customers we serve.&lt;/p&gt;

&lt;p&gt;For the &lt;a href=&quot;http://blogs.consultantsguild.com/index.php/wayne/2005/02/18/extracting_column_name_for_a_table_in_sq#comments&quot;&gt;interviewers that thought they know it all&lt;/a&gt;, it cost them a potentially great resource and asset.  In my scenario it cost my customer hundreds of thousands of dollars.  Ultimately it will cost Sybase millions of dollars.  &lt;/p&gt;

&lt;p&gt;The lesson I learned is this, technology kingdoms rise and fall primarily due to fear, pride and ignorance.  Excellent consultants, at least the ones I am willing to work with, have no room for any of these traits.  If you are on a project where fear, pride and ignorance are given free reign, raise the red flag high.  Waive the flag with vigor.  Get executive sponsorship and root it out.  These people are the type that are continually complaining, blaming and failing.  An end user cracked me up with describing these type of people like this...&quot;Their cubicles are vortexes where all happy thoughts go to die&quot;.  Sadly their teams and their organizations are where good projects go to die as well.&lt;/p&gt;

&lt;p&gt;What excellent consultants possess, at least the ones that I’m willing to work with, are increasing measures of boldness, confidence and wisdom.  Boldness replaces fear, confidence replaces pride and wisdom replaces ignorance.  We in the &lt;a href=&quot;http://www.consultantsguild.com&quot;&gt;Consultants Guild&lt;/a&gt; are passionate about Experience, Integrity and Delivery.  They are the mark of Excellent Consultants.  &lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Excellent Consultants are…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Excellent consultants are bold enough to look for new ways to deliver successful solutions better.  Whether it’s a technical challenge, a business challenge or a process challenge they always strive for success.  They don’t shrink away in fear or let pride or ignorance cause them to fail.  Typically they will lean on their wealth of experience and/or the deep pool of experience from other excellent consultants that they’ve been in the trenches with.  Boldness is the key to successful delivery when the barriers seem insurmountable.&lt;/p&gt;

&lt;p&gt;Excellent consultants are confident in their experience that has led them to success in the past.  The proof is in the pudding.  A key principle of Agile software development is that “Working software is the primary measure of progress.”  Given a reasonable amount of customer trust and freedom, I’m fully confident that I will make them successful.  This shouldn’t be confused with pride or arrogance because I’ll readily admit when I need the help of others.  Confidence is only developed through experiencing repeated success. &lt;/p&gt;

&lt;p&gt;Excellent consultants are wise enough to know what they don’t know.  A common misconception about wisdom is that it means knowing everything.  It does have to do with knowledge, but its much more than that.  Wisdom is when knowledge is applied through the filter of “experience”.  I also heard someone once say that “Wisdom is knowing what you don’t know”.  Just becaues a ASP.NET application was a perfect solution for one customer, doesn&#039;t mean that its the only solution for every customer.  We were faced with this challenge on a current project and realized that it was in the best interest of the client to build a .NET Win Forms Smart Client application vs. a traditional .NET Web Form HTML based application.  Wisdom grows as we do business with integrity by looking to the mutual best interest of our clients and ourselves.&lt;/p&gt;&lt;/blockquote&gt;

&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.consultantsguild.com/index.php/excellent_consultants?blog=6&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>The experience of a recent Consultants Guild blog reader drives home the key factors that cause projects and engineering organizations to fail.  It also is a good reminder of what is necessary in order to be an Excellent Consultant.  So indulge me for a moment and let me tell a little story of Excellent Consultants...or Why Technology Kingdoms Rise and Fall.  </p>

<p>His experience was being confronted with <a href="http://blogs.consultantsguild.com/index.php/wayne/2005/02/18/extracting_column_name_for_a_table_in_sq#comments"> antagonistic interviewers</a> that didn’t understand a technically superior solution.  I had a very similar experience trying to do a Sybase port of the <a href="http://blogs.consultantsguild.com/index.php/mclerget/2005/01/31/dynamic_t_sql_in_just_minutes">dynamic inline T-SQL aggregation</a> construct that I've used numerous times in SQL Server.  I'm first and foremost a SQL Server implementation expert, but very proficient in other database products.  We were forced to implement a SQL Server database on Sybase.  I used this construct extensively to avoid laborious and expensive CURSORS.  Then the unthinkable happened (well not really for Sybase), they released a patch which broke the <a href="http://blogs.consultantsguild.com/index.php/mclerget/2005/01/31/dynamic_t_sql_in_just_minutes">dynamic inline T-SQL aggregation</a> construct in Sybase.  Once we finally tracked down why critical portions of our system were broken, Sybase’s response was first disbelief that this approach even worked.  When I proved that it did they responded…“Well, that never should have worked in the first place, so we aren’t going to support it going forward.”  </p>

<p>Hmmm.  That doesn’t seem too intelligent to me.  Am I having a nightmare here?  Let me do a reality check.  So I asked myself a question…”Mark, I asked…Who is paying Sybase here?”.  Yep, the answer is me and the customer that I’m implementing Sybase for.  </p>

<p>That lack of disrespect for the basic customer-vendor food chain required about 2 weeks of redesign of some key backend stored procedures and processes.  Needless to say, it didn’t serve to improve my perspective of Sybase.  The customer spent between $100k-$200k in the original port from Sybase to SQL Server.  What value did it add….ZERO.  It cost more, took longer and performed poorer.  Fast forward...now the customer decided that their strategic direction is to migrate all Sybase applications to Microsoft SQL Server.  So, it will cost Sybase millions of dollars from this customer and any customer that I do business with in the future that is willing to listen to my experience.  </p>

<p>Nope, it wasn’t a nightmare after all.  At least not mine (maybe Sybase’s though).  Whew!</p>

<p><a href="http://www.haacked.com">Haacked’s</a> experience of <a href="http://blogs.consultantsguild.com/index.php/wayne/2005/02/18/extracting_column_name_for_a_table_in_sq#comments">interviewers that think they know it all</a>, like my experience, taught me an important lesson.  As technicians, we need to continually remind ourselves that fear, pride and ignorance are the greatest barriers to success.  There is almost always a more elegant, more simplistic, more cost effective and higher performing way to solve a problem.   Furthermore, I have found that fear, pride and ignorance are the hallmarks of project failure.  It can have enormous cost implications to us as consultants, to the tool vendors we utilize and ultimately the customers we serve.</p>

<p>For the <a href="http://blogs.consultantsguild.com/index.php/wayne/2005/02/18/extracting_column_name_for_a_table_in_sq#comments">interviewers that thought they know it all</a>, it cost them a potentially great resource and asset.  In my scenario it cost my customer hundreds of thousands of dollars.  Ultimately it will cost Sybase millions of dollars.  </p>

<p>The lesson I learned is this, technology kingdoms rise and fall primarily due to fear, pride and ignorance.  Excellent consultants, at least the ones I am willing to work with, have no room for any of these traits.  If you are on a project where fear, pride and ignorance are given free reign, raise the red flag high.  Waive the flag with vigor.  Get executive sponsorship and root it out.  These people are the type that are continually complaining, blaming and failing.  An end user cracked me up with describing these type of people like this..."Their cubicles are vortexes where all happy thoughts go to die".  Sadly their teams and their organizations are where good projects go to die as well.</p>

<p>What excellent consultants possess, at least the ones that I’m willing to work with, are increasing measures of boldness, confidence and wisdom.  Boldness replaces fear, confidence replaces pride and wisdom replaces ignorance.  We in the <a href="http://www.consultantsguild.com">Consultants Guild</a> are passionate about Experience, Integrity and Delivery.  They are the mark of Excellent Consultants.  </p>

<blockquote><p><strong>Excellent Consultants are…</strong></p>

<p>Excellent consultants are bold enough to look for new ways to deliver successful solutions better.  Whether it’s a technical challenge, a business challenge or a process challenge they always strive for success.  They don’t shrink away in fear or let pride or ignorance cause them to fail.  Typically they will lean on their wealth of experience and/or the deep pool of experience from other excellent consultants that they’ve been in the trenches with.  Boldness is the key to successful delivery when the barriers seem insurmountable.</p>

<p>Excellent consultants are confident in their experience that has led them to success in the past.  The proof is in the pudding.  A key principle of Agile software development is that “Working software is the primary measure of progress.”  Given a reasonable amount of customer trust and freedom, I’m fully confident that I will make them successful.  This shouldn’t be confused with pride or arrogance because I’ll readily admit when I need the help of others.  Confidence is only developed through experiencing repeated success. </p>

<p>Excellent consultants are wise enough to know what they don’t know.  A common misconception about wisdom is that it means knowing everything.  It does have to do with knowledge, but its much more than that.  Wisdom is when knowledge is applied through the filter of “experience”.  I also heard someone once say that “Wisdom is knowing what you don’t know”.  Just becaues a ASP.NET application was a perfect solution for one customer, doesn't mean that its the only solution for every customer.  We were faced with this challenge on a current project and realized that it was in the best interest of the client to build a .NET Win Forms Smart Client application vs. a traditional .NET Web Form HTML based application.  Wisdom grows as we do business with integrity by looking to the mutual best interest of our clients and ourselves.</p></blockquote>

<div class="item_footer"><p><small><a href="http://blogs.consultantsguild.com/index.php/excellent_consultants?blog=6">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.consultantsguild.com/index.php/excellent_consultants?blog=6#comments</comments>
			<wfw:commentRss>http://blogs.consultantsguild.com/index.php?blog=6&#38;tempskin=_rss2&#38;disp=comments&#38;p=70</wfw:commentRss>
		</item>
				<item>
			<title>Dynamic SQL INSERT Generator Unleashed!</title>
			<link>http://blogs.consultantsguild.com/index.php/dynamic_sql_insert_generator_unleashed_1?blog=6</link>
			<pubDate>Tue, 08 Feb 2005 08:58:10 +0000</pubDate>			<dc:creator>Mark</dc:creator>
			<category domain="main">General</category>			<guid isPermaLink="false">60@http://blogs.consultantsguild.com/</guid>
						<description>&lt;p&gt;Okay, so I&#039;m hyping a bit.  So give me a break...this little gem took me a few days to write and weeks to refine in the 90&#039;s.  Anyway, I updated it to take advantage of the &quot;dynamic aggregator&quot; approach shown in my previous query.  &lt;/p&gt;

&lt;p&gt;So you are probably saying, &quot;Great, so you can generate a CREATE TABLE statement...Whoopee!&quot;.  Well, if I could help you fill that table or tables using a script that dynamically generates INSERT statements based on the contents of a table, would that be worth something to you?  Great!  Read further and lets really impress those SQL jockey friends of yours.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Problem to Solve&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
Write a query that dynamically generates a series of INSRET statements based on the contents of a table.  The output of this query can then be used to fill an empty table or replace a table.  It also accomodates preserving IDENTITY columns.&lt;/p&gt;


&lt;p&gt;&lt;u&gt;&lt;strong&gt;Goals&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
Like always, I try to make my SQL tools reusable and tight.  In this query, I opt to blend simplicity (one cursor for the tables) with the powerful &quot;dynamic aggregator&quot; shown in my last blog (for the columns).  So without further delay....&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Solution to the Problem&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
Paste the following query into a SQL Server Query Analyzer window and set the current database to the desired database that you want to generate the INSERT script for.  Change the WHERE clause of the DECLARE CURSOR query to reflect one or more tables from that database.  Set the output format to Text.  Then let &#039;er fly! (eg: run the query)....&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;&lt;br /&gt;
create table #tmp (&lt;br /&gt;
	SQLText		varchar(8000) )&lt;br /&gt;
&lt;br /&gt;
create table #tmp2 (&lt;br /&gt;
	Id		int identity,&lt;br /&gt;
	SQLText		varchar(8000) )&lt;br /&gt;
&lt;br /&gt;
set nocount on&lt;br /&gt;
&lt;br /&gt;
delete #tmp&lt;br /&gt;
delete #tmp2&lt;br /&gt;
&lt;br /&gt;
declare	@vsSQL		varchar(8000),&lt;br /&gt;
	@vsCols		varchar(8000),&lt;br /&gt;
	@vsTableName 	varchar(40)&lt;br /&gt;
&lt;br /&gt;
declare csrTables cursor for&lt;br /&gt;
	select 	name &lt;br /&gt;
	from 	sysobjects &lt;br /&gt;
	where 	type in (&#039;u&#039;)&lt;br /&gt;
	and	name in (&#039;Customers&#039;)&lt;br /&gt;
	order by name&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
open csrTables&lt;br /&gt;
fetch next from csrTables into @vsTableName&lt;br /&gt;
&lt;br /&gt;
while (@@fetch_status = 0)&lt;br /&gt;
begin&lt;br /&gt;
&lt;br /&gt;
	select 	@vsSQL = &#039;&#039;,&lt;br /&gt;
		@vsCols = &#039;&#039;&lt;br /&gt;
	select	@vsSQL = @vsSQL +		&lt;br /&gt;
		CASE 	when sc.type in (39,47,61,111) then&lt;br /&gt;
				&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;+&#039; + &#039;isnull(rtrim(replace(&#039;+ sc.name + &#039;,&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;,&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;)),&#039;&#039;&#039;&#039;)&#039; + &#039;+&#039;&#039;&#039;&#039;&#039;&#039;,&#039;&#039;+&#039;&lt;br /&gt;
			when sc.type = 35 then&lt;br /&gt;
				&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;+&#039; + &#039;isnull(rtrim(replace(substring(&#039;+ sc.name + &#039;,1,1000),&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;,&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&#039;)),&#039;&#039;&#039;&#039;)&#039; + &#039;+&#039;&#039;&#039;&#039;&#039;&#039;,&#039;&#039;+&#039;&lt;br /&gt;
			else&lt;br /&gt;
				&#039;isnull(convert(varchar,&#039; + sc.name + &#039;),&#039;&#039;null&#039;&#039;)+&#039;&#039;,&#039;&#039;+&#039;&lt;br /&gt;
		end &lt;br /&gt;
	from	syscolumns sc &lt;br /&gt;
	where	sc.id = object_id(@vsTableName)&lt;br /&gt;
	order by ColID&lt;br /&gt;
&lt;br /&gt;
	select	@vsCols = @vsCols + sc.name + &#039;,&#039;		&lt;br /&gt;
	from	syscolumns sc &lt;br /&gt;
	where	sc.id = object_id(@vsTableName)&lt;br /&gt;
	order by ColID&lt;br /&gt;
    &lt;br /&gt;
	select @vsSQL = substring(@vsSQL,1,datalength(@vsSQL)-1)&lt;br /&gt;
&lt;br /&gt;
	select @vsCols =  substring(@vsCols,1,datalength(@vsCols)-1)&lt;br /&gt;
&lt;br /&gt;
	insert #tmp&lt;br /&gt;
	exec (&#039;select &#039; + @vsSQL + &#039; from &#039; + @vsTableName)&lt;br /&gt;
	&lt;br /&gt;
	update #tmp&lt;br /&gt;
	set sqltext = &#039;insert &#039; + @vsTableName + &#039;(&#039; + @vsCols + &#039;) values(&#039; + substring(sqltext,1,datalength(sqltext)-1) + &#039;)&#039;&lt;br /&gt;
&lt;br /&gt;
	insert #tmp2 &lt;br /&gt;
	select &#039;DELETE from &#039; + @vsTableName&lt;br /&gt;
&lt;br /&gt;
	insert #tmp2 values (&#039;GO&#039;)&lt;br /&gt;
&lt;br /&gt;
	if (select count(id) from syscolumns where id = object_id(@vsTableName)  and ((status &amp;amp; 128) = 128) ) = 1 &lt;br /&gt;
	begin&lt;br /&gt;
		insert #tmp2 &lt;br /&gt;
		select &#039;set identity_insert &#039; + @vsTableName + &#039; on&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	insert #tmp2&lt;br /&gt;
	select * from #tmp&lt;br /&gt;
&lt;br /&gt;
	if (select count(id) from syscolumns where id = object_id(@vsTableName)  and ((status &amp;amp; 128) = 128) ) = 1 &lt;br /&gt;
	begin&lt;br /&gt;
		insert #tmp2 &lt;br /&gt;
		select &#039;set identity_insert &#039; + @vsTableName + &#039; off&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	insert #tmp2 values (&#039;GO&#039;)&lt;br /&gt;
&lt;br /&gt;
	insert #tmp2 &lt;br /&gt;
	select &#039;update statistics &#039; + @vsTableName &lt;br /&gt;
&lt;br /&gt;
	insert #tmp2 values (&#039;GO&#039;)&lt;br /&gt;
&lt;br /&gt;
	delete #tmp&lt;br /&gt;
&lt;br /&gt;
	fetch next from csrTables into @vsTableName&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
close      csrTables&lt;br /&gt;
deallocate csrTables&lt;br /&gt;
&lt;br /&gt;
update #tmp2&lt;br /&gt;
set sqltext = substring(sqltext,1,charindex(&#039;,)&#039;,sqltext)-1) + &#039;,NULL)&#039;&lt;br /&gt;
where not(charindex(&#039;,)&#039;,sqltext) = 0)&lt;br /&gt;
&lt;br /&gt;
update #tmp2&lt;br /&gt;
set sqltext = replace(sqltext, &#039;,&#039;&#039;&#039;&#039;&#039;,&#039;,null&#039;)&lt;br /&gt;
where not (charindex(&#039;,&#039;&#039;&#039;&#039;&#039;,sqltext) = 0)&lt;br /&gt;
&lt;br /&gt;
update #tmp2&lt;br /&gt;
set sqltext = replace(sqltext, &#039;(&#039;&#039;&#039;&#039;&#039;,&#039;,null&#039;)&lt;br /&gt;
where not (charindex(&#039;(&#039;&#039;&#039;&#039;&#039;,sqltext) = 0)&lt;br /&gt;
&lt;br /&gt;
set nocount off&lt;br /&gt;
&lt;br /&gt;
select sqltext from #tmp2 order by id&lt;br /&gt;
&lt;br /&gt;
go&lt;br /&gt;
&lt;br /&gt;
drop table #tmp&lt;br /&gt;
drop table #tmp2&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The resulting output will be an auto-generated INSERT script that can be used to migrate data and/or seed a new database/tables.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Things to grok:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;HONEST DISCLAIMER:  Notice that this has limitations (8000 characters of SQL per INSERT line, NO image data types).  It handles about 90-95% of the needs that I use it for, but please understand that I have tweaked and embellished it over time.  So use it at your own risk.  If you find a bug/enhancement, please let me know.&lt;/li&gt;  &lt;li&gt;Notice the nifty &quot;dynamic aggregator&quot; queries used to build up the main @vsSQL and @vsCols variables.  This pattern can be leveraged over and over to generate powerful SQL&lt;/li&gt; &lt;li&gt; Don&#039;t freak about the batch of single quotes.  If you are going to do dynamic SQL, you need to know how to use these.  Each quote must be represented by two single quotes.  For example:  SELECT &#039;&#039;&#039;&#039; will result in the display of one (1) single quote in the result set.  The best thing to do is to experiment with this until you grok it.&lt;/li&gt; &lt;li&gt;Notice the use of the &quot;EXEC (@sql)&quot; construct to dynamically execute SQL to generate more SQL.&lt;/li&gt;  &lt;li&gt;Notice the concluding few UPDATE queries to &quot;massage&quot; the INSERT SQL to handle NULLs and final columns in the table.  Why punish yourself by embedding all of the conditional logic in the main queries when a few simple UPDATE statements can be used to &quot;massage&quot; the data at the end.  I use this pattern routinely.  This is one distinct advantage of SQL/Set based operations vs. iterative constructs...So use it!&lt;/li&gt;&lt;/ul&gt;


&lt;p&gt;&lt;u&gt;&lt;strong&gt;Coming next on my blog:&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
Hope you found this blog entry useful.  I know that this tool has been indispensable for me.  So, you may be wondering...&quot;Is this guy just a SQL junkie?&quot;  Well, the answer is yes and no.  I am a SQL Junky, but not &quot;just&quot; a SQL junky.  I also specialize in the design, architecture and implementation of enterprise-wide n-tier applications.  &lt;/p&gt;

&lt;p&gt;So, I&#039;m going to share a bit of a blend in my next blog.  See how I leverage the pervious pattern to generate VB.NET Business Classes to be consumed in an n-tier .NET Smart Client application...&quot;Dynamic SQL begets .NET Business Classes&quot;.  My theory is, I like classes and I like SQL, so why code redundant patterns by hand?  The answer is, you don&#039;t have to!&lt;/p&gt;

&lt;p&gt;Now, go and &quot;REALLY&quot; impress your SQL jockey friends!&lt;/p&gt;
&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.consultantsguild.com/index.php/dynamic_sql_insert_generator_unleashed_1?blog=6&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Okay, so I'm hyping a bit.  So give me a break...this little gem took me a few days to write and weeks to refine in the 90's.  Anyway, I updated it to take advantage of the "dynamic aggregator" approach shown in my previous query.  </p>

<p>So you are probably saying, "Great, so you can generate a CREATE TABLE statement...Whoopee!".  Well, if I could help you fill that table or tables using a script that dynamically generates INSERT statements based on the contents of a table, would that be worth something to you?  Great!  Read further and lets really impress those SQL jockey friends of yours.</p>

<p><u><strong>Problem to Solve</strong></u><br />
Write a query that dynamically generates a series of INSRET statements based on the contents of a table.  The output of this query can then be used to fill an empty table or replace a table.  It also accomodates preserving IDENTITY columns.</p>


<p><u><strong>Goals</strong></u><br />
Like always, I try to make my SQL tools reusable and tight.  In this query, I opt to blend simplicity (one cursor for the tables) with the powerful "dynamic aggregator" shown in my last blog (for the columns).  So without further delay....</p>

<p><u><strong>Solution to the Problem</strong></u><br />
Paste the following query into a SQL Server Query Analyzer window and set the current database to the desired database that you want to generate the INSERT script for.  Change the WHERE clause of the DECLARE CURSOR query to reflect one or more tables from that database.  Set the output format to Text.  Then let 'er fly! (eg: run the query)....</p>

<blockquote><p><code><br />
create table #tmp (<br />
	SQLText		varchar(8000) )<br />
<br />
create table #tmp2 (<br />
	Id		int identity,<br />
	SQLText		varchar(8000) )<br />
<br />
set nocount on<br />
<br />
delete #tmp<br />
delete #tmp2<br />
<br />
declare	@vsSQL		varchar(8000),<br />
	@vsCols		varchar(8000),<br />
	@vsTableName 	varchar(40)<br />
<br />
declare csrTables cursor for<br />
	select 	name <br />
	from 	sysobjects <br />
	where 	type in ('u')<br />
	and	name in ('Customers')<br />
	order by name<br />
<br />
<br />
open csrTables<br />
fetch next from csrTables into @vsTableName<br />
<br />
while (@@fetch_status = 0)<br />
begin<br />
<br />
	select 	@vsSQL = '',<br />
		@vsCols = ''<br />
	select	@vsSQL = @vsSQL +		<br />
		CASE 	when sc.type in (39,47,61,111) then<br />
				'''''''''+' + 'isnull(rtrim(replace('+ sc.name + ','''''''','''''''''''')),'''')' + '+'''''',''+'<br />
			when sc.type = 35 then<br />
				'''''''''+' + 'isnull(rtrim(replace(substring('+ sc.name + ',1,1000),'''''''','''''''''''')),'''')' + '+'''''',''+'<br />
			else<br />
				'isnull(convert(varchar,' + sc.name + '),''null'')+'',''+'<br />
		end <br />
	from	syscolumns sc <br />
	where	sc.id = object_id(@vsTableName)<br />
	order by ColID<br />
<br />
	select	@vsCols = @vsCols + sc.name + ','		<br />
	from	syscolumns sc <br />
	where	sc.id = object_id(@vsTableName)<br />
	order by ColID<br />
    <br />
	select @vsSQL = substring(@vsSQL,1,datalength(@vsSQL)-1)<br />
<br />
	select @vsCols =  substring(@vsCols,1,datalength(@vsCols)-1)<br />
<br />
	insert #tmp<br />
	exec ('select ' + @vsSQL + ' from ' + @vsTableName)<br />
	<br />
	update #tmp<br />
	set sqltext = 'insert ' + @vsTableName + '(' + @vsCols + ') values(' + substring(sqltext,1,datalength(sqltext)-1) + ')'<br />
<br />
	insert #tmp2 <br />
	select 'DELETE from ' + @vsTableName<br />
<br />
	insert #tmp2 values ('GO')<br />
<br />
	if (select count(id) from syscolumns where id = object_id(@vsTableName)  and ((status &amp; 128) = 128) ) = 1 <br />
	begin<br />
		insert #tmp2 <br />
		select 'set identity_insert ' + @vsTableName + ' on'<br />
	end<br />
<br />
	insert #tmp2<br />
	select * from #tmp<br />
<br />
	if (select count(id) from syscolumns where id = object_id(@vsTableName)  and ((status &amp; 128) = 128) ) = 1 <br />
	begin<br />
		insert #tmp2 <br />
		select 'set identity_insert ' + @vsTableName + ' off'<br />
	end<br />
<br />
	insert #tmp2 values ('GO')<br />
<br />
	insert #tmp2 <br />
	select 'update statistics ' + @vsTableName <br />
<br />
	insert #tmp2 values ('GO')<br />
<br />
	delete #tmp<br />
<br />
	fetch next from csrTables into @vsTableName<br />
<br />
end<br />
<br />
close      csrTables<br />
deallocate csrTables<br />
<br />
update #tmp2<br />
set sqltext = substring(sqltext,1,charindex(',)',sqltext)-1) + ',NULL)'<br />
where not(charindex(',)',sqltext) = 0)<br />
<br />
update #tmp2<br />
set sqltext = replace(sqltext, ',''''',',null')<br />
where not (charindex(',''''',sqltext) = 0)<br />
<br />
update #tmp2<br />
set sqltext = replace(sqltext, '(''''',',null')<br />
where not (charindex('(''''',sqltext) = 0)<br />
<br />
set nocount off<br />
<br />
select sqltext from #tmp2 order by id<br />
<br />
go<br />
<br />
drop table #tmp<br />
drop table #tmp2<br />
</code></p></blockquote>

<p>The resulting output will be an auto-generated INSERT script that can be used to migrate data and/or seed a new database/tables.</p>

<p><u><strong>Things to grok:</strong></u></p>
<ul><li>HONEST DISCLAIMER:  Notice that this has limitations (8000 characters of SQL per INSERT line, NO image data types).  It handles about 90-95% of the needs that I use it for, but please understand that I have tweaked and embellished it over time.  So use it at your own risk.  If you find a bug/enhancement, please let me know.</li>  <li>Notice the nifty "dynamic aggregator" queries used to build up the main @vsSQL and @vsCols variables.  This pattern can be leveraged over and over to generate powerful SQL</li> <li> Don't freak about the batch of single quotes.  If you are going to do dynamic SQL, you need to know how to use these.  Each quote must be represented by two single quotes.  For example:  SELECT '''' will result in the display of one (1) single quote in the result set.  The best thing to do is to experiment with this until you grok it.</li> <li>Notice the use of the "EXEC (@sql)" construct to dynamically execute SQL to generate more SQL.</li>  <li>Notice the concluding few UPDATE queries to "massage" the INSERT SQL to handle NULLs and final columns in the table.  Why punish yourself by embedding all of the conditional logic in the main queries when a few simple UPDATE statements can be used to "massage" the data at the end.  I use this pattern routinely.  This is one distinct advantage of SQL/Set based operations vs. iterative constructs...So use it!</li></ul>


<p><u><strong>Coming next on my blog:</strong></u><br />
Hope you found this blog entry useful.  I know that this tool has been indispensable for me.  So, you may be wondering..."Is this guy just a SQL junkie?"  Well, the answer is yes and no.  I am a SQL Junky, but not "just" a SQL junky.  I also specialize in the design, architecture and implementation of enterprise-wide n-tier applications.  </p>

<p>So, I'm going to share a bit of a blend in my next blog.  See how I leverage the pervious pattern to generate VB.NET Business Classes to be consumed in an n-tier .NET Smart Client application..."Dynamic SQL begets .NET Business Classes".  My theory is, I like classes and I like SQL, so why code redundant patterns by hand?  The answer is, you don't have to!</p>

<p>Now, go and "REALLY" impress your SQL jockey friends!</p>
<div class="item_footer"><p><small><a href="http://blogs.consultantsguild.com/index.php/dynamic_sql_insert_generator_unleashed_1?blog=6">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.consultantsguild.com/index.php/dynamic_sql_insert_generator_unleashed_1?blog=6#comments</comments>
			<wfw:commentRss>http://blogs.consultantsguild.com/index.php?blog=6&#38;tempskin=_rss2&#38;disp=comments&#38;p=60</wfw:commentRss>
		</item>
				<item>
			<title>Dynamic T-SQL in Just Minutes!</title>
			<link>http://blogs.consultantsguild.com/index.php/dynamic_t_sql_in_just_minutes?blog=6</link>
			<pubDate>Tue, 01 Feb 2005 06:15:24 +0000</pubDate>			<dc:creator>Mark</dc:creator>
			<category domain="main">General</category>			<guid isPermaLink="false">55@http://blogs.consultantsguild.com/</guid>
						<description>&lt;p&gt;Ever feel left behind when one of those SQL Server jockies breezes through a complex query that generates SQL on the fly?  After all its a bit over the top to use SQL to generate SQL, isn&#039;t it?  Well, its time to level the playing field.  I&#039;m going to pass on a simple pattern that you can use to generate the most sophisticated queries.  This pattern will lead to an endless supply of SQL/Database tools to add to your library.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Problem to Solve&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
Write a query that generates a CREATE TABLE definition from any table.  Then write a query that generates INSERT statements to fill a copy of that table based on the current data.&lt;/p&gt;

&lt;p&gt;So you are probably saying to yourself...Wouldn&#039;t just be easier to type the CREATE TABLE definition by hand?  Maybe so for the first one, but imagine doing it for an entire database of 300+ tables.  Or you may say...Couldn&#039;t I just use the T-SQL generator in Enterprise Manager (or equivalent)?  Sure, but if you want to take your skills to the next level, its time to make an investment.  Besides, does anyone else hate the excess baggage that those tools include in the generated SQL?  Me too.  So, dynamic SQL to the rescue.  &lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Goals&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
I always try to make my SQL tools reusable and tight.  I could do a lot of things using brute force CURSORS or WHILE loops in SQL, but I try to avoid that.  So I&#039;m going to give you a little gem that will aggregate the statement on-the-fly in one SQL statement.  So without further delay....&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Solution to the Problem&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
Paste the following query into a SQL Server Query Analyzer window and set the current database to Northwind.  Set the output format to Text.  Then run the query....&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br /&gt;
declare @vsSQL		varchar(8000)&lt;br /&gt;
declare @vsTableName 	varchar(50)&lt;br /&gt;
select @vsTableName = &#039;Customers&#039;&lt;br /&gt;
&lt;br /&gt;
select @vsSQL = &#039;CREATE TABLE &#039; + @vsTableName + char(10) + &#039;(&#039; + char(10)&lt;br /&gt;
&lt;br /&gt;
select	@vsSQL = @vsSQL + &#039;   &#039; + sc.Name + &#039; &#039; + &lt;br /&gt;
	st.Name +&lt;br /&gt;
	case when st.Name in (&#039;varchar&#039;,&#039;varchar&#039;,&#039;char&#039;,&#039;nchar&#039;) then &#039;(&#039; + cast(sc.Length as varchar) + &#039;) &#039; else &#039; &#039; end + &lt;br /&gt;
	case when sc.IsNullable = 1 then &#039;NULL&#039; else &#039;NOT NULL&#039; end + &#039;,&#039; + char(10)&lt;br /&gt;
from	sysobjects so&lt;br /&gt;
join 	syscolumns sc on sc.id = so.id&lt;br /&gt;
join	systypes st on st.xusertype = sc.xusertype&lt;br /&gt;
where	so.name = @vsTableName&lt;br /&gt;
order by&lt;br /&gt;
	sc.ColID&lt;br /&gt;
&lt;br /&gt;
select substring(@vsSQL,1,len(@vsSQL) - 2) + char(10) + &#039;)&#039;&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The resulting output will be a auto-generated CREATE TABLE statement:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CREATE TABLE Customers&lt;br /&gt;
(&lt;br /&gt;
   CustomerID nchar(10) NOT NULL,&lt;br /&gt;
   CompanyName nvarchar(80) NOT NULL,&lt;br /&gt;
   ContactName nvarchar(60) NULL,&lt;br /&gt;
   ContactTitle nvarchar(60) NULL,&lt;br /&gt;
   Address nvarchar(120) NULL,&lt;br /&gt;
   City nvarchar(30) NULL,&lt;br /&gt;
   Region nvarchar(30) NULL,&lt;br /&gt;
   PostalCode nvarchar(20) NULL,&lt;br /&gt;
   Country nvarchar(30) NULL,&lt;br /&gt;
   Phone nvarchar(48) NULL,&lt;br /&gt;
   Fax nvarchar(48) NULL&lt;br /&gt;
)&lt;/code&gt;&lt;/p&gt;


&lt;p&gt;&lt;u&gt;&lt;strong&gt;Things to grok:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Notice the nifty main SQL statement that aggregates the SQL string variable @vsSQL on-the-fly.&lt;/li&gt;  &lt;li&gt;Notice how to leverage the combination of sysobjects (for tables),  (for column Des) and systypes (for data types properties).  &lt;/li&gt;  &lt;li&gt;Notice the use of char(10) to append carriage returns to the SQL for decent formatting.&lt;/li&gt;  &lt;li&gt;Notice the use of the CASE statement to conditionally append the length.  This could be used to handled scale/precision for FLOAT, REAL and DECIMAL data types.&lt;/li&gt;&lt;/ul&gt;


&lt;p&gt;&lt;u&gt;&lt;strong&gt;Coming next on my blog:&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;
See my next Blog post on how to &quot;Dynamically generate INSERT statements&quot; from the contents of a table.  This is like gold when creating database migration scripts and especially for transferring data between varying SQL based platforms (SQL Server, Sybase, Oracle, Informix, etc.).&lt;/p&gt;

&lt;p&gt;Now, go and impress your SQL jockey friends!&lt;/p&gt;
&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.consultantsguild.com/index.php/dynamic_t_sql_in_just_minutes?blog=6&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Ever feel left behind when one of those SQL Server jockies breezes through a complex query that generates SQL on the fly?  After all its a bit over the top to use SQL to generate SQL, isn't it?  Well, its time to level the playing field.  I'm going to pass on a simple pattern that you can use to generate the most sophisticated queries.  This pattern will lead to an endless supply of SQL/Database tools to add to your library.</p>

<p><u><strong>Problem to Solve</strong></u><br />
Write a query that generates a CREATE TABLE definition from any table.  Then write a query that generates INSERT statements to fill a copy of that table based on the current data.</p>

<p>So you are probably saying to yourself...Wouldn't just be easier to type the CREATE TABLE definition by hand?  Maybe so for the first one, but imagine doing it for an entire database of 300+ tables.  Or you may say...Couldn't I just use the T-SQL generator in Enterprise Manager (or equivalent)?  Sure, but if you want to take your skills to the next level, its time to make an investment.  Besides, does anyone else hate the excess baggage that those tools include in the generated SQL?  Me too.  So, dynamic SQL to the rescue.  </p>

<p><u><strong>Goals</strong></u><br />
I always try to make my SQL tools reusable and tight.  I could do a lot of things using brute force CURSORS or WHILE loops in SQL, but I try to avoid that.  So I'm going to give you a little gem that will aggregate the statement on-the-fly in one SQL statement.  So without further delay....</p>

<p><u><strong>Solution to the Problem</strong></u><br />
Paste the following query into a SQL Server Query Analyzer window and set the current database to Northwind.  Set the output format to Text.  Then run the query....</p>

<p><code><br />
declare @vsSQL		varchar(8000)<br />
declare @vsTableName 	varchar(50)<br />
select @vsTableName = 'Customers'<br />
<br />
select @vsSQL = 'CREATE TABLE ' + @vsTableName + char(10) + '(' + char(10)<br />
<br />
select	@vsSQL = @vsSQL + '   ' + sc.Name + ' ' + <br />
	st.Name +<br />
	case when st.Name in ('varchar','varchar','char','nchar') then '(' + cast(sc.Length as varchar) + ') ' else ' ' end + <br />
	case when sc.IsNullable = 1 then 'NULL' else 'NOT NULL' end + ',' + char(10)<br />
from	sysobjects so<br />
join 	syscolumns sc on sc.id = so.id<br />
join	systypes st on st.xusertype = sc.xusertype<br />
where	so.name = @vsTableName<br />
order by<br />
	sc.ColID<br />
<br />
select substring(@vsSQL,1,len(@vsSQL) - 2) + char(10) + ')'<br />
</code></p>

<p>The resulting output will be a auto-generated CREATE TABLE statement:</p>

<p><code>CREATE TABLE Customers<br />
(<br />
   CustomerID nchar(10) NOT NULL,<br />
   CompanyName nvarchar(80) NOT NULL,<br />
   ContactName nvarchar(60) NULL,<br />
   ContactTitle nvarchar(60) NULL,<br />
   Address nvarchar(120) NULL,<br />
   City nvarchar(30) NULL,<br />
   Region nvarchar(30) NULL,<br />
   PostalCode nvarchar(20) NULL,<br />
   Country nvarchar(30) NULL,<br />
   Phone nvarchar(48) NULL,<br />
   Fax nvarchar(48) NULL<br />
)</code></p>


<p><u><strong>Things to grok:</strong></u></p>
<ul><li>Notice the nifty main SQL statement that aggregates the SQL string variable @vsSQL on-the-fly.</li>  <li>Notice how to leverage the combination of sysobjects (for tables),  (for column Des) and systypes (for data types properties).  </li>  <li>Notice the use of char(10) to append carriage returns to the SQL for decent formatting.</li>  <li>Notice the use of the CASE statement to conditionally append the length.  This could be used to handled scale/precision for FLOAT, REAL and DECIMAL data types.</li></ul>


<p><u><strong>Coming next on my blog:</strong></u><br />
See my next Blog post on how to "Dynamically generate INSERT statements" from the contents of a table.  This is like gold when creating database migration scripts and especially for transferring data between varying SQL based platforms (SQL Server, Sybase, Oracle, Informix, etc.).</p>

<p>Now, go and impress your SQL jockey friends!</p>
<div class="item_footer"><p><small><a href="http://blogs.consultantsguild.com/index.php/dynamic_t_sql_in_just_minutes?blog=6">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.consultantsguild.com/index.php/dynamic_t_sql_in_just_minutes?blog=6#comments</comments>
			<wfw:commentRss>http://blogs.consultantsguild.com/index.php?blog=6&#38;tempskin=_rss2&#38;disp=comments&#38;p=55</wfw:commentRss>
		</item>
			</channel>
</rss>
