<rss version="2.0"><channel><title>Title</title><link>http://beyondrelational.com</link><description>description</description><webMaster>beyondrelational</webMaster><language>en-us</language><image><url>http://beyondrelational.com/modules/23/groups/362/images/17021eb5-e554-4269-a990-37b1db2393c9thumbnail.jpg</url><title>Title</title><link>http://beyondrelational.com</link><width>50</width><height>50</height></image><copyright>Copyright © Beyondrelational.com</copyright><lastBuildDate>Wed, 16 May 2012 20:49:07 GMT</lastBuildDate><ttl>60</ttl><item><title>XQuery Lab 65 – Restructuring an XML document using FLWOR</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10528/xquery-lab-65-restructuring-an-xml-document-using-flwor.aspx</link><description>&lt;p&gt;I found this question in &lt;a href="http://www.sqlservercentral.com/Forums/Topic885210-356-2.aspx#bm1219220"&gt;this&lt;/a&gt; SSC forum thread requesting help to shape the XML document. Here is the input XML document.&lt;/p&gt;  &lt;pre class="brush: xml"&gt;&amp;lt;Root&amp;gt;
	&amp;lt;Student&amp;gt;Jhon &amp;lt;/Student&amp;gt;
	&amp;lt;Student&amp;gt; Luka &amp;lt;/Student&amp;gt;
	&amp;lt;Post&amp;gt;1&amp;lt;/Post&amp;gt;
	&amp;lt;Post&amp;gt;2&amp;lt;/Post&amp;gt;
&amp;lt;/Root&amp;gt;&lt;/pre&gt;

&lt;p&gt;The expected output is as follows.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;Root&amp;gt;
  &amp;lt;Students&amp;gt;
    &amp;lt;Student&amp;gt;Jhon &amp;lt;/Student&amp;gt;
    &amp;lt;Student&amp;gt; Luka &amp;lt;/Student&amp;gt;
  &amp;lt;/Students&amp;gt;
  &amp;lt;Posts&amp;gt;
    &amp;lt;Post&amp;gt;1&amp;lt;/Post&amp;gt;
    &amp;lt;Post&amp;gt;2&amp;lt;/Post&amp;gt;
  &amp;lt;/Posts&amp;gt;
&amp;lt;/Root&amp;gt;&lt;/pre&gt;

&lt;p&gt;This type of formatting can be achieved through a simple FLWOR operation. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;DECLARE @x XML = '
&amp;lt;Root&amp;gt;
	&amp;lt;Student&amp;gt;Jhon &amp;lt;/Student&amp;gt;
	&amp;lt;Student&amp;gt; Luka &amp;lt;/Student&amp;gt;
	&amp;lt;Post&amp;gt;1&amp;lt;/Post&amp;gt;
	&amp;lt;Post&amp;gt;2&amp;lt;/Post&amp;gt;
&amp;lt;/Root&amp;gt;'

SELECT @x.query ('
	for $i in (Root)
	let $s := $i/Student
	let $p := $i/Post
	return
		&amp;lt;Root&amp;gt;
			&amp;lt;Students&amp;gt; {$s} &amp;lt;/Students&amp;gt;
			&amp;lt;Posts&amp;gt;{$p}&amp;lt;/Posts&amp;gt;
		&amp;lt;/Root&amp;gt;
')

/*
Produces: 
&amp;lt;Root&amp;gt;
  &amp;lt;Students&amp;gt;
    &amp;lt;Student&amp;gt;Jhon &amp;lt;/Student&amp;gt;
    &amp;lt;Student&amp;gt; Luka &amp;lt;/Student&amp;gt;
  &amp;lt;/Students&amp;gt;
  &amp;lt;Posts&amp;gt;
    &amp;lt;Post&amp;gt;1&amp;lt;/Post&amp;gt;
    &amp;lt;Post&amp;gt;2&amp;lt;/Post&amp;gt;
  &amp;lt;/Posts&amp;gt;
&amp;lt;/Root&amp;gt;
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;View All Labs: &lt;/b&gt;&lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/06/26/xquery-labs-a-collection-of-xquery-sample-scripts.aspx"&gt;XQuery Labs - A Collection of XQuery Sample Scripts and Tutorials&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10528/xquery-lab-65-restructuring-an-xml-document-using-flwor.aspx</guid><pubDate>Fri, 09 Dec 2011 13:33:00 GMT</pubDate></item><item><title>SQL Server book from Pinal Dave</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10527/sql-server-book-from-pinal-dave.aspx</link><description>&lt;p&gt;&lt;img style="margin: 0px 6px 0px 0px; display: inline; float: left" align="left" src="http://www.pinaldave.com/bimg/joes2pros4.jpg" width="150" height="204" /&gt;&lt;a href="http://blog.sqlauthority.com/" target="_blank"&gt;Pinal Dave&lt;/a&gt; is an inspiration for a large number of SQL Server professionals all over the world. He is a great teacher who knows how to explain any complex stuff in very simple words and examples that everyone understands. That is the reason why his &lt;a href="http://blog.sqlauthority.com/" target="_blank"&gt;blog&lt;/a&gt; is considered to be one of the best source of reference for SQL Server related stuff.&lt;/p&gt;  &lt;p&gt;Pinal’s blog has helped thousands of people learn SQL Server. Very often I end up on his blog when searching for some SQL Server stuff online. He is a great teacher, who is always willing to travel to any extend if requested to present in a SQL Server group. He has done a large number of SQL Server training sessions and workshops all over India and US. &lt;/p&gt;  &lt;p&gt;I was not surprised when Microsoft picked him and gave him the role of SQL Server Evangelist. They are known for acquiring the ‘best’, no matter whether it is a company, product or a person. Vinod Kumar, Microsoft evangelist and a mentor and role model for many of us, has already set up a very high standard for anyone following his foot steps. And then the experts at MS picked the right person and put him in the right place for the benefit or the entire SQL Server community in India. That gives us a lot of reasons to smile.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;SQL Programming Joes 2 Pros&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Pinal has been teaching the SQL Server community in a number of ways. In addition to regular blog posts, he has been contributing a lot in the form of Web casts, Presentations, workshops etc. And finally, to add sweet to the dessert, he announced a SQL Server book which has made many of us quite happy and proud. I am very excited and waiting for my copy of the book, which he promised is on the way!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Get your free copy of “SQL Programming Joes 2 Pros”&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Pinal has announced a &lt;a href="http://blog.sqlauthority.com/2011/08/01/sql-server-win-a-book-a-day-contest-rules-day-0-of-35/" target="_blank"&gt;contest&lt;/a&gt; on his blog where he will give away 70 copies of his book for free. He is writing a 35 days series of blog posts where he shares a number of SQL Server tips and tricks that you can apply in your day-to-day SQL Server life. To get a copy of the book, all you need to do is to read his posts carefully and answer a few simple questions. Once done, wait for the postman or courier boy to knock your door and deliver you a printed copy of the book. &lt;/p&gt;  &lt;p&gt;I would like to invite everyone to &lt;a href="http://blog.sqlauthority.com/2011/08/01/sql-server-win-a-book-a-day-contest-rules-day-0-of-35/" target="_blank"&gt;read the series&lt;/a&gt;. Whether you win a free copy of the book or not, it is guaranteed that you will certainly learn quite a lot from the series. Thank you Pinal for writing this book and giving us yet another reason to be proud of your achievements!&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10527/sql-server-book-from-pinal-dave.aspx</guid><pubDate>Mon, 08 Aug 2011 09:52:00 GMT</pubDate></item><item><title>XQuery Lab 64 – Reading values from an XML column</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10526/xquery-lab-64-reading-values-from-an-xml-column.aspx</link><description>&lt;p&gt;I got a question in my &lt;a href="http://beyondrelational.com/ask/jacob/questions/913/sql-using-xquery.aspx" target="_blank"&gt;personal forum&lt;/a&gt; this morning requesting help to read values from an XML column. My first reaction was “Well, there is an XQuery lab demonstrating this!”. However, after reviewing the existing XQuery labs, I realized there are no posts demonstrating this. &lt;/p&gt;  &lt;p&gt;Here is a simple example that demonstrates how to read values from an XML column.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;DECLARE @t TABLE (
	ID INT IDENTITY,
	Data XML
)

INSERT INTO @t (Data)
SELECT '&amp;lt;employee name=&amp;quot;Jacob&amp;quot; /&amp;gt;' UNION ALL
SELECT '&amp;lt;employee name=&amp;quot;Michael&amp;quot; /&amp;gt;'

SELECT
	x.value('@Name[1]', 'VARCHAR(20)') AS Name
FROM @t t
CROSS APPLY Data.nodes('/employee') a(x)
/*
Name
--------------------
Jacob
Michael
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;View All Labs: &lt;/b&gt;&lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/06/26/xquery-labs-a-collection-of-xquery-sample-scripts.aspx"&gt;XQuery Labs - A Collection of XQuery Sample Scripts and Tutorials&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10526/xquery-lab-64-reading-values-from-an-xml-column.aspx</guid><pubDate>Mon, 18 Jul 2011 02:19:00 GMT</pubDate></item><item><title>SQL Server–Partitioning FILESTREAM data with RANGE LEFT does not work</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10525/sql-serverpartitioning-filestream-data-with-range-left-does-not-work.aspx</link><description>&lt;p&gt;One of the problems I came across while writing the partitioning chapter for my FILESTREAM book is that the partitioning does not work correctly with RANGE LEFT. It works as expected when using RANGE RIGHT. Something is wrong with RANGE LEFT and the problem exists in SQL Server 2008, R2 and Denali CTP1.&lt;/p&gt;  &lt;p&gt;I created a repro script and wanted to submit a connect bug. However, the connect page does not allow me to post scripts longer than 2000 characters. So I thought of posting the script here and add a link to this post in the connect item. Here is the repro script for those of you who are interested to try it, and here is the &lt;a href="https://connect.microsoft.com/SQLServer/feedback/details/675124/filestream-partitioning-does-not-work-when-using-range-left" target="_blank"&gt;connect item I submitted&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;-- -----------------------------------------------
-- Create the database
-- -----------------------------------------------
USE master
GO

IF DB_ID('NorthPole') IS NOT NULL 
	DROP DATABASE NorthPole 
GO

CREATE DATABASE NorthPole ON
PRIMARY ( 
    NAME = NorthPoleData1, 
    FILENAME = 'C:\Demos\Data\NorthPoleData1.mdf'),
FILEGROUP NorthPoleDB2(
    NAME = NorthPoleData2, 
    FILENAME = 'C:\Demos\Data\NorthPoleData2.ndf'),
FILEGROUP NorthPoleFS1 CONTAINS FILESTREAM DEFAULT( 
    NAME = NorthPoleFS1,
    FILENAME = 'C:\Demos\FS\NorthPoleFS1'),
FILEGROUP NorthPoleFS2 CONTAINS FILESTREAM( 
    NAME = NorthPoleFS2,
    FILENAME = 'C:\Demos\FS\NorthPoleFS2')
LOG ON ( 
    NAME = NorthPoleLOG,
    FILENAME = 'C:\Demos\Data\NorthPoleLOG.ldf')
GO

-- -----------------------------------------------
-- Create Partition Function and Scheme
-- -----------------------------------------------
USE NorthPole 
GO

CREATE PARTITION FUNCTION NPPartFN (INT) AS 
RANGE LEFT FOR VALUES (3)

CREATE PARTITION SCHEME NPPartDBSch AS 
PARTITION NPPartFN TO([PRIMARY],[NorthPoleDB2]) 
GO

CREATE PARTITION SCHEME NPPartFSSch AS 
PARTITION NPPartFN TO(NorthPoleFS1, NorthPoleFS2) 
GO

-- -----------------------------------------------
-- Create Table
-- -----------------------------------------------
CREATE TABLE [dbo].[Items](
	[ItemID] [int] IDENTITY(1,1) PRIMARY KEY ON NPPartDBSch(ItemID),
	[ItemGuid] [uniqueidentifier] ROWGUIDCOL  NOT NULL 
		UNIQUE ON [PRIMARY],
	[ItemNumber] [varchar](20) NULL,
	[ItemDescription] [varchar](50) NULL,
	[ItemImage] [varbinary](max) FILESTREAM  NULL
) ON NPPartDBSch(ItemID)
FILESTREAM_ON NPPartFSSch

-- -----------------------------------------------
-- Insert 6 Rows. 1-3 will go to FS1 and 4-6 will
--   go to FS2
-- -----------------------------------------------
INSERT INTO Items(itemguid, itemnumber, itemdescription, ItemImage)
SELECT NEWID(), 'ITM001', 'Item 1', CAST(1 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM002', 'Item 2', CAST(2 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM003', 'Item 3', CAST(3 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM004', 'Item 4', CAST(4 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM005', 'Item 5', CAST(5 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM006', 'Item 6', CAST(6 AS VARBINARY(MAX))


-- -----------------------------------------------
-- Add a new file group (DB and FS)
-- -----------------------------------------------
ALTER DATABASE NorthPole 
ADD FILEGROUP NorthPoleFS3 CONTAINS FILESTREAM

ALTER database NorthPole 
ADD FILE 
( 
    NAME = 'NorthPoleFS3', 
    FILENAME = 'C:\Demos\FS\NorthPoleFS3' 
) 
TO FILEGROUP NorthPoleFS3

ALTER DATABASE NorthPole 
ADD FILEGROUP NorthPoleDB3

ALTER database NorthPole 
ADD FILE 
( 
    NAME = 'NorthPoleDB3', 
    FILENAME = 'C:\Demos\Data\NorthPoleData3.ndf' 
) 
TO FILEGROUP NorthPoleDB3


-- -----------------------------------------------
-- Insert 3 more records. This will go to FS2
-- -----------------------------------------------
INSERT INTO Items(itemguid, itemnumber, itemdescription, ItemImage)
SELECT NEWID(), 'ITM007', 'Item 7', CAST(7 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM008', 'Item 8', CAST(8 AS VARBINARY(MAX))
UNION ALL
SELECT NEWID(), 'ITM009', 'Item 9', CAST(9 AS VARBINARY(MAX))


-- -----------------------------------------------
-- Switch partitions. Alter the partition function
--   so that rows 7 to 9 will go to the new 
--   file group
-- -----------------------------------------------
ALTER PARTITION SCHEME NPPartFSSch  
NEXT USED NorthPoleFS3

ALTER PARTITION SCHEME NPPartDBSch 
NEXT USED NorthPoleDB3

ALTER PARTITION FUNCTION NPPartFN() 
SPLIT RANGE (6);

-- -----------------------------------------------
-- After the above, a new FILESTREAM folder is
--   created in FS1. No data goes to FS3
-- -----------------------------------------------&lt;/pre&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10525/sql-serverpartitioning-filestream-data-with-range-left-does-not-work.aspx</guid><pubDate>Sun, 12 Jun 2011 20:15:00 GMT</pubDate></item><item><title>Getting started with SQL Server Wait Types</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10524/getting-started-with-sql-server-wait-types.aspx</link><description>&lt;p&gt;SQL Server Wait Types are important factors to consider while analyzing performance problems of SQL Server databases. If you notice a particular wait type is occurring too often or for too long, it indicates a problem in most cases.&lt;/p&gt;  &lt;p&gt;There are several dozens of different wait types and it is quite important that every Database Administrator understand them well. Luckily, star blogger &lt;a href="http://blog.sqlauthority.com/" target="_blank"&gt;Pinal Dave&lt;/a&gt; (&lt;a href="http://twitter.com/pinaldave" target="_blank"&gt;@pinaldave&lt;/a&gt; | &lt;a href="http://blog.sqlauthority.com/" target="_blank"&gt;blog.sqlauthority.com&lt;/a&gt;) has written a long series of blog posts on various wait types. What I found very interesting about this series is the way each wait type is explained. Just like every other post on his blog, every post in this series is quite easy to understand and straight to the point. &lt;/p&gt;  &lt;p&gt;I strongly believe that this series is a ‘must-read’ piece for every SQL Server Database Administrator and Developer. So start right now: &lt;a href="http://blog.sqlauthority.com/2011/02/28/sql-server-summary-of-month-wait-type-day-28-of-28/" target="_blank"&gt;SQL SERVER – Summary of Month – Wait Type&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10524/getting-started-with-sql-server-wait-types.aspx</guid><pubDate>Wed, 16 Mar 2011 13:28:00 GMT</pubDate></item><item><title>T-SQL Tuesday #016 - Summarizing data using GROUPING SETS()</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10523/t-sql-tuesday-016-summarizing-data-using-grouping-sets.aspx</link><description>&lt;p&gt;&lt;a come-one-come-all-to?="come-one-come-all-to?" DBProgramming="DBProgramming" DataMgmt="DataMgmt" index.php="index.php" blogs.lessthandot.com="blogs.lessthandot.com" href:?http:="href:?http:"&gt;&lt;img style="margin: 0px 15px 0px 0px; display: inline" align="left" src="http://blogs.lessthandot.com/media/blogs/DataMgmt/olap_1.gif" /&gt;&lt;/a&gt; I have been watching the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2010/12/07/a-year-of-tuesdays-t-sql-tuesday-meta-roundup.aspx" target="_blank"&gt;TSQL Tuesday Blog Parties&lt;/a&gt; for quite some time and this is the first time I am participating in it. &lt;a href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/come-one-come-all-to" target="_blank"&gt;T-SQL Tuesday #16&lt;/a&gt; is hosted by &lt;a href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/come-one-come-all-to"&gt;Jes Schultz Borland&lt;/a&gt; and the topic is &lt;em&gt;Aggregation&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Aggregating and summarizing data is a common business requirement. Very often we come across requirements to calculate the total values presented in one or more columns on a web page. Some times the requirement may be bit more complicated such as to calculate multiple levels of sub-totals along with a grand total. &lt;/p&gt;  &lt;p&gt;Usually this type of tasks are efficiently done by reporting tools. Most reporting tools are equipped with the functionality to partition and summarize data based on custom user requirements. Very often I see questions asking for help to write TSQL queries that returns data in specific shape and format so that the client application can directly display the information on a web page. My first answer used to be an advice to handle this type of requirements in the presentation layer of the application, until I came across a real requirement myself, a few years back. &lt;/p&gt;  &lt;p&gt;The application had a few web pages which display various sales data in a grid control with multiple levels of sub-totals and totals. The web page had a huge chunk of code written to correctly calculate the sub totals of each levels and display them at the right position within the grid control. The page was very slow and the task was to optimize it. Moving the calculation logic into the database helped to improve performance tremendously. &lt;/p&gt;  &lt;p&gt;There are a number of TSQL keywords available that we can use to produce sub-totals and totals along with the query results. The simplest of them is &lt;strong&gt;COMPUTE BY&lt;/strong&gt; which produces a second result set with the totals of the query as given in &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/09/02/tsql-lab-4-how-to-add-a-total-line-to-the-query-result.aspx" target="_blank"&gt;this example&lt;/a&gt;. But a second result set may not be desirable on certain situations. We might need a single result set with a total row. This can be easily achieved by using using WITH ROLLUP or WITH CUBE as demonstrated &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/09/03/tsql-lab-5-using-with-rollup-to-generate-subtotals-and-grand-total-rows.aspx" target="_blank"&gt;here&lt;/a&gt;, &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/09/04/tsql-lab-6-using-with-cube-to-generate-subtotal-and-grand-total-rows.aspx" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/09/05/tsql-lab-7-enhancements-to-rollup-and-cube-in-sql-server-2008.aspx" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Enter GROUPING SETS&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;SQL Server 2008 introduced a new function &lt;em&gt;GROUPING SETS()&lt;/em&gt; which gives more control over the total rows generated along with the query result. We will see a few examples to understand this. Run the following script to generate the sample table for the examples we will use in this post.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;IF OBJECT_ID('Orders') IS NOT NULL DROP TABLE Orders
GO
CREATE TABLE Orders (
    OrderID INT,
    OrderDate DATETIME,
    CustomerName VARCHAR(20),
    ItemName VARCHAR(20),
    Quantity INT,
    PricePerCase MONEY )
GO

INSERT INTO Orders( OrderID, OrderDate, CustomerName, ItemName, Quantity, PricePerCase )
    SELECT 1, '2007-08-01', 'Jacob', 'Item 1', 10, 12.5
INSERT INTO Orders( OrderID, OrderDate, CustomerName, ItemName, Quantity, PricePerCase )
    SELECT 1, '2007-08-01', 'Jacob', 'Item 2', 12, 15.0
INSERT INTO Orders( OrderID, OrderDate, CustomerName, ItemName, Quantity, PricePerCase )
    SELECT 2, '2008-08-02', 'Jacob', 'Item 1', 15, 12.5
INSERT INTO Orders( OrderID, OrderDate, CustomerName, ItemName, Quantity, PricePerCase )
    SELECT 2, '2008-08-02', 'Jacob', 'Item 2', 20, 15.0
INSERT INTO Orders( OrderID, OrderDate, CustomerName, ItemName, Quantity, PricePerCase )
    SELECT 1, '2008-08-01', 'Mike', 'Item 1', 6, 12.5
INSERT INTO Orders( OrderID, OrderDate, CustomerName, ItemName, Quantity, PricePerCase )
    SELECT 1, '2008-08-01', 'Mike', 'Item 2', 4, 11.0&lt;/pre&gt;

&lt;p&gt;Within the GROUPING SETS() function, you can define set of columns on which you need a total row to be generated. The following example shows a query using GROUPING SETS(). It does not generate any total/subtotal rows and produces the same result as a GROUP BY clause could generate.&amp;#160; &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName))
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Mike                 Item 1               75.00
Jacob                Item 2               480.00
Mike                 Item 2               44.00
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating only Subtotals and Grand Total Row&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((ItemName), (CustomerName),())
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                All Items            792.50
Mike                 All Items            119.00
All Customers        All Items            911.50
All Customers        Item 1               387.50
All Customers        Item 2               524.00
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating a Total Row per Customer&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (CustomerName))
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Jacob                Item 2               480.00
Jacob                All Items            792.50
Mike                 Item 1               75.00
Mike                 Item 2               44.00
Mike                 All Items            119.00
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating a Total Row per Item&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (ItemName))
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Mike                 Item 1               75.00
All Customers        Item 1               387.50
Jacob                Item 2               480.00
Mike                 Item 2               44.00
All Customers        Item 2               524.00
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating a Grand Total row&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), ())
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Jacob                Item 2               480.00
Mike                 Item 1               75.00
Mike                 Item 2               44.00
All Customers        All Items            911.50
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating Subtotal rows for Customers and a Grand Total row&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (CustomerName), ())
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Jacob                Item 2               480.00
Jacob                All Items            792.50
Mike                 Item 1               75.00
Mike                 Item 2               44.00
Mike                 All Items            119.00
All Customers        All Items            911.50
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating Subtotal rows for Items and a Grand Total Row&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (ItemName), ())
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Mike                 Item 1               75.00
All Customers        Item 1               387.50
Jacob                Item 2               480.00
Mike                 Item 2               44.00
All Customers        Item 2               524.00
All Customers        All Items            911.50
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating Sub total rows for Customers and Items&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (ItemName), (CustomerName))
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Mike                 Item 1               75.00
All Customers        Item 1               387.50
Jacob                Item 2               480.00
Mike                 Item 2               44.00
All Customers        Item 2               524.00
Jacob                All Items            792.50
Mike                 All Items            119.00
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Generating Sub total rows for Customers and Items along with a Grand Total Row&lt;/b&gt;&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (ItemName), (CustomerName),())
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 1               312.50
Mike                 Item 1               75.00
All Customers        Item 1               387.50
Jacob                Item 2               480.00
Mike                 Item 2               44.00
All Customers        Item 2               524.00
All Customers        All Items            911.50
Jacob                All Items            792.50
Mike                 All Items            119.00
*/&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Ordering Results&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The above result set gives us sub totals by customer and by item and again a grand total row. However, the order of the rows is not good. If you want to retrieve the results in a specific order, you need to specify an ordering clause. The following query produces the results ordered by the grouping level. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
    CASE 
        WHEN GROUPING(CustomerName) = 1 THEN 'All Customers' 
        ELSE CustomerName 
    END AS CustomerName,
    CASE WHEN GROUPING(ItemName) = 1 THEN 'All Items'
        ELSE ItemName
    END AS ItemName,
    SUM(Quantity * PricePerCase) AS Amount
FROM Orders
GROUP BY GROUPING SETS((CustomerName, ItemName), (ItemName), (CustomerName),())
ORDER BY GROUPING(CustomerName), GROUPING(ItemName)
/*
CustomerName         ItemName             Amount
-------------------- -------------------- ---------------------
Jacob                Item 2               480.00
Mike                 Item 2               44.00
Jacob                Item 1               312.50
Mike                 Item 1               75.00
Jacob                All Items            792.50
Mike                 All Items            119.00
All Customers        Item 1               387.50
All Customers        Item 2               524.00
All Customers        All Items            911.50
*/&lt;/pre&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10523/t-sql-tuesday-016-summarizing-data-using-grouping-sets.aspx</guid><pubDate>Tue, 08 Mar 2011 05:21:00 GMT</pubDate></item><item><title>SQL Server – TSQL – Quiz 2011 is here, your chance to win an Apple iPad!</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10522/sql-server-tsql-quiz-2011-is-here-your-chance-to-win-an-apple-ipad.aspx</link><description>&lt;p&gt;We are back with the first SQL Server Quiz of year 2011 – &lt;a href="http://beyondrelational.com/quiz/SQLServer/TSQL/2011/default.aspx" target="_blank"&gt;TSQL Quiz 2011&lt;/a&gt;. The quiz started on 1st March and will run until 31 March 2011. There are 31 questions in this series and a question is published every day.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Congratulations to the Winners of SQL Server Quiz 2010&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;We did a similar quiz a few months ago and it was a great experience. A large number of SQL Server enthusiasts participated actively in the discussions. We take this opportunity to congratulate the winners of &lt;a href="http://beyondrelational.com/quiz/sqlserver/general/2010/default.aspx" target="_blank"&gt;SQL Server Quiz 2010&lt;/a&gt;. &lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.30.45/4THI6ZVT0T7L.png" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;Mike Lewis &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;Apple iPad&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/8YWN3t"&gt;Redgate&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.58.06/4TGYXQHYWRWB.jpg" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;Docker &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;Amazon Kindle&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/cV9P8Q"&gt;Idera&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.47.25/4THUYOBBFYXR.jpg" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;IGO &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;iPod Nano&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/cnuqQI"&gt;Quest&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.51.12/4TG7T2FQXXI1.jpg" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;Sivaprasad S - SIVA &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;iPod Nano&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/cnuqQI"&gt;Quest&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/utility/anonymous.gif" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;Abi Chapagai &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;iPod Nano&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/cnuqQI"&gt;Quest&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.58.05/4TGQQUK85JEZ.jpg" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;Nupur Dave &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;iPod Nano&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/cnuqQI"&gt;Quest&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="42"&gt;&lt;img border="0" alt="" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.27.74/4TE9F0EAS1TJ.jpg" width="40" height="40" /&gt;&lt;/td&gt;        &lt;td valign="top" width="194"&gt;Ramireddy &lt;/td&gt;        &lt;td valign="top" width="229"&gt;&lt;strong&gt;iPod Nano&lt;/strong&gt; (Sponsored by &lt;a href="http://bit.ly/cnuqQI"&gt;Quest&lt;/a&gt;)&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;In addition to the winners listed above, 44 other people won free software licenses worth over 17,000$. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Inviting you to TSQL Quiz 2011&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;TSQL Quiz 2011 started on 1st of March and will run until March 31, 2011. Each question will stay open for 30 days and you can post an answer within 30 days of the publication date. After 30 days the quiz master will evaluate your answers and will assign a score to each answer (between 0 and 10). The winners will be decided based on the total score you get from all the 31 questions. &lt;/p&gt; &lt;img src="http://beyondrelational.com/images/quiz/ipadleft.png" /&gt;   &lt;p&gt;I invite all of you to participate in &lt;a href="http://beyondrelational.com/quiz/sqlserver/tsql/2011/questions/all.aspx" target="_blank"&gt;TSQL Quiz 2011&lt;/a&gt;. The winner will get an &lt;a href="http://beyondrelational.com/quiz/sqlserver/tsql/2011/prizes.aspx" target="_blank"&gt;Apple iPad&lt;/a&gt; from &lt;a href="http://bit.ly/dvuHga" target="_blank"&gt;Redgate Software&lt;/a&gt;. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10522/sql-server-tsql-quiz-2011-is-here-your-chance-to-win-an-apple-ipad.aspx</guid><pubDate>Sun, 06 Mar 2011 17:45:00 GMT</pubDate></item><item><title>Happy Birthday to TSQL Challenges and its younger sibling!</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10521/happy-birthday-to-tsql-challenges-and-its-younger-sibling.aspx</link><description>&lt;p&gt;&lt;strong&gt;TSQL Challenges – 2nd Birthday Party!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://beyondrelational.com/puzzles/tsql/default.aspx" target="_blank"&gt;TSQL Challenges&lt;/a&gt; is turning two years old today. We did the first TSQL Challenge two years ago - on 27th February 2009. In two years, TSQL Challenge has grown up with the help of several volunteers and TSQL enthusiasts who stepped in and selflessly helped. I have written a detailed post about this journey in one of my &lt;a href="http://beyondrelational.com/blogs/tc/archive/2011/02/21/tsql-challenges-is-turning-2-years-old.aspx" target="_blank"&gt;previous posts&lt;/a&gt;. It has been a wonderful journey with 50 challenges, 700 unique participants and over 3,500 solutions.&lt;/p&gt;  &lt;p&gt;We invite all of you to the Birthday Party on &lt;a href="http://beyondrelational.com/puzzles/tsql/default.aspx" target="_blank"&gt;beyondrelational.com&lt;/a&gt;. The first course is a re-launched version of &lt;a href="http://beyondrelational.com/puzzles/tsql/1/english/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;TSQL Challenge 1&lt;/a&gt; which comes with a variety of birds, grains and fruits. You need to feed the birds with correct combination of food baskets before you move to your own dinner table. To move to the second course, you need to solve &lt;a href="http://beyondrelational.com/puzzles/tsql/1/english/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;TSQL Challenge 1&lt;/a&gt;. To cater to the tastes all of you from different parts of the world, we have made it available in &lt;a href="http://beyondrelational.com/puzzles/tsql/1/english/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;English&lt;/a&gt;, &lt;a href="http://beyondrelational.com/puzzles/tsql/1/korean/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;Korean&lt;/a&gt;, &lt;a href="http://beyondrelational.com/puzzles/tsql/1/chinese/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;Chinese&lt;/a&gt;, &lt;a href="http://beyondrelational.com/puzzles/tsql/1/italian/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;Italian&lt;/a&gt;, &lt;a href="http://beyondrelational.com/puzzles/tsql/1/french/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;French&lt;/a&gt; and &lt;a href="http://beyondrelational.com/puzzles/tsql/1/portuguese/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;Portuguese&lt;/a&gt; flavors.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Meet the new born baby – PLSQL Challenges&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Many people from the ORACLE world suggested that it is a good idea to re-run these challenges in PLSQL as well. This will help us to learn several interesting facts about other products. For example, such a comparison will tell us how easily you can solve a problem in ORACLE which is quite hard in SQL Server. Similarly, it will be quite interesting to know that a problem that is hard to solve in PLSQL can be easily solved in TSQL. &lt;/p&gt;  &lt;p&gt;Keeping this in mind, we have been working on bringing up the PLSQL version of TSQL Challenges. You can find the first &lt;a href="http://beyondrelational.com/puzzles/plsql/default.aspx" target="_blank"&gt;PLSQL Challenge&lt;/a&gt; &lt;a href="http://beyondrelational.com/puzzles/plsql/1/english/pair-wise-and-ordered-assignment-of-objects-from-two-different-lists.aspx" target="_blank"&gt;here&lt;/a&gt;. I am quite hopeful that many of you will step forward and help this infant to grow up just like many of you did for TSQL Challenges. I look forward to hear your comments, suggestion and feed back through the &lt;a href="http://beyondrelational.com/ask/plsqlchallenges/default.aspx" target="_blank"&gt;PLSQL Challenge Discussion Thread&lt;/a&gt;. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10521/happy-birthday-to-tsql-challenges-and-its-younger-sibling.aspx</guid><pubDate>Sun, 27 Feb 2011 23:01:00 GMT</pubDate></item><item><title>What is SQL Server Juneau?</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10520/what-is-sql-server-juneau.aspx</link><description>&lt;p&gt;“&lt;a href="http://msdn.microsoft.com/en-us/data/gg427686" target="_blank"&gt;Juneau&lt;/a&gt;” is the code name given to the new SQL Server development environment which is based on Visual Studio shell. It is officially named “SQL Server Developer Tools” (SSDT) which is expected to provide a wide range of functionalities that are currently not available with SQL Server Management Studio (SSMS).&lt;/p&gt;  &lt;p&gt;The current version of SQL Server Denali is CTP1 which does not include Juneau. It is expected to be available with the next CTP release (CTP2). See &lt;a href="http://what.isnew.in/sqlserver/denali" target="_blank"&gt;What is new in SQL Server Denali&lt;/a&gt; for a detailed list of features available in the next SQL Server Version (SQL11).&lt;/p&gt;  &lt;p&gt;One of the interesting features that will be available in Juneau is more support for SQL Azure Development. A few other features that I found interesting are: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Supports connected and offline database development&lt;/li&gt;    &lt;li&gt;Integrated application and database development&lt;/li&gt;    &lt;li&gt;Entity Framework Integration&lt;/li&gt;    &lt;li&gt;WPF based Text Editor&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;SSMS is my primary (and favorite) development environment and I am not sure whether I would ever like to switch to a different tool. I hope Juneau will not replace SSMS. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10520/what-is-sql-server-juneau.aspx</guid><pubDate>Mon, 07 Feb 2011 10:44:00 GMT</pubDate></item><item><title>What is SQL Server Crescent?</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10519/what-is-sql-server-crescent.aspx</link><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/b/sqlrsteamblog/archive/2010/11/09/a-glimpse-at-project-crescent.aspx" target="_blank"&gt;Project Crescent&lt;/a&gt; is a new data visualization tool that will be part of the next version of SQL Server – code named Denali. &lt;/p&gt;  &lt;p&gt;“Crescent” is the code name given to the new reporting/visualization tools and it looks like the name may change by the time the product is released. Crescent is expected to revolutionize ad-hoc reporting requirements by providing users new user experience and allow them to present the data in new and exciting ways.&amp;#160; &lt;/p&gt;  &lt;p&gt;Experts who got early access to Crescent says that Crescent expands the Self Service BI capabilities currently available with PowerPivot for Excel. Crescent provides drag-and-drop ad-hoc reporting capability. Crescent is not available with the current release of Denali (CTP1) but is expected to be part of CTP2. To see the list of new features available in Denali, visit: &lt;a title="http://beyondrelational.com/whatisnew/sqlserver/denali/" href="http://beyondrelational.com/whatisnew/sqlserver/denali/"&gt;http://beyondrelational.com/whatisnew/sqlserver/denali/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;What is more exciting is to know that &lt;a href="http://team.silverlight.net/announcement/project-crescent/" target="_blank"&gt;Crescent is entirely built on Silverlight&lt;/a&gt;. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10519/what-is-sql-server-crescent.aspx</guid><pubDate>Fri, 04 Feb 2011 15:52:00 GMT</pubDate></item><item><title>SSRS – How to find all the reports that use one or more given columns?</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10518/ssrs-how-to-find-all-the-reports-that-use-one-or-more-given-columns.aspx</link><description>&lt;p&gt;In the past I have published a few queries that allows you to query SQL Server Reporting Services database – to retrieve specific information about various reports deployed in the Reporting Server Instance.&lt;/p&gt; &lt;p&gt;Recently, I got a &lt;a href="http://beyondrelational.com/ask/jacob/questions/11/finding-all-reports-referencing-a-certain-fieldcolumn-on-report-server.aspx"&gt;question&lt;/a&gt; in my &lt;a href="http://beyondrelational.com/ask/jacob/questions/11/finding-all-reports-referencing-a-certain-fieldcolumn-on-report-server.aspx"&gt;ASK forum&lt;/a&gt; who wanted to identify all the reports that use a specific column. I thought of writing a blog post about it so that it can be added to the SSRS query series and help other people with similar problems.&lt;/p&gt; &lt;p&gt;The RDL file that gets generated when you design a report, is an XML document. When you deploy the report on Reporting Server, the RDL file (which is an XML document) gets inserted into the Report Server database (named ReportServer by default). You can query this database to obtain the XML content of all the reports and then use XQuery to read specific information about each report.&lt;/p&gt; &lt;p&gt;The following query demonstrates how to read all the columns used by all the reports in the given SQL Server Reporting Server instance and search for a specific column. The query given below returns the report name and data source name of all reports that references a specified column name – which is passed as a parameter.&lt;/p&gt;&lt;pre class="brush: sql"&gt;DECLARE @FieldToSearch VARCHAR(100)
SELECT @FieldToSearch = 'PatientNumber'

;WITH XMLNAMESPACES (
	DEFAULT 
	'http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition',
	'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd
)
SELECT
	name,
	d.value('@Name[1]', 'VARCHAR(50)') AS DataSetName,
	df.value('@Name[1]', 'VARCHAR(50)') AS ReportFieldName,
	df.value('DataField[1]', 'VARCHAR(50)') AS DataFieldName
FROM (
	select name, 
	CAST(CAST(content AS VARBINARY(MAX)) AS XML) AS reportXML
	from ReportServer.dbo.Catalog
	WHERE Type = 2
) a
CROSS APPLY reportXML.nodes('/Report/DataSets/DataSet') r(d)
CROSS APPLY d.nodes('Fields/Field') f(df)
WHERE df.exist('DataField[ . = sql:variable("@FieldToSearch")]') = 1
/*
Name          DataSetName   ReportFieldName  DataFieldName
------------  ------------  ---------------  ---------------
Patient List  DSPatients    PatientID        PatientNumber
AR Details    DSPatientsAR  PatientNumber    PatientNumber
*/
&lt;/pre&gt;
&lt;div class="lightbulb"&gt;The code given above is tested with SSRS 2005 SP2. It is expected to work on other versions, but I have not tested. If you find a problem running this query on other SSRS versions, let me know. &lt;/div&gt;
&lt;p&gt;I would recommend you read the following posts as well:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/01/16/how-to-find-all-stored-procedures-used-by-report-server.aspx"&gt;How to find all stored procedures used by Report Server?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/11/14/how-to-query-report-server-to-find-out-the-data-source-used-by-one-or-more-reports.aspx"&gt;How to query report server to find out the data source used by one or more reports?&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10518/ssrs-how-to-find-all-the-reports-that-use-one-or-more-given-columns.aspx</guid><pubDate>Fri, 21 Jan 2011 10:28:00 GMT</pubDate></item><item><title>Inviting everyone to participate in the .NET Quiz! An Apple iPad Waiting</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10517/inviting-everyone-to-participate-in-the-net-quiz-an-apple-ipad-waiting.aspx</link><description>&lt;p&gt;After the recent &lt;a href="http://beyondrelational.com/quiz/SQLServer/General/2010/default.aspx"&gt;SQL Server Quiz&lt;/a&gt; we got several requests to start a .NET quiz that follows the similar model. We have been working hard for the last couple of months and finally the .NET Quiz is Ready.&lt;/p&gt;  &lt;p&gt;The SQL Server Quiz was our first attempt in this area and we came to know about several stuff we are missing. One of the serious shortcoming was the user interface on the web pages. We have been working hard on rebuilding the quiz module and released a new version that goes live with the .NET Quiz. &lt;/p&gt;  &lt;p&gt;I invite all of you to take part in the &lt;a href="http://beyondrelational.com/quiz/dotnet/general/2011/default.aspx"&gt;.NET Quiz&lt;/a&gt;. The winner gets an Apple iPad (sponsored by &lt;a href="http://bit.ly/dVGSTY"&gt;Redgate&lt;/a&gt;). &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10517/inviting-everyone-to-participate-in-the-net-quiz-an-apple-ipad-waiting.aspx</guid><pubDate>Sat, 01 Jan 2011 11:23:00 GMT</pubDate></item><item><title>Storing TSQL Queries in a table without losing the formatting</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10516/storing-tsql-queries-in-a-table-without-losing-the-formatting.aspx</link><description>&lt;p&gt;One of the applications we worked on recently had to deal with storing TSQL queries in a table and executing them based on some business logic. It was not a very complicated project, but the development team had a tough time with the formatting of the queries stored in the table. This was a huge problem when the queries were to be modified. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The developer writes a well formatted TSQL code and stores it into the table. Later on when a change request comes, he retrieves the query text from the table and finds that all the formatting is lost. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Why does it happen?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Well, the formatting is not really lost. When the developer stores a well formatted query into the VARCHAR(MAX)/NVARCHAR(MAX) column of a table, the formatting is also stored. The problem is the way he retrieves it. &lt;/p&gt;  &lt;p&gt;The common way of retrieving the query text is to run a SELECT query which will display the result in a grid view. The grid view does not maintain the special characters (line feed, carriage return). That is the reason why you are loosing the formatting.&lt;/p&gt;  &lt;p&gt;An immediate workaround is to change the output to text and run the SELECT query. This works if the TSQL queries stored in the table are small. If the queries are large, then it might truncate the queries.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Workaround&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In this post, let us see a workaround that shows how to retrieve the query text without loosing the formatting. To see this in action, let us start by creating a table to store the queries.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;USE tempdb
GO

IF OBJECT_ID('BRQueries','U') IS NOT NULL BEGIN
	DROP TABLE BRQueries
END

CREATE TABLE BRQueries(
	QueryID INT, 
	QueryText VARCHAR(MAX)
)&lt;/pre&gt;

&lt;p&gt;Next, let us write a well formed query.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
   t.Name AS TableName,
   c.Name AS ColumnName
FROM sys.tables t
INNER JOIN sys.columns c ON
	t.object_id = c.object_id&lt;/pre&gt;

&lt;p&gt;Let us now insert this query into the table&lt;/p&gt;

&lt;pre class="brush: sql"&gt;INSERT INTO BRQueries (QueryID, QueryText)
SELECT 1, 
'
SELECT 
   t.Name AS TableName,
   c.Name AS ColumnName
FROM sys.tables t
INNER JOIN sys.columns c ON
	t.object_id = c.object_id'&lt;/pre&gt;

&lt;p&gt;Next, Let us run a SELECT query to retrieve the query text. If we use 'result to grid', we will loose the formatting. If we use 'result to text' we will get the correctly formatted text in this case. However, if the query is longer it might get truncated. If the table has several other columns and rows, the output will be completely messed up.&lt;/p&gt;

&lt;p&gt;A workaround is to use to use the XML function &lt;i&gt;processing-instruction()&lt;/i&gt;. Run the following query.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT
	QueryID,
	(
		SELECT QueryText AS 'processing-instruction(q)' 
		FROM BRQueries b
		WHERE b.QueryID = a.QueryID
		FOR XML PATH(''), TYPE
	) AS Query
FROM BRQueries a&lt;/pre&gt;

&lt;p&gt;Take the result of the query into a grid either by pressing CTRL+D or from the toolbar and you will see the result as follows: &lt;/p&gt;
&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/query_5F00_3F245F0A.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="query" border="0" alt="query" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/query_5F00_thumb_5F00_5CB63A09.png" width="474" height="86" /&gt;&lt;/a&gt; 

&lt;p&gt;Click on the desired row and it will open up the query text with the original formatting.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;?q 
SELECT 
   t.Name AS TableName,
   c.Name AS ColumnName
FROM sys.tables t
INNER JOIN sys.columns c ON
	t.object_id = c.object_id
?&amp;gt;&lt;/pre&gt;

&lt;p&gt;You can strip of the XML tags from the top and bottom of the query text and go ahead with editing. Well, this is not a 'great' method but a quick and dirty trick that might come handy at times. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10516/storing-tsql-queries-in-a-table-without-losing-the-formatting.aspx</guid><pubDate>Fri, 17 Dec 2010 14:49:00 GMT</pubDate></item><item><title>XQuery Lab 63 – Deleting empty elements from an XML document</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10515/xquery-lab-63-deleting-empty-elements-from-an-xml-document.aspx</link><description>&lt;p&gt;I saw this question on the forum today and after writing an example that demonstrates this, I thought of including it as part of the &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/06/26/xquery-labs-a-collection-of-xquery-sample-scripts.aspx"&gt;XQuery Labs&lt;/a&gt;. &lt;/p&gt; &lt;br/&gt; &lt;p&gt;Here is the sample XML we need to process.&lt;/p&gt; &lt;pre class="brush: html"&gt;
&amp;lt;userdata pageid=&amp;quot;page9&amp;quot; annotationSetId=&amp;quot;80&amp;quot;&amp;gt;
    &amp;lt;notes /&amp;gt;
    &amp;lt;notes&amp;gt;
      &amp;lt;note id=&amp;quot;332E7A17-3E57-3540-CC28-DFA1C68A7802&amp;quot; 
		x1=&amp;quot;297.25&amp;quot; x2=&amp;quot;297.25&amp;quot; y1=&amp;quot;447.85&amp;quot; y2=&amp;quot;447.85&amp;quot; 
		lastModified=&amp;quot;2010-12-13T12:08:32Z&amp;quot; type=&amp;quot;mynotes&amp;quot;&amp;gt;
      &amp;lt;/note&amp;gt;
    &amp;lt;/notes&amp;gt;
    &amp;lt;notes /&amp;gt;
    &amp;lt;notes /&amp;gt;
    &amp;lt;page_hotspots /&amp;gt;
  &amp;lt;/userdata&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The task is to delete all &lt;strong&gt;notes &lt;/strong&gt;elements that are empty and produce the following output.&lt;/p&gt;
&lt;pre class="brush: html"&gt;
&amp;lt;userdata pageid=&amp;quot;page9&amp;quot; annotationSetId=&amp;quot;80&amp;quot;&amp;gt;
  &amp;lt;notes&amp;gt;
    &amp;lt;note id=&amp;quot;332E7A17-3E57-3540-CC28-DFA1C68A7802&amp;quot; 
		x1=&amp;quot;297.25&amp;quot; x2=&amp;quot;297.25&amp;quot; y1=&amp;quot;447.85&amp;quot; y2=&amp;quot;447.85&amp;quot; 
		lastModified=&amp;quot;2010-12-13T12:08:32Z&amp;quot; type=&amp;quot;mynotes&amp;quot; /&amp;gt;
  &amp;lt;/notes&amp;gt;
  &amp;lt;page_hotspots /&amp;gt;
&amp;lt;/userdata&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Here is the TSQL code that deletes the empty elements using an XQuery expression. &lt;/p&gt;
&lt;pre class="brush: sql"&gt;
DECLARE @x XML
SELECT @x = '
&amp;lt;userdata pageid=&amp;quot;page9&amp;quot; annotationSetId=&amp;quot;80&amp;quot;&amp;gt;
    &amp;lt;notes /&amp;gt;
    &amp;lt;notes&amp;gt;
      &amp;lt;note id=&amp;quot;332E7A17-3E57-3540-CC28-DFA1C68A7802&amp;quot; 
		x1=&amp;quot;297.25&amp;quot; x2=&amp;quot;297.25&amp;quot; y1=&amp;quot;447.85&amp;quot; y2=&amp;quot;447.85&amp;quot; 
		lastModified=&amp;quot;2010-12-13T12:08:32Z&amp;quot; type=&amp;quot;mynotes&amp;quot;&amp;gt;
      &amp;lt;/note&amp;gt;
    &amp;lt;/notes&amp;gt;
    &amp;lt;notes /&amp;gt;
    &amp;lt;notes /&amp;gt;
    &amp;lt;page_hotspots /&amp;gt;
  &amp;lt;/userdata&amp;gt;'

SET @x.modify('
	delete /userdata/notes[empty(./*)]
')

SELECT @x

/*
&amp;lt;userdata pageid=&amp;quot;page9&amp;quot; annotationSetId=&amp;quot;80&amp;quot;&amp;gt;
  &amp;lt;notes&amp;gt;
    &amp;lt;note id=&amp;quot;332E7A17-3E57-3540-CC28-DFA1C68A7802&amp;quot; 
		x1=&amp;quot;297.25&amp;quot; x2=&amp;quot;297.25&amp;quot; y1=&amp;quot;447.85&amp;quot; y2=&amp;quot;447.85&amp;quot; 
		lastModified=&amp;quot;2010-12-13T12:08:32Z&amp;quot; type=&amp;quot;mynotes&amp;quot; /&amp;gt;
  &amp;lt;/notes&amp;gt;
  &amp;lt;page_hotspots /&amp;gt;
&amp;lt;/userdata&amp;gt;
*/
&lt;/pre&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;View All Labs: &lt;/b&gt;&lt;a href="http://beyondrelational.com/blogs/jacob/archive/2008/06/26/xquery-labs-a-collection-of-xquery-sample-scripts.aspx"&gt;XQuery Labs - A Collection of XQuery Sample Scripts and Tutorials&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10515/xquery-lab-63-deleting-empty-elements-from-an-xml-document.aspx</guid><pubDate>Tue, 14 Dec 2010 17:04:00 GMT</pubDate></item><item><title>SSMS Enhancement in SQL11 (Denali) – Support for Code Snippets</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10514/ssms-enhancement-in-sql11-denali-support-for-code-snippets.aspx</link><description>&lt;p&gt;Code snippets allow you to quickly insert code templates into your query window to perform common TSQL tasks. By using a keyword short cut you can invoke the code snippet window and select the desired code snippet. This will copy the pre-defined code template to your query with placeholders which clearly indicates the locations where you need to make changes.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Inserting a code snippet&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You can activate the code snippet window by using the keyboard shortcut &lt;strong&gt;CTRL+K&lt;/strong&gt; followed by &lt;strong&gt;CTRL+X&lt;/strong&gt;. Alternatively, you can select the &lt;em&gt;Insert Snippet.. &lt;/em&gt;menu item from the &lt;em&gt;Edit &amp;gt;&amp;gt; IntelliSense &lt;/em&gt;menu. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet1_5F00_6D5BB8C0.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="codesnippet1" border="0" alt="codesnippet1" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet1_5F00_thumb_5F00_5AB2D0D7.png" width="390" height="209" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Code snippets are organized by categories. Select a category to see the available code snippets under that category. For this example, let us select “Function”.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet2_5F00_2CE50812.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="codesnippet2" border="0" alt="codesnippet2" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet2_5F00_thumb_5F00_4AE31606.png" width="390" height="98" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Let us select “Create Inline Table Function” and SSMS will insert the code required to create a Table Valued Function to your query window at the current cursor position.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet3_5F00_336861D5.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="codesnippet3" border="0" alt="codesnippet3" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet3_5F00_thumb_5F00_51666FC9.png" width="277" height="187" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;After inserting the function template, SSMS will also highlight the placeholders that need to be modified. This will help you to identify the places you need to make changes. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Creating your own code snippet&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;SSMS comes with some pre-defined code snippets. It is quite easy to add your own code snippets to SSMS and speed up developing commonly used TSQL code. To do this, you need to create a .snippet file containing your code and register it with the Code Snippet Manager. A .snippet file is an XML file that follows a pre-defined schema.&lt;/p&gt;  &lt;p&gt;Let us create a TSQL code snippet to generate the basic code for a simple TRY-CATCH block. Here is the code that we will include in the new code snippet.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;BEGIN TRY
	-- Your code here
END TRY
BEGIN CATCH
	-- Your error handling here
	;THROW
END CATCH&lt;/pre&gt;

&lt;p&gt;Here is the code snippet file created for inserting the above code fragment.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;CodeSnippets xmlns=&amp;quot;http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet&amp;quot;&amp;gt;
  &amp;lt;CodeSnippet Format=&amp;quot;1.0.0&amp;quot;&amp;gt;
    &amp;lt;Header&amp;gt;
      &amp;lt;SnippetTypes&amp;gt;
        &amp;lt;SnippetType&amp;gt;Expansion&amp;lt;/SnippetType&amp;gt;
      &amp;lt;/SnippetTypes&amp;gt;
      &amp;lt;Title&amp;gt;try-catch&amp;lt;/Title&amp;gt;
      &amp;lt;Author&amp;gt;jacob&amp;lt;/Author&amp;gt;
      &amp;lt;Description&amp;gt;
      &amp;lt;/Description&amp;gt;
      &amp;lt;HelpUrl&amp;gt;
      &amp;lt;/HelpUrl&amp;gt;
      &amp;lt;Shortcut&amp;gt;
      &amp;lt;/Shortcut&amp;gt;
    &amp;lt;/Header&amp;gt;
    &amp;lt;Snippet&amp;gt;
      &amp;lt;Code Language=&amp;quot;sql&amp;quot;&amp;gt;&amp;lt;![CDATA[
		BEGIN TRY
			-- Your code here
		END TRY
		BEGIN CATCH
			-- Your error handling here
			;THROW
		END CATCH
		]]&amp;gt;
	  &amp;lt;/Code&amp;gt;
    &amp;lt;/Snippet&amp;gt;
  &amp;lt;/CodeSnippet&amp;gt;
&amp;lt;/CodeSnippets&amp;gt;&lt;/pre&gt;

&lt;p&gt;There are several tools available that will allow you to create code snippets easily. One such tool is &lt;a href="http://snippetdesigner.codeplex.com"&gt;Snippet Designer&lt;/a&gt; available at codeplex. This allows you to create code snippets right within visual studio. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Registering a code snippet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After creating a code snippet file, you need to register it with SSMS. This can be done using the “Code Snippet Manager”. Launch the “Code Snippet Manager” from the “Tools” menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet4_5F00_08604E03.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="codesnippet4" border="0" alt="codesnippet4" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet4_5F00_thumb_5F00_5AFEB832.png" width="342" height="188" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This will open the code snippet manager window.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet5_5F00_7FAFCFA9.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="codesnippet5" border="0" alt="codesnippet5" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet5_5F00_thumb_5F00_7456959F.png" width="390" height="291" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The Code Snippet Manager shows all the code snippets registered with SSMS. You can use the &lt;strong&gt;Add&lt;/strong&gt; and &lt;strong&gt;Remove&lt;/strong&gt; buttons to register new code snippets or remove the code snippets already registered.&lt;/p&gt;

&lt;p&gt;Let us register the code snippet we created in the previous step. Click on the &lt;strong&gt;Add &lt;/strong&gt;button and select the folder where you have put your code snippet files. After selecting the code snippet folder, all the code snippets available within the selected folder will show up on the Code Snippet Manager.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet6_5F00_7AF97955.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="codesnippet6" border="0" alt="codesnippet6" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet6_5F00_thumb_5F00_16DA8881.png" width="390" height="291" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing the newly added code snippet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is time for us to test the code snippet we just created and registered. Switch back to SSMS query window and press &lt;strong&gt;CTRL+K, CTRL+X&lt;/strong&gt; and it will open the code snippet prompt as given below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet7_5F00_574D2530.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="codesnippet7" border="0" alt="codesnippet7" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet7_5F00_thumb_5F00_5CBB95D4.png" width="390" height="64" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Select the code snippet “try-catch” and it will insert the TSQL code we placed within the snippet file at the current cursor position within the SSMS query window.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet8_5F00_28A6F681.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="codesnippet8" border="0" alt="codesnippet8" src="http://beyondrelational.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jacob/codesnippet8_5F00_thumb_5F00_4711376A.png" width="247" height="139" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The code given above is very basic and used for the demonstration purpose only. You might end up creating more complex code snippets in most real world scenarios. The &lt;a href="http://snippetdesigner.codeplex.com"&gt;Snippet Designer&lt;/a&gt; tool mentioned earlier is quite capable of creating code snippets for Visual Studio as well as SSMS.&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10514/ssms-enhancement-in-sql11-denali-support-for-code-snippets.aspx</guid><pubDate>Sat, 20 Nov 2010 08:28:00 GMT</pubDate></item><item><title>TSQL Error Handling Enhancements in SQL11 – Using the THROW command</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10513/tsql-error-handling-enhancements-in-sql11-using-the-throw-command.aspx</link><description>&lt;p&gt;One of the most interesting error handling enhancements added in SQL Server 2005 is the support for structured exception handling using TRY / CATCH blocks. This reduced the complexity of error handling in TSQL significantly. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Exception Handling using TRY/CATCH&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Exception handling using TRY/CATCH is very much similar to how it is done in other programming languages. You put your code between a BEGIN TRY and END TRY block and write the error handling code within the BEGIN CATCH and END CATCH block. Here is a very basic example that shows structured exception handling in TSQL using TRY/CATCH.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;BEGIN TRY
	SELECT 1/0
END TRY
BEGIN CATCH
	PRINT 'Error: ' + ERROR_MESSAGE()
	PRINT 'Number: ' + CAST(ERROR_NUMBER() AS VARCHAR)
END CATCH
/*
Error: Divide by zero error encountered.
Number: 8134
*/&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Throwing a Database Error to the Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most serious applications handle data access errors in the application as well as in the database. Database developers will put their code within TRY/CATCH blocks and log the error details into a table for offline analysis. &lt;/p&gt;

&lt;p&gt;Some of the database errors may be relevant to the application developers as well. For example, if an error is raised due to an incorrect value being passed into the stored procedure, the application developers need to know about it. In such a case, the database developer might need to throw the error back the application after doing the database level error logging.&lt;/p&gt;

&lt;p&gt;Here is an example that shows how to do this.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;BEGIN TRY
	SELECT 1/0
END TRY
BEGIN CATCH
	DECLARE @errn INT = ERROR_NUMBER()
	DECLARE @errm VARCHAR(500) = ERROR_MESSAGE()
	RAISERROR('Error Number: %d, Message: %s', 16, 1, @errn, @errm)
END CATCH
/*
Msg 50000, Level 16, State 1, Line 7
Error Number: 8134, Message: Divide by zero error encountered.
*/&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Problems with RAISERROR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RAISERROR, like any other function/command has got its own set of capabilities and shortcomings. One relatively small problem I found with RAISERROR is the inability to RAISE the same error after catching it in a CATCH block. In the above example, note that the error caught in the CATCH block was 8134. There is no way to RE-RAISE the same error using RAISERROR. If you attempt to raise an error with Error Number 8134 (or other system error numbers), you will get an error as shown in the following example.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;BEGIN TRY
	SELECT 1/0
END TRY
BEGIN CATCH
	DECLARE @errn INT = ERROR_NUMBER()
	DECLARE @errm VARCHAR(500) = ERROR_MESSAGE()
	RAISERROR(8134, 16, 1)
END CATCH
/*
Msg 2732, Level 16, State 1, Line 7
Error number 8134 is invalid. The number must be from 13000 through 2147483647 and it cannot be 50000.
*/&lt;/pre&gt;

&lt;p&gt;Another problem is that when re-raising an error using RAISERROR, you loose the original error line number. In the example that we saw in the previous section, the actual error occurred on line 2, but when RAISERROR is called, the error line is reset to the current line number (7). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter THROW &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;THROW is a new command introduced in SQL11 (Denali) and it helps you to overcome the limitations we saw above. After performing your error handling within the CATCH block, you can use the THROW command to re-throw the same error to the calling procedure/application.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;BEGIN TRY
	SELECT 1/0
END TRY
BEGIN CATCH
	PRINT 'Error Number: ' + CAST(ERROR_NUMBER() AS VARCHAR)
	PRINT 'Error Line: ' + CAST(ERROR_LINE() AS VARCHAR)
	PRINT 'Throwing error...';
	THROW
END CATCH
/*
Error Number: 8134
Error Line: 2
Throwing error...

Msg 8134, Level 16, State 1, Line 2
Divide by zero error encountered.
*/&lt;/pre&gt;

&lt;p&gt;Note that the same error number and line number is propagated when using the THROW command. It is important to note that the THROW command should be issued as a new batch and therefore you need to terminate the previous batch by placing a semi colon before THROW.&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10513/tsql-error-handling-enhancements-in-sql11-using-the-throw-command.aspx</guid><pubDate>Wed, 17 Nov 2010 15:47:00 GMT</pubDate></item><item><title>SQL Server 2011 (SQL11 / Denali) – TSQL Enhancements to the ORDER BY clause</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10512/sql-server-2011-sql11-denali-tsql-enhancements-to-the-order-by-clause.aspx</link><description>&lt;p&gt;In the &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2010/11/14/tsql-enhancements-in-sql11-sql-server-2011-denali-to-support-server-side-paging.aspx"&gt;previous post&lt;/a&gt;, we saw the new TSQL syntax introduced in SQL Server 2011 to support server side paging. We saw the new TSQL keywords &lt;strong&gt;OFFSET&lt;/strong&gt; and &lt;strong&gt;FETCH NEXT&lt;/strong&gt; in the previous post. These new keywords are introduced as an extension to the ORDER BY clause. Let us examine them in detail.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;OFFSET &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;OFFSET specifies the number of rows to skip before start retrieving the rows. This is evaluated after sorting the result set using the columns specified in the ORDER BY clause. &lt;/p&gt;  &lt;p&gt;What is very interesting about OFFSET is that, you can specify a variable along with it. This is helpful to write generic handlers where the page size and current page number are passed as parameters. &lt;/p&gt;  &lt;pre class="brush: sql"&gt;DECLARE @offset INT
SELECT @offset = 10
SELECT 
	*
FROM @t 
ORDER BY CustID  
OFFSET @offset ROWS 
FETCH NEXT 10 ROWS ONLY;&lt;/pre&gt;

&lt;p&gt;It can also be a function, subquery or a valid TSQL expression that returns 0 or a positive integer value. If the expression returns a negative value or NULL, the query will fail with an error.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
	*
FROM @t 
ORDER BY CustID  
OFFSET (SELECT offset FROM sometable) ROWS 
FETCH NEXT 10 ROWS ONLY;&lt;/pre&gt;

&lt;p&gt;OFFSET is followed by ROWS or ROW. You can use either one of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FETCH NEXT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FETCH can be used with either FIRST or NEXT and they have the same meaning. NEXT or FIRST is followed by the number of rows to retrieve. The number can be a constant value, result of a query or an expression. Here is an example that uses a sub-query to specify the number of rows to retrieve.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
	*
FROM @t 
ORDER BY CustID  
OFFSET (SELECT offset FROM setuptable) ROWS 
FETCH NEXT (SELECT pagesize FROM setuptable) ROWS ONLY;&lt;/pre&gt;

&lt;p&gt;The expression (or sub-query) should return a positive integer value that is greater than 0. If 0, NULL or a negative value is specified the query will fail with an error.&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10512/sql-server-2011-sql11-denali-tsql-enhancements-to-the-order-by-clause.aspx</guid><pubDate>Mon, 15 Nov 2010 23:44:00 GMT</pubDate></item><item><title>TSQL Enhancements in SQL11 (SQL Server 2011 / Denali) to support Server Side Paging</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10511/tsql-enhancements-in-sql11-sql-server-2011-denali-to-support-server-side-paging.aspx</link><description>&lt;p&gt;Server Side Paging is a common scenario most application developers must have encountered while creating front end applications that requires paging support. Instead of returning all the rows from the database and implement paging at the client side, you might want to implement the paging on the server side so that only those rows needed for the current page are retrieved from the server. This reduces the pressure on the database server as well as help the client application to perform better.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Writing a paging Query&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;By writing a paging query, we are essentially telling the database engine something like the following:&lt;/p&gt;  &lt;pre class="brush: plain"&gt;/*
My application displays 10 rows on a page and I want 
data to display on page 3. 

Send me rows 21 to 30 after ordering the customer table
by Customer ID
*/&lt;/pre&gt;

&lt;p&gt;The TSQL representation of the above query is as follows&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
	*
FROM @t 
ORDER BY CustID  
OFFSET 20 ROWS 
FETCH NEXT 10 ROWS ONLY;&lt;/pre&gt;

&lt;p&gt;Here is a fully functional sample code that you can run on a SQL Server Denali (2011) instance. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Create a table
DECLARE @t TABLE (
	CustID INT IDENTITY,
	CustName VARCHAR(100) )

-- Populate some data
INSERT INTO @t (CustName)
SELECT 'Customer ' + CAST(Number AS VARCHAR)
FROM master..spt_values WHERE type = 'p' AND number BETWEEN 1 and 100

-- Write the query
SELECT 
	*
FROM @t 
ORDER BY CustID  
OFFSET 20 ROWS 
FETCH NEXT 10 ROWS ONLY;

/*
CustID      CustName
----------- -------------
21          Customer 21
22          Customer 22
23          Customer 23
24          Customer 24
25          Customer 25
26          Customer 26
27          Customer 27
28          Customer 28
29          Customer 29
30          Customer 30
*/&lt;/pre&gt;

&lt;p&gt;See &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2010/08/06/sql-server-2005-server-side-paging-with-row-number-function.aspx"&gt;this article&lt;/a&gt; that explains how to implement Server Side Paging in SQL Server 2005/2008/R2. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10511/tsql-enhancements-in-sql11-sql-server-2011-denali-to-support-server-side-paging.aspx</guid><pubDate>Sun, 14 Nov 2010 20:52:00 GMT</pubDate></item><item><title>Are you ready for SQL Server Quiz 2010?</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10510/are-you-ready-for-sql-server-quiz-2010.aspx</link><description>&lt;p&gt;If you like to win an iPad, Amazon Kindle, iPod or software licenses worth over $20,000, it is time to get ready for the upcoming &lt;a href="http://beyondrelational.com/quiz/sqlserver/general/2010/default.aspx"&gt;SQL Server Quiz 2010&lt;/a&gt;. Brush up your SQL Server skills and win your favorite gadgets and software tools.&lt;/p&gt;  &lt;p&gt;Even if you already have those gadgets and software tools, you might still find the SQL Server Quiz interesting, because there will be considerable in-depth discussion and learning you can gain from this series. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What is SQL Server Quiz?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;SQL Server Quiz is a platform to verify your understanding of SQL Server and enhance your SQL Server skills. Through SQL Server Quiz, we bring a series of questions on various SQL Server topics and will provide a platform for discussing, explaining and understanding the related SQL Server areas. &lt;/p&gt;  &lt;p&gt;SQL Server Quiz 2010 is a series of 31 questions, managed by 31 quiz masters who are experts in SQL Server. Each quiz master will ask one question each and will moderate the discussions and answers and finally will identify the winner of each quiz. Each answer that is correct will get a certain score (between 1 and 10, where 10 is the best) the scores of all the 31 questions will be added up to identify the final winner. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Quiz Home Page: &lt;a href="http://beyondrelational.com/quiz/sqlserver/general/2010/default.aspx"&gt;http://beyondrelational.com/quiz/sqlserver/general/2010/default.aspx&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Prizes: &lt;a href="http://beyondrelational.com/quiz/sqlserver/general/2010/prizes.aspx"&gt;http://beyondrelational.com/quiz/sqlserver/general/2010/prizes.aspx&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;FAQ: &lt;a href="http://beyondrelational.com/quiz/sqlserver/general/2010/faq.aspx"&gt;http://beyondrelational.com/quiz/sqlserver/general/2010/faq.aspx&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I look forward to see many of you actively participating in the discussions and win some of these prizes.&lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10510/are-you-ready-for-sql-server-quiz-2010.aspx</guid><pubDate>Thu, 30 Sep 2010 09:38:00 GMT</pubDate></item><item><title>SQL Server - Server-side paging with Row_number() function</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10434/sql-server-server-side-paging-with-rownumber-function.aspx</link><description>&lt;p&gt;If you are a programmer working with SQL Server, you must have found it little embarrassing to display information which spans across multiple pages (web pages). SQL Server 2000 did not allow you to retrieve a specific range of records, say, records 51 to 100 ordered by a certain column. &lt;/p&gt;

&lt;p&gt;For example, assume that you are working on a web page which lists the names of all the cities in different countries. Assume that you need to display 25 records in a page. The database has 50,000 records consisting all the cities/towns across the globe. In the above scenario, it really makes sense to retrieve only the required records. for example, in the first page, retrieve 1 to 25 records. When the user clicks on &amp;quot;next&amp;quot; button, retrieve records 26 to 50 and so on. at this stage the user might click on another column to change the sort order. Earlier it was ordered by city name but now the display is based on Zip code. &lt;/p&gt;

&lt;p&gt;With SQL Server 2000, it was not very easy to achieve this. Some times people used temp tables achieve this. Others put the paging responsibility to the application which retrieved all the records and then displayed the information needed for the current page. (this approach will not only overload server resources, but also degrades performance of the application as well as the database server.)&lt;/p&gt;

&lt;p&gt;SQL Server 2005 introduces a helpful function ROW_NUMBER() which helps in this scenario. Using ROW_NUMBER()&amp;#160; you can generate a sequence number based on a given sort order and then select specific records from the results. Here is an example:&lt;/p&gt;

&lt;pre class="brush: sql"&gt;ROW_NUMBER() OVER (ORDER BY City) as Seq&lt;/pre&gt;

&lt;p&gt;The syntax ideally says the following. &amp;quot;Order the records by City, and then assign a serial number to each record&amp;quot;. You can use it in a query as follows. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
     ROW_NUMBER() OVER (ORDER BY City) AS row, 
     CityName, 
     Zip, 
     Country 
FROM Cities&lt;/pre&gt;

&lt;p&gt;However, filtering the records is a little tricky. A TSQL statement like the following will not work. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
     ROW_NUMBER() OVER (ORDER BY City) AS row, 
     CityName, 
     Zip, 
     Country 
FROM Cities 
WHERE row BETWEEN 25 AND 50&lt;/pre&gt;

&lt;p&gt;Again, using the ROW_NUMBER directly inside the WHERE clause does not work (as shown below) &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
     ROW_NUMBER() OVER (ORDER BY City) AS row, 
     CityName, 
     Zip, 
     Country 
FROM Cities 
WHERE ( ROW_NUMBER() OVER (ORDER BY City) AS row ) BETWEEN 50 BETWEEN 75 &lt;/pre&gt;

&lt;p&gt;One option is to use an inner query: &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT * FROM ( 
     SELECT 
          ROW_NUMBER() OVER (ORDER BY City) AS row, * 
     FROM Cities 
) AS a WHERE row BETWEEN 101 AND 125&lt;/pre&gt;

&lt;p&gt;The inner query creates a sub-table and then the outer query filters the records from the inner result set. ROW_NUMBER() is a function that I had been waiting for so long and am glad to find with the version 2005 of SQL Server. As the SQL Server Team celebrates the 17th Anniversary this year, I would really like to congratulate them. &lt;/p&gt;

&lt;p&gt;&lt;u&gt;Edit on 16 June 2008&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;It is almost 2 years since I wrote the above post. I had been learning SQL Server 2005 for the last few years (Still learning uh!) and wrote a few articles and blog posts on the new features introduced by SQL Server 2005. One of the articles that is close to the subject discussed here is &amp;quot;&lt;a href="http://www.sqlservercentral.com/articles/Advanced+Querying/3181/" target="_blank"&gt;Server side paging with SQL Server 2005&lt;/a&gt;&amp;quot;. This article closely examines the problems related to server-side-paging and then demonstrates a few examples that implements this.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Edit on 31 July 2010&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;SQL Server CE 4.0 introduced a new TSQL extension that makes paging queries much easier. For example, to fetch rows 21 to 30, a query can be written like this.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT 
   * 
FROM Orders 
ORDER BY OrderID 
OFFSET 20 ROWS 
FETCH NEXT 10 ROWS ONLY;&lt;/pre&gt;

&lt;p&gt;See &lt;a href="http://beyondrelational.com/blogs/jacob/archive/2010/07/13/support-for-paging-queries-in-sql-server-ce-4-0.aspx"&gt;Support for Paging Queries in SQL Server CE 4.0&lt;/a&gt; for more details of this feature. I hope this feature will be part of the next SQL Server release.&lt;/p&gt;
&lt;div class="InlineAdBox"&gt;
First published on May 29, 2006
&lt;/div&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10434/sql-server-server-side-paging-with-rownumber-function.aspx</guid><pubDate>Fri, 06 Aug 2010 06:38:00 GMT</pubDate></item><item><title>Tips and Tricks for Error Handling in ASP.NET Web Applications</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10435/tips-and-tricks-for-error-handling-in-aspnet-web-applications.aspx</link><description>&lt;p&gt;Error handling is very important for any serious application. It is very crucial that the application is capable of detecting the errors and take corrective measures to the maximum possible extend. If the error situation is beyond the control of the application, it should report the situation to the user/administrator so that an external action can be taken. &lt;/p&gt;

&lt;p&gt;The following are the most common ways of handling exceptions in an ASP.NET web application.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Structured Exception Handling &lt;/li&gt;

  &lt;li&gt;Error Events &lt;/li&gt;

  &lt;li&gt;Custom Error Pages &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Structured Exception Handling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most popular error handling is Structured Exception Handling (SEH). Most of us are familiar with it in the form of &lt;i&gt;try..catch&lt;/i&gt; blocks. All of us use SEH a lot in whatever application that we are working on. The primary focus of SEH is to make sure that a block of code is executed correctly, and if an exception takes place, we have another piece of code which can take care of the exception and take some corrective measures if possible. &lt;/p&gt;

&lt;p&gt;SEH is used to protect the application from an exceptional situation where something unexpected happens. For example the application tries to connect to a database server and the server is not available. It is an exceptional situation or an exception :-). If such a case happens the developer can handle the situation in the &lt;i&gt;catch&lt;/i&gt; block and take the necessary action. I have seen smart developers making use of SEH for the application logic too. for example, assume that the developer needs to open a file and display the content. Ideally he needs to check if the file exists first and then if it exists open it as follows. (This kind of programming is called DEFENSIVE Programming). &lt;/p&gt;

&lt;pre class="brush: plain"&gt;If file exists    
    work with the file 
else    
   take action 
end if &lt;/pre&gt;

&lt;p&gt;But the developer can simply use a try..catch block to open the file without even checking if the file exists as &lt;/p&gt;

&lt;pre class="brush: plain"&gt;try    
     just work with the file 
catch 
     file-does-not-exist-exception    
     take action 
end try &lt;/pre&gt;

&lt;p&gt;The above approach reduces the complexity of checking for the existing of the file etc. However it adds some overhead to the system. Generating and handling an exception takes some system resources. I have also seen people using SEH to branch the code execution to a specific upper function block, from inside a series of complex nested functions. &lt;/p&gt;

&lt;p&gt;For example function a calls b and b calls c and c calls d and d calls e and if the developer wants to transfer control to a specific location in any of the parent methods, he or she can make use of SEH. SEH is mostly used for procedure/function level error handling. Any code which access external resources like database connections, files/folders, URLs should always be inside &lt;i&gt;try..catch&lt;/i&gt; blocks because they are most vulnerable for exceptions. &lt;/p&gt;

&lt;p&gt;I have experienced a lot of trouble with combo boxes too and hence would recommend that any action that you do on a combo box should be inside try/catch blocks. Another area where you might consider is working with a dataaset where a null value can cause an exception. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Events&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of the times we will be able to put the code into &lt;i&gt;try..catch &lt;/i&gt;blocks. But exceptions occurs in exceptional situations. There might be several cases when we would not be able to fore-see that a given block code is vulnerable to a specific exception. &lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;pre class="brush: vb"&gt;dim CustomerName as string = new string(&amp;quot;jacob&amp;quot;) &lt;/pre&gt;

&lt;p&gt;The above statement is not a candidate for an error. No one would expect that the above statement can generate an error. But what if the system memory is full? The system is not able to allocate memory for that variable and it will throw an exception. Is it practical to put every line of code in &lt;i&gt;try..catch&lt;/i&gt; blocks and catch every possible exception with every line of code? Of course not. &lt;/p&gt;

&lt;p&gt;The best idea is to use Error Events of ASP.NET to handle such exceptions. Error events can be used to catch exceptions which are not handled with SEH. Asp.net provides three events to handle error conditions. &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;a. page_error &lt;/li&gt;

  &lt;li&gt;b. global_error &lt;/li&gt;

  &lt;li&gt;c. application_error &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can write excpetion handling code in &lt;i&gt;page_error &lt;/i&gt;to handle any un-handled exceptions that occur inside your page. similarly &lt;i&gt;global_error&lt;/i&gt; and &lt;i&gt;application_error&lt;/i&gt; can be used for application-wide error handling. From within the error event (page_error, global_error or application_error) you need to find the exception which occured. &lt;i&gt;Server.GetLastError()&lt;/i&gt; can be used to retrieve the exception which triggered the error. After you have processed the error, you should call &lt;i&gt;Server.ClearError()&lt;/i&gt; so that the further exception processing/handlers are not called. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Error Pages &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yet another way you can handle errors in ASP.NET Web applications is by using Custom Error pages. When an exception occurs you can redirect the user to a customized page which explains the error condition or just give a friendly note to the user. The scope of Custom error page is very much large that it can even detect errors which are not related to the web application. For example, if your web application is down, still you can instruct IIS to show the user a specific page. &lt;/p&gt;

&lt;p&gt;Custom error pages can be configured in 3 different ways. &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;1. Configure the custom error page with IIS &lt;/li&gt;

  &lt;li&gt;2. Configure the custom error page with web.config &lt;/li&gt;

  &lt;li&gt;3. Configure the custom error page declaratively in each web form &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&amp;#160;&lt;b&gt;Configuring a custom error page with IIS&lt;/b&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://photos1.blogger.com/blogger/4779/3059/1600/customerror.jpg"&gt;&lt;img style="display: inline; cursor: hand" border="0" src="http://photos1.blogger.com/blogger/4779/3059/320/customerror.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;You can configure a custom error page with IIS by opening the properties window of your application.&amp;#160; Custom error pages in IIS work based on HTTP response codes. you can define a custom page for each HTTP error that you need to handle. The question &amp;quot;which error code should I handle&amp;quot; largely depends on your application. However, I think the following HTTP response codes may be handled in a normal web application. &lt;i&gt;HTTP 401 - Unauthorized&lt;/i&gt; &lt;i&gt;HTTP 404 - Page Not Found&lt;/i&gt; &lt;i&gt;HTTP 408 - Request Timeout&lt;/i&gt; &lt;i&gt;HTTP 500 - Internal Server Error&lt;/i&gt; &lt;i&gt;HTTP 503 - Server Not Available&lt;/i&gt; &lt;i&gt;&lt;/i&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Configuring Custom Error Pages in Web.Config&lt;/b&gt; &lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;&lt;/i&gt;&lt;/b&gt;The &lt;i&gt;&lt;customerrors&gt;&lt;/customerrors&gt;&lt;/i&gt;section if web.config can be used to configure error pages. The following example shows a typical example.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;customerrors defaultredirect=&amp;quot;Error.aspx&amp;quot; mode=&amp;quot;on&amp;quot;&amp;gt;    
     &amp;lt;error redirect=&amp;quot;PageNotFound.aspx&amp;quot; statuscode=&amp;quot;404&amp;quot; /&amp;gt;    
     &amp;lt;error redirect=&amp;quot;InternalServerErr.aspx&amp;quot; statuscode=&amp;quot;500&amp;quot; /&amp;gt; 
&amp;lt;/customerrors&amp;gt;&lt;/pre&gt;

&lt;p&gt;Note: Custom error handling using web.config is applicable to ASP.NET resources only. For example, if a &amp;quot;page not found&amp;quot; error occurs with an aspx file, your custom error page will be displayed. However if a &amp;quot;page not found&amp;quot; error occurs for an html file, your application's error handler page will not be launched. To handle situations external to the web application, the setting needs to be configured with IIS. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Page Level Error Configuration&lt;/b&gt; &lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;The error configuration on web.config has application wide scope. However, it is possible to configure the error pages for a given web form. You can specify error pages declaratively on your web form as shown in the following example. &lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;%@ page 
    language=&amp;quot;vb&amp;quot; 
    AutoEventWireup=&amp;quot;false&amp;quot; 
    codebehind=&amp;quot;pagename.aspx.vb&amp;quot; 
    inherits=&amp;quot;projectname.pagename&amp;quot; 
    errorPage=&amp;quot;Error.aspx&amp;quot; %&amp;gt; 
&lt;/pre&gt;

&lt;p&gt;Setting on the web page supersedes the configuration setting on the web.config. In the above example, if an error occurs inside the above page (pagename.aspx) the user will be taken to &amp;quot;error.aspx&amp;quot; which might contain the details of the page. You can use Server.GetLastError() to identify the exception and can display an appropriate message to the user. &lt;/p&gt;

&lt;p&gt;Hope this helps&lt;/p&gt;
&lt;div class="InlineAdBox"&gt;
First published on 27 June 2006
&lt;/div&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10435/tips-and-tricks-for-error-handling-in-aspnet-web-applications.aspx</guid><pubDate>Thu, 05 Aug 2010 01:00:00 GMT</pubDate></item><item><title>SQL Server FILESTREAM feature and Differential Backups</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10509/sql-server-filestream-feature-and-differential-backups.aspx</link><description>&lt;p&gt;This post tries to explain the behavior of differential backups on a FILESTREAM enabled database. A number of times, I see questions looking for a confirmation whether Differential Backups will correctly backup the NTFS (FILESTREAM) files and restore them correctly when a differential backup is restored. &lt;/p&gt;  &lt;p&gt;A differential backup of a FILESTREAM enabled database will include the FILESTREAM data files as well. When the differential backup is restored, the FILESTREAM data files will be restored on the target location. Here is a set of TSQL scripts to demonstrate this.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Creating a FILESTREAM Enabled Database&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let us start by creating a FILESTREAM enabled database. Here is the script to create the database.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;-- Create a FILESTREAM enabled Database
CREATE DATABASE NorthPole ON
PRIMARY (
    NAME = NorthPoleDB,
    FILENAME = 'C:\Demos\NorthPoleDB.mdf'
), FILEGROUP NorthPoleFS CONTAINS FILESTREAM(
    NAME = NorthPoleFS,
    FILENAME = 'C:\Demos\FS\NorthPoleFS')
LOG ON (
    NAME = NorthPoleLOG,
    FILENAME = 'C:\Demos\NorthPoleLOG.ldf')
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Creating a table with a FILESTREAM column&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the following script to create a table with a FILESTREAM column.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Set context to the newly created DB
USE NorthPole
GO
-- Create &amp;quot;Items&amp;quot; table
CREATE TABLE [dbo].[Items](
   [ItemID] UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,
   [ItemImage] VARBINARY(MAX) FILESTREAM NULL
)
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Insert Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let us insert a record into the table we just created.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Insert 1 row into the table
INSERT INTO Items (ItemID, ItemImage)
SELECT NEWID(), CAST(1 AS VARBINARY(MAX))&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Taking a FULL Backup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let us now take a FULL BACKUP of the database we just created. Run the following script to take a FULL backup.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Take a Backup
BACKUP DATABASE NorthPole 
TO DISK = 'C:\Demos\NorthPoledb_Full.bak'
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Restoring the FULL Backup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let us go ahead and restore the FULL backup we took in the previous step. Let us create a new database from the backup. Since we intend to restore differential backups later on, let us keep the database in recovery mode.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Restore
RESTORE DATABASE NorthPole2
FROM DISK = N'C:\demos\NorthPoledb_Full.bak'
WITH NORECOVERY,
MOVE 'NorthPoleDB' TO 'C:\Demos\NorthPole2DB.mdf',
MOVE 'NorthPoleLOG' TO 'C:\Demos\NorthPole2LOG.ldf',
MOVE 'NorthPoleFS' TO 'C:\Demos\FS\NorthPole2FS', FILE=1&lt;/pre&gt;

&lt;p&gt;Once the database is restored, go to the FILESTREAM data folder and you will notice that the folder contains only one file. This is exactly what we had in the primary database at the time of taking the FULL backup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Populating more data into the PRIMARY database&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;let us go back to the primary database and populate the FILESTREAM table with more rows. Run the following script that will add 4 more rows to the table. This will also generate 4 more FILESTREAM data files in the FILESTREAM data container.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Insert 4 more rows into the table
WHILE (SELECT COUNT(*) FROM Items) &amp;lt; 5 BEGIN
	INSERT INTO Items (ItemID, ItemImage)
	SELECT NEWID(), CAST(1 AS VARBINARY(MAX))
END&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Taking a Differential Backup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is time to take a differential backup. Run the following script to take a differential backup. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Take a differential backup 
BACKUP DATABASE NorthPole 
TO DISK = 'C:\Demos\NorthPoledb_Diff.bak'
WITH DIFFERENTIAL
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Restoring the Differential Backup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let us now restore the differential backup on the secondary database. After restoring the full backup, we have added 4 more rows to the &lt;em&gt;Items &lt;/em&gt;table in the source database. The differential backup is expected to contain those 4 rows along with the associated FILESTREAM data files. After we restore the differential backup, we should have 5 rows in the &lt;em&gt;Item&lt;/em&gt;&amp;#160; table and 5 files in the FILESTREAM data container.&lt;/p&gt;

&lt;p&gt;Run the following script to restore the differential backup.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;RESTORE DATABASE NorthPole2 
FROM DISK = 'C:\Demos\NorthPoledb_Diff.bak' 
WITH RECOVERY
GO&lt;/pre&gt;
&lt;P&gt;
After restoring the differential backup, you can verify that the FILESTREAM data files are correctly restored by doing one of the following.
&lt;/P&gt;
&lt;ul&gt;
&lt;li&gt;Run a SELECT query on the &lt;i&gt;Items&lt;/i&gt; table and you will see that there are 5 rows and all the 5 rows have FILESTREAM data in it.&lt;/li&gt;
&lt;li&gt;Go to the FILESTREAM folder and you can see that there are 5 FILESTREAM data files. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Conclusions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This post tries to demonstrate that a differential backup of a FILESTREAM enabled database contains the FILESTREAM data files too. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10509/sql-server-filestream-feature-and-differential-backups.aspx</guid><pubDate>Wed, 04 Aug 2010 05:29:00 GMT</pubDate></item><item><title>Getting started with PIVOT Queries in SQL Server 2005/2008</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10362/getting-started-with-pivot-queries-in-sql-server-20052008.aspx</link><description>&lt;p&gt;This post intends to help TSQL developers get started with PIVOT/CROSS TAB queries. Most business applications will need some sort of PIVOT queries and I am sure many of you must have come across pivoting requirements several times in the past.&lt;p&gt;

&lt;p&gt; Let us say for example we need a result set as following &lt;/p&gt;

&lt;p&gt;&lt;a href="http://photos1.blogger.com/blogger/4779/3059/1600/pivotresult.0.jpg"&gt;&lt;img style="margin: 0px 10px 10px 0px; float: left; cursor: hand" title="SQL Server PIVOT example" border="0" alt="SQL Server PIVOT example" src="http://photos1.blogger.com/blogger/4779/3059/400/pivotresult.jpg" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;from a table which has data as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://photos1.blogger.com/blogger/4779/3059/1600/PivotTableData.jpg"&gt;&lt;img style="margin: 0px 10px 10px 0px; display: inline; cursor: hand" title="SQL Server PIVOT Example sample data" border="0" alt="SQL Server PIVOT Example sample data" src="http://photos1.blogger.com/blogger/4779/3059/400/PivotTableData.jpg" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;This essentially means the task is to generate a tabular result set from the rows that we have. With SQL Server 2000, most of us might have used #TEMP tables where we update the data temporarily and SELECTED from. Another option that most of the developers might have used with SQL Server 2000 is the CASE statement. In the example above, you can use a series of 12 CASE statements which can take for each column. &lt;/p&gt;

&lt;p&gt;SQL Server 2005 has a handy PIVOT operator which can help us with the above task. The PIVOT clause generates a resultset as shown in the example above. For the purpose of this example, let us create a table as follows. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;CREATE TABLE invoice (
    InvoiceNumber VARCHAR(20),
    invoiceDate DATETIME,
    InvoiceAmount MONEY 
)&lt;/pre&gt;

&lt;p&gt;The above SQL statement creates a table for the purpose of this example. Now let us insert some data into it.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;INSERT INTO invoice
SELECT 'INV001', '2005-01-01', 100 UNION ALL
SELECT 'INV002', '2005-02-01', 40 UNION ALL
SELECT 'INV003', '2005-03-01', 60 UNION ALL
SELECT 'INV004', '2005-03-10', 15 UNION ALL
SELECT 'INV005', '2005-04-01', 50 UNION ALL
SELECT 'INV006', '2005-05-01', 77 UNION ALL
SELECT 'INV007', '2005-06-01', 12 UNION ALL
SELECT 'INV008', '2005-06-05', 56 UNION ALL
SELECT 'INV009', '2005-07-01', 34 UNION ALL
SELECT 'INV010', '2005-08-01', 76 UNION ALL
SELECT 'INV011', '2005-09-01', 24 UNION ALL
SELECT 'INV012', '2005-09-20', 10 UNION ALL
SELECT 'INV013', '2005-10-01', 15 UNION ALL
SELECT 'INV014', '2005-11-01', 40 UNION ALL
SELECT 'INV015', '2005-11-15', 21 UNION ALL
SELECT 'INV016', '2005-12-01', 17 UNION ALL
SELECT 'INV017', '2006-01-01', 34 UNION ALL
SELECT 'INV018', '2006-02-01', 24 UNION ALL
SELECT 'INV019', '2006-03-01', 56 UNION ALL
SELECT 'INV020', '2006-03-10', 43 UNION ALL
SELECT 'INV021', '2006-04-01', 24 UNION ALL
SELECT 'INV022', '2006-05-01', 11 UNION ALL
SELECT 'INV023', '2006-06-01', 6 UNION ALL
SELECT 'INV024', '2006-06-05', 13&lt;/pre&gt;

&lt;p&gt;Let us create the PIVOT query now which will return a result set as per what we needed. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT *
FROM (
    SELECT 
        year(invoiceDate) as [year], 
        left(datename(month,invoicedate),3)as [month], 
        InvoiceAmount as Amount 
    FROM Invoice
) as s
PIVOT
(
    SUM(Amount) FOR [month] IN (
        jan, feb, mar, apr, 
        may, jun, jul, aug, sep, oct, nov, dec
    )
)AS p&lt;/pre&gt;

&lt;p&gt;The above query generates a result set that we needed. Let me explain the structure of the query. The first part of the query &lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT *
FROM (
    SELECT 
        year(invoiceDate) as [year], 
        left(datename(month,invoicedate),3)as [month], 
        InvoiceAmount as Amount 
    FROM Invoice
) as s &lt;/pre&gt;

&lt;p&gt;The first part of the query generates a subtable (view) as per the following.&lt;/p&gt;

&lt;p style="margin: 0px"&gt;&amp;#160;&lt;a href="http://photos1.blogger.com/blogger/4779/3059/1600/PivotSubTable.jpg"&gt;&lt;img style="margin: 0px 0px 10px; display: inline; cursor: hand" title="SQL Server PIVOT Example intermediate data" border="0" alt="SQL Server PIVOT Example intermediate data" src="http://photos1.blogger.com/blogger/4779/3059/400/PivotSubTable.jpg" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p style="margin: 0px"&gt;The second part of the query generates a PIVOT table from the above result set.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;SELECT *
FROM (
    SELECT 
        year(invoiceDate) as [year], 
        left(datename(month,invoicedate),3)as [month], 
        InvoiceAmount as Amount 
    FROM Invoice
) as s
PIVOT
(
    SUM(Amount)
    FOR [month] IN (jan, feb, mar, apr, 
    may, jun, jul, aug, sep, oct, nov, dec)
)AS p&lt;/pre&gt;

&lt;p&gt;The above query returns a result set as follows. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://photos1.blogger.com/blogger/4779/3059/1600/pivotresult.0.jpg"&gt;&lt;img style="margin: 0px 10px 10px 0px; float: left; cursor: hand" title="SQL Server PIVOT output" border="0" alt="SQL Server PIVOT output" src="http://photos1.blogger.com/blogger/4779/3059/400/pivotresult.jpg" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Hope this helps! If you found this useful or have a question, please post a comment to let me know about it.&lt;/p&gt;
&lt;div class="InlineAdBox"&gt;
First published on 18 June 2006
&lt;/div&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10362/getting-started-with-pivot-queries-in-sql-server-20052008.aspx</guid><pubDate>Tue, 03 Aug 2010 11:12:00 GMT</pubDate></item><item><title>How to load a huge file into a FILESTREAM column quickly</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10508/how-to-load-a-huge-file-into-a-filestream-column-quickly.aspx</link><description>&lt;p&gt;This post shows a quick and dirty way of loading a huge file into the FILESTREAM column of a SQL Server 2008 database instance. Note that this is an unsupported method which is not recommended on a production server. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The correct way of loading BLOB data into a FILESTREAM column&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The right way of loading a huge file into a FILESTREAM column is by using the OpenSqlFileStream() API or SqlFileStream() .NET class. The following steps are required to perform this.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Connect to the database&lt;/li&gt;    &lt;li&gt;Begin a transaction&lt;/li&gt;    &lt;li&gt;Execute a query and retrieve the PathName() and FILESTREAM Transaction Context&lt;/li&gt;    &lt;li&gt;Open the FILESTREAM data file for WRITE operation&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;Open the source file&lt;/li&gt;      &lt;ol&gt;       &lt;li&gt;Read small chunks from the read file&lt;/li&gt;        &lt;li&gt;Write into the FILESTREAM data file&lt;/li&gt;     &lt;/ol&gt;      &lt;li&gt;Close the source file&lt;/li&gt;   &lt;/ol&gt;    &lt;li&gt;Close the FILESTREAM data file&lt;/li&gt;    &lt;li&gt;Commit Transaction&lt;/li&gt;    &lt;li&gt;Close connection&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;A quick (but incorrect) way of loading BLOB data into a FILESTREAM column&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;As I have mentioned in a few of my previous posts, I am writing a book on FILESTREAM and am spending quite a lot of time experimenting how SQL Server behaves with files larger than 2 GB. As part of these exercises, I often have to load really huge files into FILESTREAM columns, update, delete and reload etc.&lt;/p&gt;  &lt;p&gt;Since I am not playing with production data, I have been looking for a quick way of getting the data loaded into SQL Server, without bothering about the best practices, transactional consistency etc. So I ended up doing the following.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Insert a dummy value into the FILESTREAM column using a TSQL insert or UPDATE statement. This will create a file in the FILESTREAM folder.&lt;/li&gt;    &lt;li&gt;Go to the FILESTREAM folder and locate the FILE SQL Server just created to store my dummy data. Replace this file with the huge data file that I wanted to load into the FILESTREAM column. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;How does it work?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;SQL Server does not keep a lock on the FILESTREAM data files when those files are not being accessed. SQL Server touches the file only when a connection requests to read or write the data. SQL Server identifies the file by its name and does not store any other metadata (such as the file size, creation date etc) internally. It means that if you replace the file using windows explorer (or using a software tool), SQL Server cannot detect that the file has been changed. The next request trying to access the FILESTREAM data file will get the new file.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Be careful&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It is not recommended that you touch the FILESTREAM data directly. All access to the FILESTREAM data should be done through SQL Server. Direct access to FILESTREAM data might corrupt your database. &lt;/p&gt;  &lt;p&gt;This method might help when setting up a test environment to test FILESTREAM behavior with large files. You may not want to go through all the best practices to get some really huge files loaded into FILESTREAM columns. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10508/how-to-load-a-huge-file-into-a-filestream-column-quickly.aspx</guid><pubDate>Mon, 02 Aug 2010 21:42:00 GMT</pubDate></item><item><title>Backup of a FILESTREAM database may include garbage files as well</title><link>http://beyondrelational.com/modules/2/blogs/28/posts/10507/backup-of-a-filestream-database-may-include-garbage-files-as-well.aspx</link><description>&lt;p&gt;I have been playing with FILESTREAM backups for a book that I am writing and came across something that I did not really like. I observed that a FILESTREAM backup may include garbage files which gets restored along with the database. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What are garbage files?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let us understand what are &lt;strong&gt;garbage &lt;/strong&gt;files. SQL Server stores FILESTREAM data as disk files. SQL Server does not support in-place update of FILESTREAM data. It means that if you try to change the data stored in a FILESTREAM column, a NEW file will be created and the old file will be discarded. A background garbage collector thread will remove the old file(s) asynchronously. Till the garbage collector jumps into action (and deletes them) these unwanted files will stay around in the FILESTREAM folder. These unwanted files that sit in the FILESTREAM folder for a short period (till they are deleted) are called &lt;strong&gt;garbage &lt;/strong&gt;files.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Your FULL Backup may include Garbage Files&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The garbage collector does not run continuously. SQL Server fires the garbage collector thread when certain criteria is met (such as a CHECKPOINT). So you might see garbage files lying around quite often. When you take a backup of your database, the garbage files will also go into the backup. When the backup is restored on another location, the garbage files are also restored.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Demonstration&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Here is a repro script that shows that your backup may include garbage files and they get restored along with the database. Here is what the script does. &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Creates a FILESTREAM enabled database &lt;/li&gt;    &lt;li&gt;Creates a table with a FILESTREAM column &lt;/li&gt;    &lt;li&gt;Inserts a row into the FILESTREAM table. &lt;strong&gt;This will create a disk file in the FILESTREAM folder&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Updates the FILESTREAM column 100 times. &lt;strong&gt;This will create 100 garbage files on the folder, because every time you update a FILESTREAM column value (from a NON NULL value to another NON NULL value), SQL Server will create a new file. &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Take a backup of the database – &lt;strong&gt;The database will include the 100 garbage files.&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Restore the backup – &lt;strong&gt;The 100 garbage files will be restored in the new location&lt;/strong&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Creating the Database&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let us start with creating the FILESTREAM enabled database. You might need to change the location of the files to run these scripts on your end.&lt;/p&gt;  &lt;pre class="brush: sql"&gt;-- Create a FILESTREAM enabled Database
CREATE DATABASE NorthPole ON
PRIMARY (
    NAME = NorthPoleDB,
    FILENAME = 'C:\Data\NorthPoleDB.mdf'
), FILEGROUP NorthPoleFS CONTAINS FILESTREAM(
    NAME = NorthPoleFS,
    FILENAME = 'C:\FS\NorthPoleFS')
LOG ON (
    NAME = NorthPoleLOG,
    FILENAME = 'C:\Data\NorthPoleLOG.ldf')
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Creating a table with a FILESTREAM column&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Next, let us create a table with a FILESTREAM column. Run the following script to create the table.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Set context to the newly created DB
USE NorthPole
GO
-- Create &amp;quot;Items&amp;quot; table
CREATE TABLE [dbo].[Items](
   [ItemID] UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,
   [ItemImage] VARBINARY(MAX) FILESTREAM NULL
)
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Inserting a new record&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Let us now insert a new row into the FILESTREAM table. SQL Server will create a disk file for every NON-NULL value in the FILESTREAM columns of each row. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Insert 1 row into the table
INSERT INTO Items (ItemID, ItemImage)
SELECT NEWID(), CAST(1 AS VARBINARY(MAX))&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Generating the garbage files&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;As mentioned earlier, when you update a FILESREAM column (from a NON-NULL value to another NON-NULL value), SQL Server will create a new file with the updated value. The old file will stay around till it is deleted by the garbage collector. The following script updates the FILESTREAM column of the row we just inserted 100 times. It generates 100 garbage files. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Update the data 100 times
DECLARE @i INT = 1
WHILE @i &amp;lt;= 100 BEGIN
    UPDATE Items SET ItemImage = CAST(1 AS VARBINARY(MAX))
    SET @i = @i + 1
END&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Taking a Backup&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The next step is to take a backup of the database. The backup file will include all the garbage files we generated in the previous step. &lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Take a Backup
BACKUP DATABASE NorthPole TO DISK = 'C:\temp\bak\NorthPoledb1.bak'
GO&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Restoring the database&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Let us create a new database from the backup file we just created.&lt;/p&gt;

&lt;pre class="brush: sql"&gt;-- Restore
RESTORE DATABASE NorthPole2
FROM DISK = N'C:\temp\bak\NorthPoledb1.bak'
WITH RECOVERY,
MOVE 'NorthPoleDB' TO 'C:\Data\NorthPole2DB.mdf',
MOVE 'NorthPoleLOG' TO 'C:\Data\NorthPole2LOG.ldf',
MOVE 'NorthPoleFS' TO 'C:\FS\NorthPole2FS', FILE=1&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Look for the Garbage Files&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;After you have restored the backup, go to the FILESTREAM data container (C:\FS\NorthPole2FS - if you have not changed the path at the time of restoring your database) and you will see (in most cases) 101 files, whereas your table has only one row and only one FILESTREAM file is required. You have 100 garbage files that came in through the backup which will stay around (for ever ??). &lt;/p&gt;
&lt;strong&gt;Points to Note&lt;/strong&gt; 

&lt;ul&gt;
  &lt;li&gt;After you update the FILESTREAM columns, if the garbage collector steps in and removes the unwanted files, your backup will be clean. So, some of you may not see this problem by running the above script if you wait for some time before taking the backup &lt;/li&gt;

  &lt;li&gt;If the backup is taken while the garbage collector is already running, you might see lesser number of garbage files in the new location. During my testing, at one occasion I ended up with 40 garbage files (instead of 100) when the new database is restored on the secondary location. &lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;How do I clean the garbage?&lt;/strong&gt; 

&lt;p&gt;I could not find any easy way to clean the garbage. The only workaround I could come up with (thanks Erland and Klein) is to restore additional transaction log backups from the original database. However, this may not be practical in most cases when we want to move a full backup to a secondary location, restore it and start using it right away. To be able to restore additional transaction log backups, the new database needs to be kept in recovery mode which may not be possible in many scenarios. &lt;/p&gt;
&lt;strong&gt;Conclusions&lt;/strong&gt; 

&lt;p&gt;I suppose the scenario I presented in this post is not too common. Books Online says that FILESTREAM data is not ideal for storing BLOB values that gets updated often. So if you need frequent updates, you may not decide to use a FILESTREAM column at all. &lt;/p&gt;

&lt;p&gt;But as in every environment, a small percentage of updates on the FILESTREAM columns may be expected and there may be always some garbage lying around. It would be really good if a future version of SQL Server can exclude the garbage files from the backups. &lt;/p&gt;</description><guid isPermaLink="true">http://beyondrelational.com/modules/2/blogs/28/posts/10507/backup-of-a-filestream-database-may-include-garbage-files-as-well.aspx</guid><pubDate>Wed, 28 Jul 2010 02:51:00 GMT</pubDate></item></channel></rss>

