<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.simple-talk.com/community/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Andras</title><link>http://www.simple-talk.com/community/blogs/andras/default.aspx</link><description>Software Architect - Red Gate Software</description><dc:language>en-US</dc:language><generator>CommunityServer 2.0 (Debug Build: 60217.2664)</generator><item><title>SQL Server 2008: Table-valued parameters</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/08/27/69298.aspx</link><pubDate>Wed, 27 Aug 2008 22:10:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:69298</guid><dc:creator>András</dc:creator><slash:comments>3</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/69298.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=69298</wfw:commentRss><description>&lt;p&gt;&lt;span&gt;Table-valued types and parameters 
	are among the many exciting new features of the recently released SQL Server 
	2008. These table-valued types allow you to pass table data to stored 
	procedures and functions.&lt;/span&gt;&lt;/p&gt;
	&lt;p&gt;&lt;span&gt;But why is this useful? In previous 
	versions of SQL Server one could pass parameters to stored procedures and 
	functions. A single parameter can describe a single value. But what did you 
	do if the information you want to pass to a stored procedure is more 
	dynamic? If not all information is required for the stored procedure? For 
	example a customer order that has optional delivery time or priority 
	information? You could pass null values, but if these make the code look 
	rather unreadable. Previous solutions included optional parameters for 
	stored procedures. Parameters that had a default value need not be 
	specified. This made stored procedure calls nicer, but the parameter list of 
	stored procedures could quickly become unmanageable. The situation was 
	aggravated when new parameters were introduced.&lt;/span&gt;&lt;/p&gt;

	&lt;p&gt;&lt;span&gt;Furthermore, this solution could not 
	handle a different type of dynamic information, for example a customer order 
	that contains multiple items. People started to use dirty hacks to 
	circumvent this restriction, and used comma separated lists, and later XML. 
	However, a database management system is certainly not ideal for processing 
	strings or XML, especially when using T-SQL. &lt;/span&gt;&lt;/p&gt;
	&lt;p&gt;&lt;span&gt;Another alternative was using a 
	communication table that was either fixed or created on demand. This 
	solution suffered too, because when the communication table was permanent, 
	it needed regular clean up, concurrency needed to be handled manually, and 
	with temporary tables there could be recompilation issues. &lt;/span&gt;&lt;/p&gt;
	&lt;p&gt;&lt;span&gt;Using communication tables was also 
	not ideal from the point of view of roundtrips or code simplicity between 
	the applications and the database. Multiple insert statements needed to be 
	executed just to set up the stored procedure call, all of this put into a 
	single transaction, etc.&lt;/span&gt;&lt;/p&gt;
	
	&lt;p&gt;&lt;span&gt;Well, this is hopefully the past, 
	welcome the new table-valued types and parameters. So let’s see an example.&lt;/span&gt;&lt;/p&gt;
	&lt;p&gt;&lt;span&gt;In order to use table-valued 
	parameters one needs to set up a table type. This looks like the crossbreed 
	of a user defined type and a table definition:&lt;/span&gt;&lt;/p&gt;
	
		&lt;blockquote&gt;

			&lt;p&gt;&lt;font face="Courier New" size="2"&gt;&lt;font color="blue"&gt;CREATE&lt;/font&gt;&lt;font&gt;
			&lt;font color="blue"&gt;TYPE&lt;/font&gt; myTableType &lt;font color="blue"&gt;AS&lt;/font&gt;
			&lt;font color="blue"&gt;TABLE&lt;/font&gt;&lt;/font&gt; &lt;br&gt;&lt;font color="blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
			&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt; &lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; id
			&lt;font color="blue"&gt;INT&lt;/font&gt; &lt;font color="gray"&gt;NOT&lt;/font&gt;

			&lt;font color="gray"&gt;NULL&lt;/font&gt;&lt;/font&gt; &lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
			&lt;font color="blue"&gt;PRIMARY&lt;/font&gt; &lt;font color="blue"&gt;KEY&lt;/font&gt;&lt;font color="gray"&gt;,&lt;/font&gt;&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
data &lt;font color="blue"&gt;NVARCHAR&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;100&lt;font color="gray"&gt;)&lt;/font&gt;&lt;/font&gt;

			&lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="gray"&gt;)&lt;/font&gt;&lt;/font&gt;
			&lt;/font&gt;&lt;/p&gt;
		&lt;/blockquote&gt;
&lt;p&gt;&lt;span&gt;Note that you can specify a primary key, 
constraints, computed columns, etc. This gives you a lot of flexibility, and 
this extra control will help you to optimize performance and ensure data 
integrity.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Once you have set up a table type, you 
can use it as a stored procedure or function parameter. In the following example 
we just select the information inside the table that is passed in as a 
parameter:&lt;/span&gt;&lt;/p&gt;
		&lt;blockquote&gt;
			&lt;p&gt;&lt;font face="Courier New" size="2"&gt;&lt;font color="blue"&gt;CREATE&lt;/font&gt;&lt;font&gt;

			&lt;font color="blue"&gt;PROCEDURE&lt;/font&gt; myProcedure&lt;/font&gt; &lt;br&gt;
			&lt;font color="blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font&gt; 
@TableVariable myTableType &lt;font color="blue"&gt;READONLY&lt;/font&gt; &lt;font color="gray"&gt;)&lt;/font&gt;&lt;/font&gt;
			&lt;br&gt;&lt;font color="blue"&gt;AS&lt;/font&gt;&lt;font&gt; &lt;/font&gt;&lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;

			&lt;font color="blue"&gt;BEGIN&lt;/font&gt;&lt;/font&gt; &lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
			&lt;font color="blue"&gt;SELECT&lt;/font&gt;&amp;nbsp; &lt;font color="gray"&gt;*&lt;/font&gt;&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
			&lt;font color="blue"&gt;FROM&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @TableVariable&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;

&lt;font color="blue"&gt;END&lt;/font&gt;&lt;/font&gt; &lt;br&gt;&lt;font color="blue"&gt;GO&lt;/font&gt; &lt;/font&gt;
			&lt;/p&gt;
		&lt;/blockquote&gt;
&lt;p&gt;&lt;span&gt;As the above example shows, you can 
query the table parameter as if it were an ordinary table variable. However, you 
cannot modify the table parameter, and this is spelled out explicitly by the 
mandatory “READONLY” word after the parameter specification.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;To see how the above works in T-SQL we 
can declare a table variable using our new table type, insert data into this 
table variable (and I also use the new row constructor in SQL Server 2008 to 
insert multiple rows in a single statement), and call the stored procedure with 
the table variable as its parameter:&lt;/span&gt;&lt;/p&gt;
		&lt;blockquote&gt;
			&lt;p&gt;&lt;font face="Courier New" size="2"&gt;&lt;font color="blue"&gt;DECLARE&lt;/font&gt;&lt;font&gt; 

@table myTableType &lt;/font&gt;&lt;br&gt;&lt;font color="blue"&gt;INSERT&lt;/font&gt;&lt;font&gt;&amp;nbsp;
			&lt;font color="blue"&gt;INTO&lt;/font&gt; @table&lt;/font&gt; &lt;br&gt;&lt;font color="blue"&gt;VALUES&amp;nbsp; 
			&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font&gt; 
1&lt;font color="gray"&gt;,&lt;/font&gt; &lt;font color="red"&gt;'a'&lt;/font&gt; &lt;font color="gray"&gt;),&lt;/font&gt;&lt;/font&gt;

			&lt;br&gt;&lt;font color="blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
			&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font&gt; 
2&lt;font color="gray"&gt;,&lt;/font&gt; &lt;font color="red"&gt;'b'&lt;/font&gt; &lt;font color="gray"&gt;),&lt;/font&gt;&lt;/font&gt;
			&lt;br&gt;&lt;font color="blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
			&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font&gt; 
3&lt;font color="gray"&gt;,&lt;/font&gt; &lt;font color="red"&gt;'c'&lt;/font&gt; &lt;font color="gray"&gt;)&lt;/font&gt;&lt;/font&gt;

			&lt;br&gt;&lt;font color="blue"&gt;EXEC&lt;/font&gt;&lt;font&gt; 
dbo&lt;font color="gray"&gt;.&lt;/font&gt;myProcedure&lt;font color="blue"&gt; &lt;/font&gt;@table&lt;/font&gt;
			&lt;/font&gt;&lt;/p&gt;
		&lt;/blockquote&gt;
&lt;p&gt;
&lt;span&gt;After executing the above we get a resultset like:&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/p&gt;

		&lt;blockquote&gt;
			&lt;p&gt;
			&lt;span&gt;&lt;font size="2"&gt;id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
data&lt;br&gt;----------- ----------------&lt;br&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

			&lt;p&gt;
			&lt;span&gt;(3 row(s) affected)&lt;/span&gt;&lt;/p&gt;
		&lt;/blockquote&gt;
&lt;p&gt;&lt;span&gt;The above may simplify the work of 
people writing stored procedures and functions, but what about developers. Well, 
the above works just as well with ADO.Net. When creating a SQLCommand object for 
a stored procedure, one can now pass in a DataTable object as a parameter, 
exactly as it is done in the following C# code segment:&lt;/span&gt;&lt;/p&gt;
		&lt;blockquote&gt;
			&lt;font face="Courier New" size="2"&gt;&lt;font color="#2B91AF"&gt;SqlConnection&lt;/font&gt;&lt;font&gt; 
connection = &lt;font color="blue"&gt;new&lt;/font&gt; &lt;font color="#2B91AF"&gt;SqlConnection&lt;/font&gt;(&lt;font color="#A31515"&gt;&amp;quot;server = ...&amp;quot;&lt;/font&gt;);&lt;/font&gt;

			&lt;br&gt;&lt;font&gt;&amp;nbsp;&lt;/font&gt; &lt;br&gt;&lt;font color="#2B91AF"&gt;SqlCommand&lt;/font&gt;&lt;font&gt; 
command = connection.CreateCommand();&lt;/font&gt; &lt;br&gt;&lt;font&gt;command.CommandText =
			&lt;font color="#A31515"&gt;&amp;quot;dbo.myProcedure&amp;quot;&lt;/font&gt;;&lt;/font&gt; &lt;br&gt;
			&lt;font&gt;command.CommandType = &lt;font color="#2B91AF"&gt;CommandType&lt;/font&gt;.StoredProcedure;&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;&amp;nbsp;&lt;/font&gt; &lt;br&gt;&lt;font color="green"&gt;// declare a table to store the parameter values&lt;/font&gt;

			&lt;br&gt;&lt;font color="#2B91AF"&gt;DataTable&lt;/font&gt;&lt;font&gt; 
paramTable = &lt;font color="blue"&gt;new&lt;/font&gt; &lt;font color="#2B91AF"&gt;DataTable&lt;/font&gt;();&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;paramTable.Columns.Add(&lt;font color="#A31515"&gt;&amp;quot;id&amp;quot;&lt;/font&gt;,
			&lt;font color="blue"&gt;typeof&lt;/font&gt;(&lt;font color="blue"&gt;int&lt;/font&gt;));&lt;/font&gt;

			&lt;br&gt;&lt;font&gt;paramTable.Columns.Add(&lt;font color="#A31515"&gt;&amp;quot;data&amp;quot;&lt;/font&gt;,
			&lt;font color="blue"&gt;typeof&lt;/font&gt;(&lt;font color="blue"&gt;string&lt;/font&gt;));&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;&amp;nbsp;&lt;/font&gt; &lt;br&gt;&lt;font color="green"&gt;// add the table as a parameter to the stored procedure&lt;/font&gt;
			&lt;br&gt;&lt;font color="#2B91AF"&gt;SqlParameter&lt;/font&gt;&lt;font&gt; 
sqlParam = command.Parameters.AddWithValue(&lt;font color="#A31515"&gt;&amp;quot;@TableVariable&amp;quot;&lt;/font&gt;, 
paramTable);&lt;/font&gt; &lt;br&gt;&lt;font&gt;sqlParam.SqlDbType = &lt;font color="#2B91AF"&gt;SqlDbType&lt;/font&gt;.Structured;&lt;/font&gt;

			&lt;br&gt;&lt;font&gt;sqlParam.TypeName = &lt;font color="#A31515"&gt;&amp;quot;dbo.myTableType&amp;quot;&lt;/font&gt;;&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;&amp;nbsp;&lt;/font&gt; &lt;br&gt;&lt;font color="green"&gt;// add rows to the table parameter&lt;/font&gt;
			&lt;br&gt;&lt;font&gt;paramTable.Rows.Add(&lt;font color="blue"&gt;new&lt;/font&gt;
			&lt;font color="blue"&gt;object&lt;/font&gt;[] {1, &lt;font color="#A31515"&gt;&amp;quot;a&amp;quot;&lt;/font&gt;});&lt;/font&gt;

			&lt;br&gt;&lt;font&gt;paramTable.Rows.Add(&lt;font color="blue"&gt;new&lt;/font&gt;
			&lt;font color="blue"&gt;object&lt;/font&gt;[] {2, &lt;font color="#A31515"&gt;&amp;quot;b&amp;quot;&lt;/font&gt; });&lt;/font&gt;
			&lt;/font&gt;
		&lt;/blockquote&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;Note that there are no insert 
statements; we can just use a DataTable to pass in table parameters to the 
stored procedure. Hopefully this solution in SQL Server 2008 will get rid of all 
the now unnecessary “hacks” that used XML, comma separated lists and temporary 
tables used in a large number of database applications.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&amp;nbsp;If you want to hear more about what is 
new in SQL Server 2008, and you are in the UK or Poland on the following dates, 
do come to my presentations or talk to me later. For the first half of September 
my schedule looks like the following:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;September 2&lt;sup&gt;nd&lt;/sup&gt; 2008:
&lt;a href="http://www.nxtgenug.net/ViewEvent.aspx?EventID=161"&gt;
SQL Server and the Sequel&lt;/a&gt; , NxtGenUG in Cambridge, UK&lt;/span&gt;
&lt;/li&gt;&lt;li&gt;&lt;span&gt;September 6&lt;sup&gt;th&lt;/sup&gt; 2008:
&lt;a href="http://zine.net.pl/blogs/sqlgeek/archive/2008/07/25/pl-andr-s-belokosztolszki-na-zineday-2008.aspx"&gt;

Managing change in the database world&lt;/a&gt; at
&lt;a href="http://zine.net.pl/blogs/zineday/archive/2008/08/25/zineday200825augustinfo.aspx"&gt;
ZineDay&lt;/a&gt; in Warsaw, Poland&lt;/span&gt;
&lt;/li&gt;&lt;li&gt;&lt;span&gt;September 13&lt;sup&gt;th&lt;/sup&gt; 2008:
	&lt;a href="http://www.sqlbits.com/information/MainAgenda.aspx"&gt;
	Advanced T-SQL (2005 and 2008)&lt;/a&gt; at
	&lt;a href="http://www.sqlbits.com/"&gt;

	SQL Bits 3&lt;/a&gt; in Hatfield, UK&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=69298" width="1" height="1"&gt;</description></item><item><title>The unexpected behaviour of DirectoryInfo.GetFiles() with three letter extensions</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/08/01/65554.aspx</link><pubDate>Fri, 01 Aug 2008 16:02:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:65554</guid><dc:creator>András</dc:creator><slash:comments>1</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/65554.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=65554</wfw:commentRss><description>There is a documented, but certainly counterintuitive issue with the DirectoryInfo.GetFiles() method in .Net. This method returns a list of files that match a particular pattern. For example in the following example it will return us all the files on drive Z: that have the exact extension “.foobar”&lt;br&gt;&lt;br&gt;&lt;br&gt;DirectoryInfo folder = new DirectoryInfo(@"z:");&lt;br&gt;&lt;br&gt;FileInfo[] files = folder.GetFiles("*.foobar",&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SearchOption.AllDirectories);&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;However, the DirectoryInfo.GetFiles method behaves very differently when you use it with an extension that contains exactly three characters.&amp;nbsp; For example consider the following example:&lt;br&gt;&lt;br&gt;&lt;br&gt;FileInfo[] files = folder.GetFiles("*.sql", SearchOption.AllDirectories);&lt;br&gt;&lt;br&gt;&lt;br&gt;This will, as expected, return all the files with the extension “.sql”. However, it will also return all the files that have the extension “.sql-backup”, “sqlold”, “sql~”, etc.&amp;nbsp; Surprisingly this is the behaviour that is documented in Visual Studio’s documentation. A quote from that documentation (&lt;a href="http://msdn.microsoft.com/en-us/library/ms143327.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms143327.aspx&lt;/a&gt;):&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span&gt;“The matching behavior of searchPattern when the extension is exactly three characters long is different from when the extension is more than three characters long. A searchPattern of exactly three characters returns files having an extension of three or more characters. A searchPattern of one, two, or more than three characters returns only files having extensions of exactly that length.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span&gt;…&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span&gt;The following list shows the behavior of different lengths for the searchPattern parameter: &lt;/span&gt;&lt;br&gt;&lt;span&gt;•&amp;nbsp;&amp;nbsp; &amp;nbsp;"*.abc" returns files having an extension of.abc,.abcd,.abcde,.abcdef, and so on.&lt;/span&gt;&lt;br&gt;&lt;span&gt;•&amp;nbsp;&amp;nbsp; &amp;nbsp;"*.abcd" returns only files having an extension of.abcd.&lt;/span&gt;&lt;br&gt;&lt;span&gt;•&amp;nbsp;&amp;nbsp; &amp;nbsp;"*.abcde" returns only files having an extension of.abcde.&lt;/span&gt;&lt;br&gt;&lt;span&gt;•&amp;nbsp;&amp;nbsp; &amp;nbsp;"*.abcdef" returns only files having an extension of.abcdef.&lt;/span&gt;&lt;br&gt;&lt;span&gt;”&lt;/span&gt;&lt;br&gt;&lt;br&gt;The reason for the above strange behaviour is the support for the 8.3 file name format. A file with the name “alongfilename.longextension” has an equivalent 8.3 filename of “along~1.lon”. If we filter the extensions “.lon”, then the above 8.3 filename will be a match.&lt;br&gt;&lt;br&gt;&lt;br&gt;This behaviour has bitten me with a tool I’ve been working on. This tool reads “.sql” files and builds up a database schema from these files. This schema can then be compared with live database schemata. The primary motivation for such a tool is to support database schemata in source control. However, there were two different scenarios when the application started to fail. In one case I used emacs to edit a file, and it left me (as expected) a backup file postfixed with a ~ character. On another occasion, I used a source control system that decided to store caching information in the same folder where the sql scripts were located, and the cached files had an extension that started with sql and were followed by a timestamp. In both of these cases the database schema that built by my application was inconsistent, due to objects being duplicated.&lt;br&gt;&lt;br&gt;&lt;br&gt;The only solution to the strange behaviour of the DirectoryInfo.GetFiles() seems to be to check the extension of the file explicitly if you use an extension with exactly three characters. The FileInfo.Extension property returns the full extension of the file, not only the first three characters.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=65554" width="1" height="1"&gt;</description></item><item><title>SQL Server 2008: new data types and .Net 2 with and without SP1</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/06/20/60191.aspx</link><pubDate>Fri, 20 Jun 2008 18:05:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:60191</guid><dc:creator>András</dc:creator><slash:comments>4</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/60191.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=60191</wfw:commentRss><description>SQL Server 2008 has introduced a few new data types, among others the new date types, like date, time, datatime2 and datetimespan. Because .Net 2 was released before SQL Server 2008 has introduced these data types, there are no classes that map to these new types in .Net 2. &lt;br&gt;&lt;br&gt;But this has changed with .Net 2 SP1, which introduces the DateTimeOffset structure.&lt;br&gt;&lt;br&gt;So, what should we expect when we run an application without SP1?&lt;br&gt;When we connect to SQL Server 2008 using .Net 2, the version of the runtime of the connecting application will determine the .Net data type that is returned to the user. For example, for a SQL datetimespan column without&amp;nbsp; .Net SP1 we get back a string, with SP1 we get a DateTimeOffset. Note that this happens even if you compile your application on a machine with SP1. So even though you have compiled and tested your application on .Net 2 SP1, a customer who runs the client without SP1 may experience a different behaviour. So what are these differences:&lt;br&gt;&lt;br&gt;We will use a simple table that contains the new date data types:&lt;br&gt;&lt;br&gt;CREATE TABLE someProblematicTypes&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c_date date&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , c_time time&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , c_datatime2 datetime2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , c_datetimeoffset datetimeoffset&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&lt;br&gt;Insert a single row:&lt;br&gt;&lt;br&gt;INSERT&amp;nbsp; INTO someProblematicTypes&lt;br&gt;VALUES&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GETDATE()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , GETDATE()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , GETDATE()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , GETDATE() )&lt;br&gt;&lt;br&gt;Then we create a C# application that uses an SqlDataReader&amp;nbsp; to retrieve the information about the data stored in this table. We compile this on a machine with .Net2 SP1, and run it on two machines, one with .Net 2 SP1 and one without. The instance of the SqlDataReader returns an object for the various columns, and the values and their types for the above table are:&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span&gt;Without SP1:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Column c_date&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:2008-06-20&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.String&lt;br&gt;Column c_time&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:2008-06-20&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.String&lt;br&gt;Column c_datatime2&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:2008-06-20 12:11:28.6000000&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.String&lt;br&gt;Column c_datetimeoffset&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:2008-06-20 12:11:28.6000000 +00:00&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.String&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span&gt;With SP1:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Column c_date&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:20/06/2008 00:00:00&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.DateTime&lt;br&gt;Column c_time&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:20/06/2008 00:00:00&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.DateTime&lt;br&gt;Column c_datatime2&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:20/06/2008 12:11:28&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.DateTime&lt;br&gt;Column c_datetimeoffset&lt;br&gt;&amp;nbsp;&amp;nbsp; Value:20/06/2008 12:11:28 +00:00&lt;br&gt;&amp;nbsp;&amp;nbsp; Type :System.DateTimeOffset&lt;br&gt;&lt;br&gt;&lt;br&gt;That the results are different, and let's not forget that it is the same executable that is being run. Without .Net2 SP1 we are getting strings instead of DateTime and the new DateTimeOffset. This could upset the application, and if our application was expecting a DateTime type, and got a string, we could easily get an invalid cast exception. &lt;br&gt;&lt;br&gt;Also, we must be careful when we use the new DateTimeOffset type in our code. The application that is compiled and tested on a machine with SP1 will by default start on a client machine that does not have .Net 2 SP1. However, when it gets to the new data type, it will throw an unknown type exception. Unfortunately, since .Net 2 SP1 is relatively new (released November 2007), many have not upgraded to it. There are two general solutions to this. Either force the your customers to upgrade to .Net 2 SP1, or your application must be prepared for the above type differences and must be tested both with and without .Net 2 SP1.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=60191" width="1" height="1"&gt;</description></item><item><title>SQL Server 2008: New languages and older operating systems</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/04/21/48058.aspx</link><pubDate>Mon, 21 Apr 2008 16:36:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:48058</guid><dc:creator>András</dc:creator><slash:comments>2</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/48058.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=48058</wfw:commentRss><description>
&lt;p class="MsoNormal"&gt;SQL Server 2008 introduces a few new languages like Welsh, Tibetan
and Norwegian. While these new languages map to the codepages in Windows Server
2008, in earlier operating systems (like XP) this is not so, and simple queries
like “select * from mytable” can break with the SQL error 4078.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;The problem occurs if you use a collation that uses one of
the new languages in a char, varchar or text column. In queries that return
such a non-unicode column SQL Server relies on the client to use the
appropriate codepage when displaying or converting the returned characters to Unicode.
If the codepage does not exist on the client side, the query will fail. For
example, in the following we declare a table variable with a varchar column
that uses the new FRISIAN_100_CS_AS collation.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;DECLARE @t TABLE (&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;id INT PRIMARY
KEY IDENTITY(1, 1),&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;data
VARCHAR(100) COLLATE FRISIAN _100_CS_AS)&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;INSERT&lt;span&gt;&amp;nbsp; &lt;/span&gt;INTO @t
VALUES&lt;span&gt;&amp;nbsp; &lt;/span&gt;( N'aaa' )&lt;/p&gt;

&lt;p class="MsoNormal"&gt;SELECT data FROM @t&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;The above statement will work fine on the computer on which
SQL Server 2008 is installed. If you execute it in Query Analyzer on a computer
with Windows XP, then you will get the following error:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Server: Msg 4078, Level 16, State 1, Line 13&lt;/p&gt;

&lt;p class="MsoNormal"&gt;The statement failed because column 'data' (ID=0) uses
collation Welsh_100_CS_AS, which is not recognized by older client drivers. Try
upgrading the client operating system or applying a service update to the database
client software, or use a different collation. See SQL Server Books Online for
more information on changing collations.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;(If it was run from a .Net application, the SqlException exception
message is: “The Collation specified by SQL Server is not supported.”)&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;(I use Query Analyzer only because with CTP6 of SQL Server
2008 you cannot use Management Studio 2005. However, you can use osql, sqlcmd,
Query Analyzer, your own applications, etc.)&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;The same problem occurs with .Net applications. Whether an
application that executes the above query will actually work will depend on what
operating system it is executed on. &lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;A reasonably simple workaround is not to use select *, and
when querying columns that are based on the char, varchar, or text, cast them
to nchar, nvarchar or ntext. In this case the data will be returned in Unicode (actually
UCS-2), and the query will work on pre Windows Server 2008 systems. In a .Net application you would also need to collate the result to a known collation, like latin1_general.&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;The new languages in SQL Server 2008 that seem to be
affected are: &lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span&gt;Chinese_Traditional_Stroke_Count&lt;span&gt;,&lt;/span&gt; Chinese_Traditional_Bopomofo&lt;span&gt;,&lt;/span&gt; Chinese_Simplified_Pinyin&lt;span&gt;,&lt;/span&gt;
Chinese_Simplified_Stroke_Order&lt;span&gt;,&lt;/span&gt;
Chinese_Traditional_Pinyin&lt;span&gt;,&lt;/span&gt;
Chinese_Traditional_Stroke_Order&lt;span&gt;,&lt;/span&gt;
Danish_Greenlandic&lt;span&gt;,&lt;/span&gt; Japanese_XJIS&lt;span&gt;,&lt;/span&gt; Japanese_Bushu_Kakusu&lt;span&gt;,&lt;/span&gt;
Norwegian&lt;span&gt;,&lt;/span&gt; Romansh&lt;span&gt;,&lt;/span&gt;
Serbian_Latin&lt;span&gt;,&lt;/span&gt; Serbian_Cyrillic&lt;span&gt;,&lt;/span&gt; Bosnian_Latin&lt;span&gt;,&lt;/span&gt;
Bosnian_Cyrillic&lt;span&gt;,&lt;/span&gt; Urdu&lt;span&gt;,&lt;/span&gt;
Persian&lt;span&gt;,&lt;/span&gt; Mapudungan&lt;span&gt;,&lt;/span&gt;
Upper_Sorbian&lt;span&gt;,&lt;/span&gt; Bashkir&lt;span&gt;,&lt;/span&gt;
Maltese&lt;span&gt;,&lt;/span&gt; Sami_Norway&lt;span&gt;,&lt;/span&gt;
Sami_Sweden_Finland&lt;span&gt;,&lt;/span&gt; Turkmen&lt;span&gt;,&lt;/span&gt; Bengali&lt;span&gt;,&lt;/span&gt; Assamese&lt;span&gt;,&lt;/span&gt; Pashto&lt;span&gt;,&lt;/span&gt; Tibetan&lt;span&gt;,&lt;/span&gt; Welsh&lt;span&gt;,&lt;/span&gt; Khmer&lt;span&gt;,&lt;/span&gt; Lao&lt;span&gt;,&lt;/span&gt; Frisian&lt;span&gt;,&lt;/span&gt; Tamazight&lt;span&gt;,&lt;/span&gt; Nepali&lt;span&gt;,&lt;/span&gt; Azeri_Latin&lt;span&gt;,&lt;/span&gt;
Azeri_Cyrillic&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=48058" width="1" height="1"&gt;</description></item><item><title>SQL Compare 7 Beta and peeking into SQL Server backup files</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/03/28/45803.aspx</link><pubDate>Fri, 28 Mar 2008 15:51:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:45803</guid><dc:creator>András</dc:creator><slash:comments>2</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/45803.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=45803</wfw:commentRss><description>

&lt;p class="MsoNormal"&gt;I want to restore only a single table from my database
backup. We have been hearing this request from many of our SQL Backup
customers. The problem is simple: Given a large database backup and a live
database that has a partial “corruption”, e.g. the data in a single table has
been accidentally modified and committed, the DBA would like to have the table,
and nothing else, restored. Or, another example is when a particular stored
procedure has been modified, and we would like to get back the original
version. This problem is a bit worse if we do not even know which backup file
contains the right information.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;In SQL Server the only way to solve the above problem is to
restore the whole backup file to a new database, and copy the table data or the
stored procedure to the current database.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Well, this problem is now history. We have just released the
first public beta of SQL Compare 7. This tool, which is primarily used for
comparing and synchronizing two database schemata, can now read the schema
information directly from a backup file. This complements well SQL Data Compare
6.1 which already has this feature at the data level. These two products open
up a lot of new recovery opportunities. &lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;If you want to restore a few stored procedures, you just
compare your live database with a backup file, and you can explore the
differences in your schema objects. It may be that the modified stored procedure
has a few dependent stored procedures that you also wish to restore. After
selecting all the schema objects you wish to retrieve from the backup files,
you can either restore them or create and save a synchronization script. When
it comes to tables, Data Compare can do even more. Not only can you restore the
data in a particular table, you can do this at a much finer level of
granularity. First, you can see the differences between a table in the backup
and the live database, and you can control which individual rows should be
restored. &lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Anyway, back to SQL Compare 7 Beta 1. You can download it
from &lt;a href="http://www.red-gate.com/messageboard/viewtopic.php?t=6730"&gt;http://www.red-gate.com/messageboard/viewtopic.php?t=6730&lt;/a&gt;
&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;It was quite a challenge to implement reading schemata
information from backup files. First, the core system tables are different in
SQL Server 2000, 2005 and 2008. Some objects, like XML schema collections, have
very cryptic representations, and there is of course backup compression in SQL
Server 2008. We are still working on row and page compressions. Of course we support
Red Gate’s SQL Backup files, both compressed and encrypted ones, but the tool
works with SQL Server’s native backups just as well.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Another major feature for this beta is support for SQL
Server 2008. Although we will not see SQL Server 2008 RTMed until at least Q3
2008, when it is out, we hope to have SQL Compare 7 ready and waiting for it. In
the meantime, you are encouraged to download and try this beta. Please let us
know if you find any issues with it, or if you think that there is something we
have missed from this product. The forum for this beta is on &lt;a href="http://www.red-gate.com/messageboard/viewforum.php?f=78"&gt;http://www.red-gate.com/messageboard/viewforum.php?f=78&lt;/a&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Regards,&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;Andras&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=45803" width="1" height="1"&gt;</description></item><item><title>SQL Server 2008 CTP6 takes a day off</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/02/29/44726.aspx</link><pubDate>Fri, 29 Feb 2008 22:55:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:44726</guid><dc:creator>András</dc:creator><slash:comments>1</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/44726.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=44726</wfw:commentRss><description>

&lt;p class="MsoNormal"&gt;SQL Server 2008 CTP6 does not work on February 29&lt;sup&gt;th&lt;/sup&gt;.
Period.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;On one hand, it is really nice that Microsoft is releasing
Community Technology Previews for its latest SQL Server. It helps developers
and DBAs to test their solutions and get familiar with the next version of SQL
Server. On the other hand, since Microsoft still has many months before the
final release, there are many bugs in these CTPs. This is certainly expected,
this is the point of these CTPs. But there was one bug that nearly killed me.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;As a last minute preparation for tomorrow’s SQL Bits event
in Birmingham, I decided to check that my demo scripts work properly. I tried
to connect to my SQL Server instance on my laptop, and was greeted with an
unpleasant error message. Initially I was not worried, after a few minutes of
fluffing around I started to blame the screen capturing application I’ve been
asked to install for the event. After some more headache, I though, it was not
worth the time, so I installed SQL Server 2008 CTP6 on a second laptop.
Surprise! The installation has failed too. Same happened when I tried to
install it on a virtual server, etc. So now, after three hours wasted, I’ve
found a relevant bug report &lt;a href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=330614" target="_"&gt;https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=330614&lt;/a&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Apparently, SQL Server 2008 CTP6 does not work on 29 February.
It is ironic that this is just two days after the launch of the product (the
launch has nothing to do with the release).&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Changing the system time to 1 March has temporarily resolved
this issue :), but the bald patch on my head has grown today.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=44726" width="1" height="1"&gt;</description></item><item><title>Type less in SQL Server 2008 (variable initialization and multiple row inserts)</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/02/28/44645.aspx</link><pubDate>Thu, 28 Feb 2008 15:34:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:44645</guid><dc:creator>András</dc:creator><slash:comments>1</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/44645.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=44645</wfw:commentRss><description>

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Among the large number of new features in SQL Server 2008
there are two, almost insignificant features, that I use almost constantly.
These are variable initialization and the values clause of insert statements that
now accept multiple rows.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;When playing with SQL one inevitably declares some variables.
After the declaration, and as per the SQL standard, we can use the SET
statement to assign a value to a variable:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;DECLARE @a int, @b int&lt;/p&gt;

&lt;p class="MsoNormal"&gt;SET @a = 1&lt;/p&gt;

&lt;p class="MsoNormal"&gt;SET @b = 2&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;If we do not stick to the standard, then we can use a SELECT
statement to assign values to several variables in a single statement:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;SELECT @a = 1, @b =2&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Sometimes, using SELECT is indeed our only choice, e.g. when
we want to get both the row count and the error code from the last statement.
There is no SET alternative to the following statement:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;SELECT @RowCount = @@ROWCOUNT, @ErrCode = @@ERROR&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Anyway, SQL Server 2008 allows us to declare and initialize
variables in a single statement, like:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;DECLARE @a int = 1, @b int = 2&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;While I still do not understand why saving on the number of
lines of code on my screen makes me feel better (two 19’’ screens provide me
with plenty of space &lt;span&gt;&lt;span&gt;:) &lt;/span&gt;&lt;/span&gt;),
somehow I like this feature.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Another small extension to T-SQL that prevents me from including
more typos is adding multiple rows in an insert statement:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;DECLARE @table TABLE ( a INT, b INT )&lt;/p&gt;

&lt;p class="MsoNormal"&gt;INSERT INTO @table VALUES (1,1), (2,2), (3,3)&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;The INSERT statement here inserts three rows into the
@table. This is something I got used to before, and was missing from SQL
Server.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;It is nice to see that in SQL Server 2008 Microsoft is adding
such syntactic sugar in addition to the number of other improvements, like
spatial data types, data compression, transparent data encryption, etc. I’ve
been talking about these improvements at VBUG and NxtGen events during the last
few weeks, so in my blog I’d also like to say thanks to the people who attended
and organized these events.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=44645" width="1" height="1"&gt;</description></item><item><title>Can I redeclare a variable in T-SQL? Teaser for SQL Bits</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2008/02/15/44040.aspx</link><pubDate>Fri, 15 Feb 2008 19:17:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:44040</guid><dc:creator>András</dc:creator><slash:comments>2</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/44040.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=44040</wfw:commentRss><description>

&lt;p class="MsoNormal"&gt;Variables in T-SQL behave differently from what people may be
used to in languages like C or C#. The scope of a variable is the batch in
which it is declared. This may not be intuitive to people who are used to local
variables. So let’s look at an interesting example:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;DECLARE&lt;/span&gt;&lt;span&gt; @counter &lt;span&gt;INT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; @counter &lt;span&gt;=&lt;/span&gt;
0&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;WHILE&lt;/span&gt;&lt;span&gt; @counter &lt;span&gt;&amp;lt;&lt;/span&gt;
100&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;DECLARE&lt;/span&gt; @value &lt;span&gt;INT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;SET&lt;/span&gt; @value &lt;span&gt;=&lt;/span&gt; &lt;span&gt;ISNULL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;@value&lt;span&gt;,&lt;/span&gt; 0&lt;span&gt;)&lt;/span&gt; &lt;span&gt;+&lt;/span&gt; 5&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;SET&lt;/span&gt; @counter &lt;span&gt;=&lt;/span&gt;
@counter &lt;span&gt;+&lt;/span&gt; 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;END&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;
&lt;/span&gt;@value&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;In this example we have a simple loop. The loop counter is a
variable @counter. What is interesting that inside the loop we have a variable
declaraion for @variable. We assign it a value (if it was null we set it to 5,
if it was not null, we increment it by 5). Does this make sense? How could I
ever consider the previous value if I’ve just declared the variable? What is
unusual for many developers, is that the declaration is evaluated only once.
This means that in the second iteration of the loop the @value variable is
already declared and set, so we are incrementing it by five in every subsequent
iteration. &lt;/p&gt;

&lt;p class="MsoNormal"&gt;At the end of the loop we can access the @value variable (do
not forget that the scope is the whole batch), and the value will be 500 (100
iterations, 100 times adding 5).&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Variable declarations are evaluated at the time of parsing,
and the scope is the whole batch. Because of this, you cannot have two declare statements
for the same variable in a batch, even if the only one declaration is reachable
in the code. For example, the following statement will result in a parsing
error:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;IF&lt;/span&gt;&lt;span&gt; 1 &lt;span&gt;=&lt;/span&gt; 1 &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;DECLARE&lt;/span&gt; @a &lt;span&gt;INT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;ELSE&lt;/span&gt;&lt;span&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;DECLARE&lt;/span&gt; @a &lt;span&gt;INT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;The error is:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;Msg 134, Level 15, State 1, Line 4&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;The variable name '@a' has already been declared. Variable
names must be unique within a query batch or stored procedure.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;If you would like to know more about how transient data,
like the above variable, is handled in SQL Server, come to my session at &lt;a href="http://www.sqlbits.com/default.aspx"&gt;SQL
Bits&lt;/a&gt; in Birmingham (UK) on 1 March, 2008. Like the previous SQL Bits event it
is free. The last one was held in Reading half a year ago, and with 20 sessions
and over 300 people attending it, it provides a unique opportunity to learn
about SQL Server, as well as to meet your fellow DBAs and SQL developers in the
UK. I will talk about transient data in SQL Server, and you can learn about
what is stored in tempdb, how the tempdb can be a performance bottleneck, what the
differences between temporary tables and table variables are, what is stored in
the transaction log file and how its can size be kept under control.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=44040" width="1" height="1"&gt;</description></item><item><title>Some interesting, obscure (and absolutely useless) T-SQL syntax</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/11/28/40245.aspx</link><pubDate>Wed, 28 Nov 2007 16:05:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:40245</guid><dc:creator>András</dc:creator><slash:comments>3</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/40245.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=40245</wfw:commentRss><description>/*&lt;br&gt;Writing ugly SQL Statements is an art. Today I've spent&lt;br&gt;a few minutes trying to break our parser as well as giving &lt;br&gt;a grill to SQL Server's parser.&lt;br&gt;So here is some extra syntax that is not behaving as &lt;br&gt;I'd expect it to behave. &lt;br&gt;*/&lt;br&gt;&lt;br&gt;select 1.a&lt;br&gt;&lt;br&gt;-- Yes, this is legal, surprise surprise it returns a &lt;br&gt;-- table with a single column, a single row, the value&lt;br&gt;-- is 1, the column name is "a" !&lt;br&gt;&lt;br&gt;-- So let's push it a bit further:&lt;br&gt;&lt;br&gt;select -1.a&lt;br&gt;&lt;br&gt;/*&lt;br&gt;Works, the result is:&lt;br&gt;a&lt;br&gt;---------------------------------------&lt;br&gt;-1&lt;br&gt;*/&lt;br&gt;&lt;br&gt;select -1/2.[-1/2]&lt;br&gt;&lt;br&gt;/*&lt;br&gt;Wow, this works too, and it gives me &lt;br&gt;-1/2&lt;br&gt;---------------------------------------&lt;br&gt;-0.500000&lt;br&gt;&lt;br&gt;So can I just put anything after the ?decimal? point?&lt;br&gt;*/&lt;br&gt;&lt;br&gt;select 1.SomeString&lt;br&gt;&lt;br&gt;/*&lt;br&gt;SomeString&lt;br&gt;---------------------------------------&lt;br&gt;1&lt;br&gt;*/&lt;br&gt;&lt;br&gt;&lt;br&gt;-- But then there are exceptions:&lt;br&gt;select 1.a, 1.e, 0.a&lt;br&gt;&lt;br&gt;/*&lt;br&gt;a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a&lt;br&gt;----------- ---------------------- ----------------&lt;br&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.0&lt;br&gt;sa&lt;br&gt;&lt;br&gt;1.e does not produce the alias (e for exponent???),&lt;br&gt;0.a seems to use float, so the value displayed is 0.0&lt;br&gt;&lt;br&gt;It is a shame that you cannot use this with string literals.&lt;br&gt;Unless you want to torture your colleagues I reckon that &lt;br&gt;the above is absolutely useless. But if you have an idea why &lt;br&gt;the above works, and works the way it works, do let me know.&lt;br&gt;&lt;br&gt;PS: the above syntax works on 2000,2005 and 2008.&lt;br&gt;&lt;br&gt;&amp;nbsp; Andras&lt;br&gt;*/&lt;br&gt;&lt;br&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=40245" width="1" height="1"&gt;</description></item><item><title>SQL Server 2008: Microsoft has given, and Microsoft has taken away (powersum)</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/11/22/40021.aspx</link><pubDate>Thu, 22 Nov 2007 18:14:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:40021</guid><dc:creator>András</dc:creator><slash:comments>8</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/40021.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=40021</wfw:commentRss><description>

&lt;p class="MsoNormal"&gt;SQL Server 2008 November CTP came out this week. This CTP
finally contains many major features that are worth playing with. However,
there are things that are no longer in SQL Server, things that I will be
missing (and many things that I’ll be happy to see go).&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;One of my favourite system functions is &lt;span&gt;powersum&lt;/span&gt;. This is
not documented, so Microsoft cannot be blamed at all for removing it (Well, not
really removing it, but just denying public access to it. It is very useful, so
Microsoft keep using it internally). However, I liked using this on 2005 to create
bit arrays from numbers. Powersum is an aggregate. It takes numbers, and it
returns a varbinary. It takes its input number, and SHIFTs 1 to the left by
this number, then ORs this with the aggregated value.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;For example the following query returns 0x16:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;
&lt;/span&gt;powersum&lt;span&gt;(&lt;/span&gt;col&lt;span&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;/span&gt;&lt;span&gt;(&lt;/span&gt; &lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;UNION ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;2&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;UNION ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;4&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;AS&lt;/span&gt; data &lt;span&gt;(&lt;/span&gt; col &lt;span&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;0x16’s binary representation is 10110 (so the bits at
position 1, 2 and 4 are set).&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;I’m really sorry to see this function go. I used it when
returning column permissions in SQL Compare. It allowed me to group column
permissions together, consequently my queries were sending less data. It also
allowed building query results in 2005 that were similar to SQL Server 2000’s syspermissions
table.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;However, the access restriction to this useful function
reminds me that while there are new features in SQL Server 2008, some obsolete
features and syntax will go away, just like it has happened with SQL Server
2005. I’ve seen many people finally migrating to the “new” join syntax, and abandoning
the =* syntax in 2005. Since SQL Server 2008 does not support compatibility
level 70 and before, this syntax will finally die out. &lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;2008 also seems to remove the DUMP and LOAD keywords. People
should use BACKUP and RESTORE instead, and it is a good time to look at all
those old maintenance jobs.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Books online mentions a few other changes that we should
expect in SQL Server 2008. (The page is &lt;a href="http://msdn2.microsoft.com/en-us/library/ms143729.aspx"&gt;Deprecated
Database Engine Features in SQL Server 2005&lt;/a&gt;). However this list is likely
to change. For example this page claims that SETUSER will be removed from 2008,
but it still seems to work (let’s not forget though that SQL Server 2008 is not
yet released). It is worth however to keep a close eye on this page as well as
the "Discontinued Database Engine Functionality in SQL Server 2008"
page in 2008’s Books online.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=40021" width="1" height="1"&gt;</description></item><item><title>SQLBits in Reading and the British language</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/10/08/37975.aspx</link><pubDate>Mon, 08 Oct 2007 14:35:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:37975</guid><dc:creator>András</dc:creator><slash:comments>0</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/37975.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=37975</wfw:commentRss><description>
&lt;p class="MsoNormal"&gt;SQLBits was held in Reading this Saturday and it certainly superseded
my expectations. There were over 300 people, excellent talks and plenty of
opportunities to meet others.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;There were four parallel sessions, one for BI, Dev, Katmai
and DBA, and since there is only one me, it was, as always, difficult to
choose.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;One thing that probably tops my list of interesting findings
for the day is the “British language”. Since the event was in the UK, this was
of course bound to happen. And it did happen at least four times in &lt;span&gt;Dave McMahon’s entertaining session. He liked
using “SET LANGUAGE ‘British’”. This is a statement that certainly increases
the comfort level of SQL Server. It is useful when you want to parse date
strings in your session, and these strings are following the format of a
different culture. Let’s say, they are in the format commonly used in the UK.
You may not want to play with SET DATEFORMAT, just type in “SET LANGUAGE ‘British’”.&lt;span&gt;&amp;nbsp; &lt;/span&gt;Note that sys.messages is looked up based on
the language_id, which in case of British is still 1033, so do not expect
different error messages after using SET LANGUAGE ‘British’ &lt;/span&gt;&lt;span&gt;&lt;span&gt;:)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;There were of course more interesting bits at this event,
but I leave them for later. For now I just want to say thanks to Simon Sabin
and Tony Rogerson for organizing the event, and of course, many thanks to those
who attended my session.&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=37975" width="1" height="1"&gt;</description></item><item><title>The GO command can have a parameter?</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/09/24/37563.aspx</link><pubDate>Mon, 24 Sep 2007 18:57:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:37563</guid><dc:creator>András</dc:creator><slash:comments>2</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/37563.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=37563</wfw:commentRss><description>I have mixed feelings about the GO command. It is not a T-SQL statement, it is just something that Management Studio and the other SQL Server tools understand as a batch separator command. Indeed, you can change it to whatever you wish in Management Studio under Tools-&amp;gt;Options-&amp;gt;Query Execution-&amp;gt;SQL Server-&amp;gt;General-&amp;gt;Batch separator.&lt;br&gt;So you can write queries like &lt;br&gt;&lt;br&gt;SELECT * FROM sys.objects&lt;br&gt;foo&lt;br&gt;SELECT * FROM sysobjects&lt;br&gt;foo&lt;br&gt;&lt;br&gt;Of course I'm still struggling to find a reason why someone would change the GO command.&lt;br&gt;&lt;br&gt;One thing I've found out recently is its parameter. SQL Server Management Studio seems to accept an integer after the GO command, and this will start an execution loop. For example if you write &lt;br&gt;&lt;br&gt;PRINT 'Hello word' &lt;br&gt;GO 5&lt;br&gt;&lt;br&gt;The result will be:&lt;br&gt;&lt;br&gt;Beginning execution loop&lt;br&gt;Hello word&lt;br&gt;Hello word&lt;br&gt;Hello word&lt;br&gt;Hello word&lt;br&gt;Hello word&lt;br&gt;Batch execution completed 5 times.&lt;br&gt;&lt;br&gt;&lt;br&gt;This is perfect for lazy moments when I want to populate a test table with some default values like:&lt;br&gt;&lt;br&gt;CREATE TABLE foo&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( a INT PRIMARY KEY IDENTITY&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , b INT DEFAULT 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;GO&lt;br&gt;&lt;br&gt;I usually write something like:&lt;br&gt;INSERT TOP (10) INTO foo (b) SELECT 1 FROM sys.objects&lt;br&gt;&lt;br&gt;but with the parameter to the GO command the above can be achieved with even less typing:&lt;br&gt;&lt;br&gt;INSERT INTO foo DEFAULT VALUES&lt;br&gt;GO 10&lt;br&gt;&lt;br&gt;The above will also insert 10 rows :)&lt;br&gt;Do let me know if you find a more interesting use for this parameter.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Andras&lt;br&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=37563" width="1" height="1"&gt;</description></item><item><title>Pivots with Dynamic Columns in SQL Server 2005</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx</link><pubDate>Fri, 14 Sep 2007 14:28:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:37265</guid><dc:creator>András</dc:creator><slash:comments>17</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/37265.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=37265</wfw:commentRss><description>&lt;P&gt;Pivots in SQL Server 2005 can rotate a table, i.e. they can turn rows into columns. PIVOTs are frequently used in reports, and they are reasonably simple to work with. However, I've seen quite a few questions about this operator. Most questions were about the column list in the PIVOT statement. This list is fixed, but many times the new columns are determined by the report at a later stage. This problem is easily solved when we mix pivots with dynamic SQL, so here is a very simple example about how to dynamically generate the pivot statement:&lt;/P&gt;
&lt;P&gt;PIVOT allows you to turn data rows into columns. For example, if you have a table like this (I use only three months here for simplicity):&lt;/P&gt;
&lt;DIV&gt;
&lt;P dir=ltr&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Sales&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;[Month]&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VARCHAR&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;20&lt;/FONT&gt;&lt;FONT color=gray&gt;)&amp;nbsp;,&lt;/FONT&gt;&lt;FONT color=black&gt;SaleAmount&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;INT&lt;/FONT&gt;&lt;FONT color=gray&gt;)

&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Sales&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=red&gt;'January'&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=black&gt;100&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Sales&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=red&gt;'February'&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=black&gt;200&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Sales&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=red&gt;'March'&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=black&gt;300&lt;/FONT&gt;&lt;FONT color=gray&gt;)

&lt;/FONT&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;*&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;SALES
&amp;nbsp;
&lt;/FONT&gt;&lt;FONT color=black&gt;
Month&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SaleAmount
----------------&amp;nbsp;&amp;nbsp;-----------
January&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;100
February&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;200
March&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;300&amp;nbsp;

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Suppose we wanted to convert the above into this: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=black&gt;&amp;nbsp;
January&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;February&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;March
&lt;/FONT&gt;&lt;FONT color=green&gt;-----------&amp;nbsp;----------&amp;nbsp;&amp;nbsp;----------
&lt;/FONT&gt;&lt;FONT color=black&gt;100&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;200&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;300

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;We can do this using the PIVOT operator, as follows: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[January]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[February]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[March]
&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Month]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;SaleAmount
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Sales
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;)&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;p&amp;nbsp;PIVOT&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=magenta&gt;SUM&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;SaleAmount&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FOR&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Month]&amp;nbsp;&lt;BR&gt;                      &lt;/FONT&gt;&lt;FONT color=blue&gt;IN&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;[January]&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;[February]&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;[March]&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;AS&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;pvt

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;However, in the above example, I have the column names fixed as the first three months. If I want to create a result in which the columns are dynamic (for example, they are read from a table), then I need to construct the above query dynamically. To demonstrate this let’s look at the following example:&lt;/P&gt;
&lt;P&gt;In the first table I have the column names I want to use:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;ColId&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;INT&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;ColName&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VARCHAR&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;10&lt;/FONT&gt;&lt;FONT color=gray&gt;))
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'Country'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'Month'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'Day'&lt;/FONT&gt;&lt;FONT color=gray&gt;)

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;In the second table I have the data. This consists of a row identifier (tID), a column ID (ColID) that refers to the column type in Table1, and a value:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2 &lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;tID&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;INT&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;ColID&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;INT&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;Txt&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VARCHAR&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;10&lt;/FONT&gt;&lt;FONT color=gray&gt;))

&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'US'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'July'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'4'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'US'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'Sep'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'11'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'US'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'Dec'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;VALUES&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;,&lt;/FONT&gt;&lt;FONT color=black&gt;3&lt;/FONT&gt;&lt;FONT color=gray&gt;, &lt;/FONT&gt;&lt;FONT color=red&gt;'25'&lt;/FONT&gt;&lt;FONT color=gray&gt;)

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Now I would like to retrieve data from these two tables, in the following format: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=black&gt;
tID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Country&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Day&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Month
-----------&amp;nbsp;----------&amp;nbsp;----------&amp;nbsp;----------
1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;US&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;July
2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;US&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Sep
3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;US&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dec&amp;nbsp;

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;In other words I want to turn the data rows in Table2 into columns. If I had a fixed set of columns for the result, i.e. the columns Country, Day, and Month were fixed, I could use SQL Server 2005’s PIVOT operator in a query like: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;tID
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Country]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Day]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Month]
&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2.tID
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t1.ColName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2.Txt
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;AS&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;JOIN&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table2&amp;nbsp;&lt;BR&gt;                       &lt;/FONT&gt;&lt;FONT color=blue&gt;AS&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;ON&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t1.ColId&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;=&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2.ColID
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;)&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;p&amp;nbsp;PIVOT&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;MAX&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;[Txt]&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FOR&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;ColName&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;IN&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;(&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Country]&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Day]&lt;/FONT&gt;&lt;FONT color=gray&gt;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;[Month]&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;)&amp;nbsp;)&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;AS&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;pvt
&lt;/FONT&gt;&lt;FONT color=blue&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;tID&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;;

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;However I need to construct this query dynamically, because the column names Country, Day, and Month are specified in a table, and can be changed independently from my query. In our case these columns are given in Table1. &lt;/P&gt;
&lt;P&gt;In the first step to generate the final pivot query I need to create the list of columns, in this case [Country], [Day], [Month].&lt;/P&gt;
&lt;P&gt;Since there is no string concatenation aggregator in SQL (a concatenation aggregator would not be deterministic without some order restriction), and since the column names are stored in rows of a table, I need to flatten these columns into a single row or variable. There are various solutions to achieve this. One solution would be to use a query like: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;DECLARE&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;2000&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;=&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=magenta&gt;COALESCE&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;',['&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;colName&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;']'&lt;/FONT&gt;&lt;FONT color=gray&gt;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;'['&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;colName&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;']'&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1
&lt;/FONT&gt;&lt;FONT color=blue&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;colName

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;This query works both on SQL Server 2000 and 2005. It is efficient, but some may not like it because it uses the same variable (@cols) on both sides of an assignment. Another solution that works on SQL Server 2005 only is to use XML PATH. &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;DECLARE&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;2000&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;=&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=magenta&gt;STUFF&lt;/FONT&gt;&lt;FONT color=gray&gt;((&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;SELECT&amp;nbsp;DISTINCT&amp;nbsp;TOP&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;100&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;PERCENT
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;'],['&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2.ColName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;Table1&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;AS&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;'],['&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;t2.ColName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;FOR&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;XML&amp;nbsp;PATH&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=red&gt;''&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;),&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;1&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=black&gt;2&lt;/FONT&gt;&lt;FONT color=gray&gt;,&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;''&lt;/FONT&gt;&lt;FONT color=gray&gt;)&amp;nbsp;+&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;']'

&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;This second query (I’ve seen this posted by Peter Larsson) has the advantage that it does not use the @cols variable on the right hand side. I like this solution more, since this can be extended as a general string concatenation aggregate in more complex queries. &lt;/P&gt;
&lt;P&gt;Both of the above queries generate, from &lt;STRONG&gt;Table1,&lt;/STRONG&gt; the string: &lt;STRONG&gt;‘[Country],[Day], [Month]’.&lt;/STRONG&gt; This column list is used twice in the pivot query that we aim to construct. Once it is use in the list of columns that we want to retrieve, and once it is used as the list of values that should become columns. Having constructed this list of columns above, we can just concatenate it with the missing parts of the pivot query like: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;DECLARE&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#434343&gt;@query&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=black&gt;4000&lt;/FONT&gt;&lt;FONT color=gray&gt;)
&lt;/FONT&gt;&lt;FONT color=blue&gt;SET&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#434343&gt;@query&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=blue&gt;=&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=red&gt;N'SELECT&amp;nbsp;tID,&amp;nbsp;'&lt;/FONT&gt;&lt;FONT color=gray&gt;+
&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&lt;/FONT&gt;&lt;FONT color=red&gt;'
FROM
(SELECT&amp;nbsp;&amp;nbsp;t2.tID
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;t1.ColName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;t2.Txt
FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Table1&amp;nbsp;AS&amp;nbsp;t1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;JOIN&amp;nbsp;Table2&amp;nbsp;AS&amp;nbsp;t2&amp;nbsp;ON&amp;nbsp;t1.ColId&amp;nbsp;=&amp;nbsp;t2.ColID)&amp;nbsp;p
PIVOT
(
MAX([Txt])
FOR&amp;nbsp;ColName&amp;nbsp;IN
(&amp;nbsp;'&lt;/FONT&gt;&lt;FONT color=gray&gt;+
&lt;/FONT&gt;&lt;FONT color=#434343&gt;@cols&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=gray&gt;+&lt;/FONT&gt;&lt;FONT color=red&gt;'&amp;nbsp;)
)&amp;nbsp;AS&amp;nbsp;pvt
ORDER&amp;nbsp;BY&amp;nbsp;tID;'
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Executing this with &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=blue&gt;EXECUTE&lt;/FONT&gt;&lt;FONT color=gray&gt;(&lt;/FONT&gt;&lt;FONT color=#434343&gt;@query&lt;/FONT&gt;&lt;FONT color=gray&gt;)&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;will give us the expected result: a table that is pivoted and shows columns that were specified in a table:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=green&gt;&lt;FONT color=#000000&gt;tID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Country&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Day&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Month
-----------&amp;nbsp;----------&amp;nbsp;----------&amp;nbsp;----------
1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;US&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;July
2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;US&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Sep
3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;US&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dec&lt;/FONT&gt;
&lt;/FONT&gt;&lt;/PRE&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=37265" width="1" height="1"&gt;</description></item><item><title>Do you need to be dbo to compare two databases using SQL Compare?</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/07/30/34240.aspx</link><pubDate>Mon, 30 Jul 2007 15:01:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:34240</guid><dc:creator>András</dc:creator><slash:comments>1</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/34240.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=34240</wfw:commentRss><description>&lt;SPAN&gt;
&lt;P class=MsoNormal&gt;This question comes up time to time. SQL Compare compares two database schemata, and in order to do so it needs to read the system tables and system views. On the other hand, some organizational policies can be rather restrictive about who and with what permissions are allowed to connect to a production system.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;The more complex databases make use of object owners to organise the database objects. Objects like tables, views, user defined types can be owned by individual users/schemas. Under SQL Server 2000, in order to read all the schema information, you do need to be dbo, otherwise you will not be able to see some of the object definitions, or you will not be able to learn about the existence of certain database objects.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Under SQL Server 2005 however there is a permission (VIEW DEFINITION) to control access to viewing object definitions. To add this permission to user UserA in a particular database run:&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;GRANT VIEW DEFINITION TO UserA;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;You can also grant this permission at server level by executing:&lt;/P&gt;&lt;u1:p&gt;&lt;/u1:p&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;GRANT VIEW ANY DEFINITION UserA;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;The nice thing about this is that with the help of the above permission you are not granting permission to modify the database schema, so you can allow people to use SQL Compare to compare and monitor schema changes without allowing them to modify the databases in question. You can still generate a synchronization script, but that you can later execute as a different user.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Andras&lt;/SPAN&gt;&lt;BR&gt;&lt;/P&gt;&lt;SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=34240" width="1" height="1"&gt;</description></item><item><title>Databases and source control article</title><link>http://www.simple-talk.com/community/blogs/andras/archive/2007/05/30/30010.aspx</link><pubDate>Wed, 30 May 2007 19:39:00 GMT</pubDate><guid isPermaLink="false">f46e5dea-70cd-4a69-a7e1-fd07a313bd4d:30010</guid><dc:creator>András</dc:creator><slash:comments>2</slash:comments><comments>http://www.simple-talk.com/community/blogs/andras/comments/30010.aspx</comments><wfw:commentRss>http://www.simple-talk.com/community/blogs/andras/commentrss.aspx?PostID=30010</wfw:commentRss><description>

&lt;p class="MsoNormal"&gt;My current interest is focused on database evolution and on
ways to manage changes to database schemata. This interest is reflected in my
current project, SQL Compare 6. This version has the goal to help source
control integration for databases by allowing users to handle a set of SQL
creation scripts as a possible source for the database schema. However, even with this tool, it is
not a simple task to set up source control, and there are
many problems one needs to find a solution for. I have summarized some of these
problems in an article which you can access on &lt;a href="/sql/database-administration/source-control-and-databases/"&gt;Simple Talk&lt;/a&gt;&lt;br&gt;&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=30010" width="1" height="1"&gt;</description></item></channel></rss>