<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-25106554</id><updated>2024-09-27T19:05:55.533+05:30</updated><category term="SQL Server"/><category term="T-SQL"/><category term=".Net"/><category term=".Net 2.0"/><category term="C#"/><category term="GC"/><category term="General"/><category term="XML"/><title type='text'>Rajdeep Kwatra&#39;s Blog</title><subtitle type='html'>.Net and beyond.....</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-25106554.post-371107328872806873</id><published>2007-06-25T22:42:00.000+05:30</published><updated>2008-12-13T09:11:06.499+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="XML"/><title type='text'>Validating XML in .Net</title><content type='html'>There might be a case where you are importing XML file from somewhere and need to validate it before performing some operations on the XML file. Though, there can be many ways to do so, probably the best is using &lt;a href=&quot;https://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.aspx&quot;&gt;XMLValidatingReader&lt;/a&gt; or &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx&quot;&gt;XMLReaderSettings&lt;/a&gt;. It provides you mechanism to provide a XML file, add a schema and validate the XML file supplied against the schema. It also provides an event (&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.validationeventhandler(VS.80).aspx&quot;&gt;ValidationEventHandler&lt;/a&gt;) which is fired as soon as an exception occurs in validating the XMLDocument. Please note that this class has been marked obsolete in .Net framework 2.0 which recommends using &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreader.create.aspx&quot;&gt;XMLReader.Create()&lt;/a&gt; with proper &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx&quot;&gt;XMLReaderSettings&lt;/a&gt; for validating the document. We will be looking at both the cases i.e. using &lt;a href=&quot;https://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.aspx&quot;&gt;XMLValidatingReader&lt;/a&gt; as well as &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreader.create.aspx&quot;&gt;XMLReader.Create()&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Lets assume that the XML file that we wish to validate has details about orders. Each of the Order contains the Order ID, details about the Customer, Discount percent given and the details about Products. Following graphic(click for larger image) shows the XML file that we are using:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwGiGKx4zvKVCo3DyHJ6iwdG0e8Xvk-1IfvPbv5W6qO_aVCtFJTO2p9xo-DNHJOSkem_arQgiyrleP-4iKmONv7G_NCOgF-W9j8eNsILaYnTbvGk8gDWQv_PwlaC0woVhKxh6rcw/s1600-h/OrdersXML.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5080059571690023970&quot; style=&quot;CURSOR: hand&quot; alt=&quot;Click to view larger image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwGiGKx4zvKVCo3DyHJ6iwdG0e8Xvk-1IfvPbv5W6qO_aVCtFJTO2p9xo-DNHJOSkem_arQgiyrleP-4iKmONv7G_NCOgF-W9j8eNsILaYnTbvGk8gDWQv_PwlaC0woVhKxh6rcw/s400/OrdersXML.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://rajkwatra.googlepages.com/Orders.xml&quot;&gt;Orders.xml&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To validate the XML shown above, we have the schema. The schema for the XML can be found &lt;a href=&quot;http://rajkwatra.googlepages.com/Orders.xsd&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Validating XML using XmlValidatingReader:&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;To validate the XML file against a schema, we can use &lt;a href=&quot;https://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.aspx&quot;&gt;XmlValidatingReader&lt;/a&gt;. The steps involved are:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create instance of &lt;a href=&quot;https://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.aspx&quot;&gt;XmlValidatingReader&lt;/a&gt; using the XML file to validate.&lt;/li&gt;&lt;li&gt;Create an object of &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx&quot;&gt;XmlSchema &lt;/a&gt;using the schema file to validate against.&lt;/li&gt;&lt;li&gt;Hookup event for &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.validationeventhandler(VS.80).aspx&quot;&gt;XmlValidatingReader.ValidationEventHandler&lt;/a&gt;. &lt;/li&gt;&lt;li&gt;Read the Xml to the end using &lt;a href=&quot;https://msdn2.microsoft.com/en-us/library/system.xml.xmlvalidatingreader.aspx&quot;&gt;XmlValidatingReader&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;Please note that in absence of event mentioned in point (3), an exception will be thrown on the first error encountered in XML file where as in case of having the ValidationEventHandler hooked up, all the errors in the XML file can be displayed. Following code shows the steps mentioned above:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;using&lt;/span&gt; (&lt;span style=&quot;color:#2b91af;&quot;&gt;XmlValidatingReader&lt;/span&gt; xmlValidatingReader = &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlValidatingReader&lt;/span&gt;(&lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlTextReader&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;Orders.xml&quot;&lt;/span&gt;)))&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Create the schema object to validate XML files&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlSchema&lt;/span&gt; xmlSchema = &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlSchema&lt;/span&gt;.Read(&lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlTextReader&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;Orders.xsd&quot;&lt;/span&gt;), &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;ValidationEventHandler&lt;/span&gt;(Schema_ValidationError));&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Add to the collection of schemas for XmlValidatingReader&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                xmlValidatingReader.Schemas.Add(xmlSchema);&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Attach an event which will be filed on validating error&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                xmlValidatingReader.ValidationEventHandler += &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;ValidationEventHandler&lt;/span&gt;(xmlValidatingReader_ValidationEventHandler);&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Read the XML to the end&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:blue;&quot;&gt;while&lt;/span&gt; (xmlValidatingReader.Read()) ;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:#2b91af;&quot;&gt;Console&lt;/span&gt;.WriteLine(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;\nFinished validating XML file....&quot;&lt;/span&gt;);&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            }&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Validating XML using XmlReaderSettings:&lt;/span&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;Validating XML using &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx&quot;&gt;XmlReaderSettings&lt;/a&gt; follows almost the same path as that for XmlValidatingReader, with a difference that here we will be using &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx&quot;&gt;XmlReaderSettings&lt;/a&gt; to pass in the schema details. Following are the steps to using &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx&quot;&gt;XmlReaderSettings&lt;/a&gt; for validating an XML file:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx&quot;&gt;XmlSchema &lt;/a&gt;object using the schema file.&lt;/li&gt;&lt;li&gt;Create an object for &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx&quot;&gt;XmlReaderSettings&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Set the ValidationType of XmlReaderSettings as &quot;Schema&quot;.&lt;/li&gt;&lt;li&gt;Add the &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx&quot;&gt;XmlSchema&lt;/a&gt; to the collection of schemas of XmlReaderSettings.&lt;/li&gt;&lt;li&gt;Attach the event for &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreadersettings.validationeventhandler.aspx&quot;&gt;XmlReaderSettings.ValidationEventHandler&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Create an instance of XmlReader using &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.xml.xmlreader.create.aspx&quot;&gt;XmlReader.Create()&lt;/a&gt; and passing in XML file to validate.&lt;/li&gt;&lt;li&gt;Read the XmlFile to the end.&lt;/li&gt;&lt;/ol&gt;In this case also, absence of ValidationEventHandler will cause exception on the first error encountered in reading the XML file. Following code shows the above mentioned steps:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green128\blue0;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red0\green0\blue255;\red163\green21\blue21;}??\fs24 \cf1 // Create the schema object\par ??\cf0             \cf4 XmlSchema\cf0  xmlSchema = \cf4 XmlSchema\cf0 .Read(\cf5 new\cf0  \cf4 XmlTextReader\cf0 (\cf6 &quot;Orders.xsd&quot;\cf0 ), \cf5 new\cf0  \cf4 ValidationEventHandler\cf0 (Schema_ValidationError));\par ??            \cf1 // Create reader settings\par ??\cf0             \cf4 XmlReaderSettings\cf0  xmlReaderSettings = \cf5 new\cf0  \cf4 XmlReaderSettings\cf0 ();\par ??            \cf1 // Set validation type to schema\par ??\cf0             xmlReaderSettings.ValidationType = \cf4 ValidationType\cf0 .Schema;\par ??            \cf1 // Add to the collection of schemas in readerSettings\par ??\cf0             xmlReaderSettings.Schemas.Add(xmlSchema);\par ??            \cf1 // Attach event handler whic will be fired when validation error occurs\par ??\cf0             xmlReaderSettings.ValidationEventHandler += \cf5 new\cf0  \cf4 ValidationEventHandler\cf0 (xmlReaderSettings_ValidationEventHandler);\par ??            \cf1 // Create object of XmlReader using XmlReaderSettings\par ??\cf0             \cf5 using\cf0  (\cf4 XmlReader\cf0  xmlReader = \cf4 XmlReader\cf0 .Create(\cf5 new\cf0  \cf4 XmlTextReader\cf0 (\cf6 &quot;Orders.xml&quot;\cf0 ), xmlReaderSettings))\par ??            \{\par ??                \cf1 // Read XML to the end\par ??\cf0                 \cf5 while\cf0  (xmlReader.Read()) ;\par ??                \cf4 Console\cf0 .WriteLine(\cf6 &quot;\\nFinished validating XML file....&quot;\cf0 );\par ??            \}} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;            // Create the schema object&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlSchema&lt;/span&gt; xmlSchema = &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlSchema&lt;/span&gt;.Read(&lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlTextReader&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;Orders.xsd&quot;&lt;/span&gt;), &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;ValidationEventHandler&lt;/span&gt;(Schema_ValidationError));&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Create reader settings&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlReaderSettings&lt;/span&gt; xmlReaderSettings = &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlReaderSettings&lt;/span&gt;();&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Set validation type to schema&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            xmlReaderSettings.ValidationType = &lt;span style=&quot;color:#2b91af;&quot;&gt;ValidationType&lt;/span&gt;.Schema;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Add to the collection of schemas in readerSettings&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            xmlReaderSettings.Schemas.Add(xmlSchema);&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Attach event handler whic will be fired when validation error occurs&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            xmlReaderSettings.ValidationEventHandler += &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;ValidationEventHandler&lt;/span&gt;(xmlReaderSettings_ValidationEventHandler);&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Create object of XmlReader using XmlReaderSettings&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;using&lt;/span&gt; (&lt;span style=&quot;color:#2b91af;&quot;&gt;XmlReader&lt;/span&gt; xmlReader = &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlReader&lt;/span&gt;.Create(&lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;XmlTextReader&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;Orders.xml&quot;&lt;/span&gt;), xmlReaderSettings))&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Read XML to the end&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:blue;&quot;&gt;while&lt;/span&gt; (xmlReader.Read()) ;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:#2b91af;&quot;&gt;Console&lt;/span&gt;.WriteLine(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;\nFinished validating XML file....&quot;&lt;/span&gt;);&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            }&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The code behaves the same in both the cases. However, there is a small difference in how the exception message is displayed. Using theXmlValidatingReader tells about the element/attribute with incorrect value as per the data type, but using XmlReaderSetting provides a detailed error showing the incorrect value along with the expected datatype.&lt;br /&gt;&lt;br /&gt;I hope I was able to provide most of you with a good insight on validating XML files using schemas. If you have been using some other method, please do share it here.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dotnetkicks.com/kick/?url=http://rajkwatra.blogspot.com/2007/06/validating-xml-in-net.html&quot;&gt;&lt;img alt=&quot;kick it on DotNetKicks.com&quot; src=&quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://rajkwatra.blogspot.com/2007/06/validating-xml-in-net.html&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/371107328872806873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/371107328872806873' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/371107328872806873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/371107328872806873'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/06/validating-xml-in-net.html' title='Validating XML in .Net'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwGiGKx4zvKVCo3DyHJ6iwdG0e8Xvk-1IfvPbv5W6qO_aVCtFJTO2p9xo-DNHJOSkem_arQgiyrleP-4iKmONv7G_NCOgF-W9j8eNsILaYnTbvGk8gDWQv_PwlaC0woVhKxh6rcw/s72-c/OrdersXML.png" height="72" width="72"/><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-8984625892907444736</id><published>2007-06-11T20:49:00.000+05:30</published><updated>2008-12-13T09:11:06.853+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server"/><category scheme="http://www.blogger.com/atom/ns#" term="T-SQL"/><title type='text'>T-SQL New features in SQL Server 2005 - Part 5</title><content type='html'>In continuation to the series that I have on new features in &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_0&quot;&gt;SQL&lt;/span&gt; Server 2005, today I will be discussing about two new operators- &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms188055(SQL.90).aspx&quot;&gt;Intersect and Except&lt;/a&gt;. I believe, most of you know that Oracle already has these operators, called Intersect and Minus. It was good to learn that now these are supported in &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_1&quot;&gt;SQL&lt;/span&gt; Server as well. Before going any further, lets discuss what these operators help achieve. To give you a brief idea - both these operators combine the result of two &lt;em&gt;select&lt;/em&gt; statements &lt;u&gt;having same number of columns&lt;/u&gt; and outputs result based on the operator used.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;u&gt;Intersect:&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;As mentioned above, it combines the result of two select statements and gets the distinct rows that exists in both the queries. To make it more clear, lets take an example. Suppose, we have a table that contains the details about Products and another table that contains the details about the Orders. Now, we want to get all the product IDs for which we have at least one order. Following graphics shows the structure and data of Products and Orders tables:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Products:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmlNQmP8NxOlLFQMY1zSlMgZNWKv7GHvHEzia_dk9SIrAz9Gnfm5roPMEGXrPVYAUpGh-QYkBonSq8cC-uHEsL-dvn-F-tY_Qu-TAToED_w4KikB4Om9CXuc8LWvKTullz5dawbA/s1600-h/Products.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5074834932953000930&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmlNQmP8NxOlLFQMY1zSlMgZNWKv7GHvHEzia_dk9SIrAz9Gnfm5roPMEGXrPVYAUpGh-QYkBonSq8cC-uHEsL-dvn-F-tY_Qu-TAToED_w4KikB4Om9CXuc8LWvKTullz5dawbA/s400/Products.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Orders:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuX8JrIIhLEarvnxiGKAIpXBBMxqk3lF5zN_nMYTLAwLeD8-ntghFWgc8Lm8flR-rBpuQzONQTCqIvh9ymX_u9itJ81Im5O51RpP-9QlttxVdm7vWjrecXbrlBXLGinWdjQ-FetA/s1600-h/Orders.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5074834937247968242&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuX8JrIIhLEarvnxiGKAIpXBBMxqk3lF5zN_nMYTLAwLeD8-ntghFWgc8Lm8flR-rBpuQzONQTCqIvh9ymX_u9itJ81Im5O51RpP-9QlttxVdm7vWjrecXbrlBXLGinWdjQ-FetA/s400/Orders.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, we wish to get all the Product IDs which have at least one order associated with it. Using the Intersect operator, we can get the desired output:&lt;br /&gt;&lt;pre&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_2&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Production.Product&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;INTERSECT&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_3&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Sales.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_4&quot;&gt;SalesOrderDetail&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;This lists all the distinct products that are associated to any Order. Its also worth mentioning here, that whatever can be done using Intersect and Except, can be done achieved using &lt;a href=&quot;http://technet.microsoft.com/en-us/library/ms188336(SQL.90).aspx&quot;&gt;Exists&lt;/a&gt; as well as shown below:&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;}??\fs20 \cf1 SELECT DISTINCT \cf0 ProductID \cf1 FROM \cf0 Production.Product P\par ??\cf1 WHERE EXISTS\par ??\cf0 (\cf1 SELECT \cf0 ProductID \cf1 FROM \cf0 Sales.SalesOrderDetail S \cf1 WHERE \cf0 S.ProductID = P.ProductID)} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT DISTINCT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_5&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Production.Product P&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;WHERE EXISTS&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;(&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_6&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Sales.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_7&quot;&gt;SalesOrderDetail&lt;/span&gt; S &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;S.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_8&quot;&gt;ProductID&lt;/span&gt; = P.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_9&quot;&gt;ProductID&lt;/span&gt;)&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;Note that the output of both the queries are identical. However, we are required to place &lt;em&gt;Distinct&lt;/em&gt; in the query using &lt;em&gt;Exists&lt;/em&gt;, so as to remove the duplicate rows. Intersect, on the other hand, handles this automatically and provides a more straight forward way to get the desired result set.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;u&gt;Except:&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;Contrary to &lt;em&gt;Intersect&lt;/em&gt;, &lt;em&gt;Except &lt;/em&gt;combines output from both the supplied queries and give the result as the records which are present in result set of first query and not in that of the second query. Lets take an example. Suppose we wish to get the list of slow moving products from the Products table shown above. In order to get such a list, we need to check for such products which exists, but have no orders associated with them. In essence, we are reversing the example discussed above:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_10&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Production.Product&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;EXCEPT&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_11&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Sales.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_12&quot;&gt;SalesOrderDetail&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;Here, we will get a list of all those items which do not have any orders associated with them. As mentioned above, this can be achieved using &lt;em&gt;Exists &lt;/em&gt;as well.&lt;br /&gt;&lt;pre style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT DISTINCT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_13&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Production.Product P&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;WHERE NOT EXISTS&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;(&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_14&quot;&gt;ProductID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Sales.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_15&quot;&gt;SalesOrderDetail&lt;/span&gt; S &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;S.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_16&quot;&gt;ProductID&lt;/span&gt; = P.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_17&quot;&gt;ProductID&lt;/span&gt;)&lt;/p&gt;&lt;/pre&gt;Looking at the queries above, it is clear that the &lt;em&gt;Intersect&lt;/em&gt; and &lt;em&gt;Except&lt;/em&gt; provides a neat and straight forward &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_18&quot;&gt;mechanism&lt;/span&gt; to get the records as &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_19&quot;&gt;discussed&lt;/span&gt; in our examples.&lt;br /&gt;&lt;br /&gt;On a final note, we do have some limitations using the &lt;em&gt;Intersect&lt;/em&gt; and &lt;em&gt;Except &lt;/em&gt;operators. You can use &lt;em&gt;&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms188385(SQL.90).aspx&quot;&gt;Order By&lt;/a&gt; &lt;/em&gt;only on the overall &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_20&quot;&gt;result set&lt;/span&gt; whereas &lt;em&gt;&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms177673(SQL.90).aspx&quot;&gt;Group By&lt;/a&gt;&lt;/em&gt; and &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms180199(SQL.90).aspx&quot;&gt;&lt;em&gt;Having&lt;/em&gt;&lt;/a&gt; can only be used with the queries involved and not with the result set.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dotnetkicks.com/kick/?url=http://rajkwatra.blogspot.com/2007/06/t-sql-new-features-in-sql-server-2005.html&quot;&gt;&lt;img alt=&quot;kick it on DotNetKicks.com&quot; src=&quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://rajkwatra.blogspot.com/2007/06/t-sql-new-features-in-sql-server-2005.html&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/8984625892907444736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/8984625892907444736' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/8984625892907444736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/8984625892907444736'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/06/t-sql-new-features-in-sql-server-2005.html' title='T-SQL New features in SQL Server 2005 - Part 5'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmlNQmP8NxOlLFQMY1zSlMgZNWKv7GHvHEzia_dk9SIrAz9Gnfm5roPMEGXrPVYAUpGh-QYkBonSq8cC-uHEsL-dvn-F-tY_Qu-TAToED_w4KikB4Om9CXuc8LWvKTullz5dawbA/s72-c/Products.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-6115259577638507276</id><published>2007-05-24T19:56:00.000+05:30</published><updated>2007-05-24T23:50:43.567+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><title type='text'>Custom string formatting in .Net</title><content type='html'>Recently, while working on a project, I came across the need to format the phone number supplied as string in the standard U.S. phone format(i.e. 1234567890 should be displayed as (123) 456-7890. The phone number was being fetched as a string from the database. I personally feel, that a better option to operate on strings is to save them in a formatted manner i.e. the way you wish to display them, but this is not always possible.&lt;br /&gt;&lt;br /&gt;So how do you custom format the strings in .Net? You got it - you use &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.aspx&quot;&gt;IFormatProvider&lt;/a&gt;. &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.aspx&quot;&gt;IFormatProvider &lt;/a&gt;is an interface that provides you an option to format the value as per your requirements. The sole member contained in this interface is &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.getformat.aspx&quot;&gt;GetFormat()&lt;/a&gt;. To provide the custom formatting, you need to make a class that implements &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.aspx&quot;&gt;IFormatProvider&lt;/a&gt;. Apart from this, your class must also implement &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.icustomformatter.aspx&quot;&gt;ICustomFormatter&lt;/a&gt;. This is the interface that actually handles the custom logic of formatting the supplied value. ICustomFormatter contains a single method named &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.icustomformatter.format.aspx&quot;&gt;Format()&lt;/a&gt; which accepts the format in which value should be formatted, the value that is to be formatted and an instance of &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.aspx&quot;&gt;IFormatProvider&lt;/a&gt;(i.e your custom class that implements &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.aspx&quot;&gt;IFormatProvider&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Lets get down to the code and see what it need to do a custom formatting:-&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Our requirement: &lt;/strong&gt;We have a string that contains the phone number. The phone number is a standard 10 digit number. However, it may or may not have a country code attached. If the country code is present, the format will be &#39;+&#39; followed by country code, a space and then the 10 digit phone number. So, example of valid values are:&lt;br /&gt;&lt;br /&gt;Phone number without country code: 1234567890&lt;br /&gt;Phone number with country code: +91 1234567890&lt;br /&gt;&lt;br /&gt;Lets look at the implementation of our class that handles the formatting:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;PhoneFormatter&lt;/span&gt; : &lt;span style=&quot;color:#2b91af;&quot;&gt;IFormatProvider&lt;/span&gt;, &lt;span style=&quot;color:#2b91af;&quot;&gt;ICustomFormatter&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;        #region&lt;/span&gt; IFormatProvider Members &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        &lt;span style=&quot;color:blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;object&lt;/span&gt; GetFormat(&lt;span style=&quot;color:#2b91af;&quot;&gt;Type&lt;/span&gt; formatType)&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Check if the class implements ICustomFormatter &lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;if&lt;/span&gt; (formatType == &lt;span style=&quot;color:blue;&quot;&gt;typeof&lt;/span&gt;(&lt;span style=&quot;color:#2b91af;&quot;&gt;ICustomFormatter&lt;/span&gt;))&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:blue;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;this&lt;/span&gt;;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            }&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;else&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:blue;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            }&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        } &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;        #endregion&lt;/span&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;        #region&lt;/span&gt; ICustomFormatter Members &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        &lt;span style=&quot;color:blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; Format(&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; format, &lt;span style=&quot;color:blue;&quot;&gt;object&lt;/span&gt; arg, &lt;span style=&quot;color:#2b91af;&quot;&gt;IFormatProvider&lt;/span&gt; formatProvider)&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// if the passed in argument is null, return empty string&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;if&lt;/span&gt; (arg == &lt;span style=&quot;color:blue;&quot;&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:blue;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            } &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Get the value of argument in string&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; phoneNumber = arg.ToString(); &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Check if phone number has country code&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;if&lt;/span&gt; (phoneNumber.StartsWith(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;+&quot;&lt;/span&gt;) &amp;&amp;amp; phoneNumber.IndexOf(&lt;span style=&quot;color:#a31515;&quot;&gt;&#39; &#39;&lt;/span&gt;) &gt; 1)&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// If it contains country code, separate it from phone number&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; countryCode = phoneNumber.Substring(0, phoneNumber.IndexOf(&lt;span style=&quot;color:#a31515;&quot;&gt;&#39; &#39;&lt;/span&gt;) + 1);&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                phoneNumber = phoneNumber.Remove(0, countryCode.Length);&lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Get the formatted value of phone number and prefix it with the country code&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                phoneNumber = &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt;.Format(&lt;span style=&quot;color:#a31515;&quot;&gt;&quot;{0}{1}&quot;&lt;/span&gt;, countryCode, &lt;span style=&quot;color:blue;&quot;&gt;this&lt;/span&gt;.GetFormattedPhoneNumber(phoneNumber, format));&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            }&lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;// Check if the phone number is a valid 10 digit number&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;if&lt;/span&gt; (phoneNumber.Length == 10)&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// Get the formatted value of phone number&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                phoneNumber = &lt;span style=&quot;color:blue;&quot;&gt;this&lt;/span&gt;.GetFormattedPhoneNumber(phoneNumber, format);&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            }&lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;return&lt;/span&gt; phoneNumber;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        }        &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;        #endregion&lt;/span&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;        #region&lt;/span&gt; Helper method &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;       &lt;span style=&quot;color:gray;&quot;&gt;&lt;span style=&quot;color:gray;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        &lt;span style=&quot;color:blue;&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color:#000000;&quot;&gt;GetFormattedPhoneNumber&lt;/span&gt;(&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color:#000000;&quot;&gt;phoneNumber&lt;/span&gt;, &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color:#000000;&quot;&gt;format&lt;/span&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        {&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;long&lt;/span&gt; number = 0;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:green;&quot;&gt;//Check if the phone number is a valid numeric value&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color:blue;&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;.TryParse(phoneNumber,&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;out&lt;/span&gt; &lt;span style=&quot;color:#000000;&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;))&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:#000000;&quot;&gt;            {&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:green;&quot;&gt;// If phone number is numeric, format it as per the passed in value&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;                &lt;span style=&quot;color:#000000;&quot;&gt;phoneNumber = number.ToString(format);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:#000000;&quot;&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;            &lt;span style=&quot;color:blue;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#000000;&quot;&gt;phoneNumber&lt;/span&gt;;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;        &lt;span style=&quot;color:#000000;&quot;&gt;}&lt;/span&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;        #endregion&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;   &lt;span style=&quot;color:#000000;&quot;&gt; }&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;As you can see, we have a class defined, that implements &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.iformatprovider.aspx&quot;&gt;IFormatProvider &lt;/a&gt;and &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.icustomformatter.aspx&quot;&gt;ICustomFormatter&lt;/a&gt;. I have commented code at each step so that it is easier to understand whats going on.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;Now, lets have a look at its usage:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; phoneNumber = &lt;span style=&quot;color:#a31515;&quot;&gt;&quot;+91 1234567890&quot;&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:#2b91af;&quot;&gt;Console&lt;/span&gt;.WriteLine(&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt;.Format(&lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;PhoneFormatter&lt;/span&gt;(), &lt;span style=&quot;color:#a31515;&quot;&gt;&quot;{0:(###) ###-####}&quot;&lt;/span&gt;, phoneNumber));&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This outputs: +91 (123) 456-7890&lt;br /&gt;&lt;br /&gt;Similarly, following code produces (123) 456-7890&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; phoneNumber = &lt;span style=&quot;color:#a31515;&quot;&gt;&quot;1234567890&quot;&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:#2b91af;&quot;&gt;Console&lt;/span&gt;.WriteLine(&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt;.Format(&lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af;&quot;&gt;PhoneFormatter&lt;/span&gt;(), &lt;span style=&quot;color:#a31515;&quot;&gt;&quot;{0:(###) ###-####}&quot;&lt;/span&gt;, phoneNumber));&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Another interesting implementation could be in case of displaying Bank account numbers where only last 4 or 5 digits are displayed and rest are shown as &#39;*&#39; (e.g. ****-****-1234). Its not that this can&#39;t be achieved by string operations like substring, but its just that this approach provides you a more structured, managable and reusable way of formatting values.&lt;br /&gt;&lt;br /&gt;I hope that this article was easy to follow and enjoyable to you as much as it was to me writing it.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dotnetkicks.com/kick/?url=http://rajkwatra.blogspot.com/2007/05/custom-string-formatting-in-net.html&quot;&gt;&lt;img src=&quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://rajkwatra.blogspot.com/2007/05/custom-string-formatting-in-net.html&quot; border=&quot;0&quot; alt=&quot;kick it on DotNetKicks.com&quot; /&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/6115259577638507276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/6115259577638507276' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/6115259577638507276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/6115259577638507276'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/custom-string-formatting-in-net.html' title='Custom string formatting in .Net'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-4806350696093942823</id><published>2007-05-21T23:36:00.000+05:30</published><updated>2008-12-13T09:11:07.678+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server"/><category scheme="http://www.blogger.com/atom/ns#" term="T-SQL"/><title type='text'>T-SQL New features in SQL Server 2005 - Part 4</title><content type='html'>Have you ever come across a situation where you need to delete data from one table and keep the deleted records in another table? or insert data in one table and also add the new rows at the same time to another? Weird situation...but this is what I had to do while writing a stored procedure that operates on some physical table and also keep track of affected records in another table(a table data type variable, to be precise) so that I can do some more manipulations on that. This approach, of keeping two tables(a physical and a table type variable)in sync with each other, is definitely not a clean approach but comes in handy when you know that you will be working on a very small subset of a table containing thousands of rows. Now remember, I had to do all manipulations in the stored procedure itself and SQL Server 2000 or earlier version, do not provide you any option so that I can affect two tables with one query.By using &lt;em&gt;Output&lt;/em&gt; clause, not only you can output the data into another table, but also send it to the &lt;em&gt;client &lt;/em&gt;as if it were a &lt;em&gt;select&lt;/em&gt; command.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;u&gt;Output Clause&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;SQL Server 2005 provides a new clause known as &quot;Output&quot;. &lt;em&gt;Output &lt;/em&gt;operates on similar lines as that of a trigger i.e. it provides you the details about affected records in logical tables named &lt;em&gt;deleted &lt;/em&gt;and&lt;em&gt; inserted. &lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;Lets take up a quick example to understand what I have been talking about:&lt;br /&gt;&lt;br /&gt;Suppose we have a table called Employees and we wish to insert a new record into it and also get the ID of the inserted record, which we want to return to the &lt;em&gt;client &lt;/em&gt;of our stored procedure.&lt;br /&gt;&lt;br /&gt;Lets assume, we have a column named EmployeeID in the table. The query we will write to insert the record looks like following:&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;}??\fs20 \cf1 INSERT INTO \cf0 Employees([Name],DepartmentID, ManagerID) \par ??\cf1 VALUES\cf0 (\cf4 &#39;Alec&#39;\cf0 , 1, 2)} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;INSERT INTO &lt;/span&gt;Employees([Name],DepartmentID, ManagerID) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;VALUES&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&#39;Alec&#39;&lt;/span&gt;, 1, 2)&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;To get the value of identity column, we can use well known @@&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms187342.aspx&quot; target=&quot;_blank&quot;&gt;Identity&lt;/a&gt; as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;}??\fs20 \cf1 INSERT INTO \cf0 Employees([Name],DepartmentID, ManagerID) \par ??\cf1 VALUES\cf0 (\cf4 &#39;Alec&#39;\cf0 , 1, 2)\par ??\cf1 SELECT \cf0 @@Identity} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;INSERT INTO &lt;/span&gt;Employees([Name],DepartmentID, ManagerID) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;VALUES&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&#39;Alec&#39;&lt;/span&gt;, 1, 2)&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;@@Identity&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;This will output the inserted ID. However, while working on tables having triggers defined on it, it is better to use &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms190315.aspx&quot;&gt;Scope_Identity() &lt;/a&gt;since it operates in the current scope. The modified statement will look as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;}??\fs20 \cf1 INSERT INTO \cf0 Employees([Name],DepartmentID, ManagerID) \par ??\cf1 VALUES\cf0 (\cf4 &#39;Alec&#39;\cf0 , 1, 2)\par ??\cf1 SELECT Scope_Identity\cf0 ()} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;INSERT INTO &lt;/span&gt;Employees([Name],DepartmentID, ManagerID) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;VALUES&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&#39;Alec&#39;&lt;/span&gt;, 1, 2)&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT Scope_Identity&lt;/span&gt;()&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;In both the cases, however, you can see that we are required to write two statements: one for performing the operation(insert the record) and another to get the affected/inserted ID. Using the &lt;em&gt;Output&lt;/em&gt; clause, makes it possible to insert the record as well as return the ID in same SQL statement:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;}??\fs20 \cf1 INSERT INTO \cf0 Employees([Name],DepartmentID, ManagerID) \par ??\cf1 OUTPUT \cf0 inserted.EmployeeID\par ??\cf1 VALUES\cf0 (\cf4 &#39;Alec&#39;\cf0 , 1, 2)} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;INSERT INTO &lt;/span&gt;Employees([Name],DepartmentID, ManagerID) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;OUTPUT &lt;/span&gt;inserted.EmployeeID&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;VALUES&lt;/span&gt;(&lt;span style=&quot;color:#a31515;&quot;&gt;&#39;Alec&#39;&lt;/span&gt;, 1, 2)&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;Pretty neat! You can see that all the above three statements produces the same result, but using output saves you from writing an extra statement to fetch the ID of inserted record. It is also worth noting that the Output clause give you the value before any triggers have fired on the table i.e. if there is an &quot;instead of&quot; trigger defined, and the record is not actually inserted, you will still get the ID of the inserted record.&lt;br /&gt;Lets look at an interesting problem now. Suppose that you wish to update data in certain table as per the condition specified in &lt;em&gt;where&lt;/em&gt; clause and you also wish to return the affected records to the &lt;em&gt;client&lt;/em&gt; for some reason. &lt;em&gt;Output&lt;/em&gt; does just that.&lt;br /&gt;&lt;br /&gt;Lets look the table first:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMstes3-0okCTRDwgxvn8StUMqrDlA5fXSV8grYPryup2pP8zf_Ql7xCT0xjwxkkIM39Zsx_99vn33E09zizm2Rz0YBR0kDUWeQmtV63NAZlA16WaKQqdQd_fKaKSDvssD4WKPaA/s1600-h/Employees_Output.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5067402288641891026&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMstes3-0okCTRDwgxvn8StUMqrDlA5fXSV8grYPryup2pP8zf_Ql7xCT0xjwxkkIM39Zsx_99vn33E09zizm2Rz0YBR0kDUWeQmtV63NAZlA16WaKQqdQd_fKaKSDvssD4WKPaA/s400/Employees_Output.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, we wish to update the departmentID to 2 for all those employees who are reporting to EmployeeID 2(i.e. employeeID 4, 5 and 8) and have department ID set as 3 and also return these records to &lt;em&gt;client&lt;/em&gt; of our stored procedure. Once these records are updated, we have absolutely no way to get the details about which records were updated. To do this, we can possibly store all the IDs(based on our condition) into some table variable before firing the update command and then use the previously saved IDs to get which records were updated. Another, more efficient, way can be: &lt;em&gt;Output&lt;/em&gt;&lt;br /&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre managerid=&quot;2&quot; departmentid=&quot;2\par&quot;&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;UPDATE &lt;/span&gt;Employees&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    &lt;span style=&quot;color:blue;&quot;&gt;SET &lt;/span&gt;DepartmentID = 2&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;OUTPUT &lt;/span&gt;inserted.EmployeeID, inserted.[Name], inserted.DepartmentID, inserted.ManagerID&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;ManagerID = 2 &lt;span style=&quot;color:blue;&quot;&gt;AND &lt;/span&gt;DepartmentID = 3&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;Following is the output of above mentioned query:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9FAkbVRnxdEjzWi3KmCvoWGoI8A-SleLKEv9qQsgDF6dwKh_kYSAILzf2n1ipyDHTx4_7NXVy2LodGnOOVTsRchc80LjUwdcBuo7Ca01g-RZyQuLK_MrZZQG4gX9hetoaeMhD6w/s1600-h/Output_Result.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5067403495527701218&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9FAkbVRnxdEjzWi3KmCvoWGoI8A-SleLKEv9qQsgDF6dwKh_kYSAILzf2n1ipyDHTx4_7NXVy2LodGnOOVTsRchc80LjUwdcBuo7Ca01g-RZyQuLK_MrZZQG4gX9hetoaeMhD6w/s400/Output_Result.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As mentioned earlier, &lt;em&gt;Output &lt;/em&gt;provides you access to &lt;em&gt;inserted&lt;/em&gt; and &lt;em&gt;deleted&lt;/em&gt; logical tables. The data that has been inserted into the table OR the data after &lt;em&gt;update &lt;/em&gt;statement has been executed, is available in &lt;em&gt;inserted&lt;/em&gt; logical table. Similarly, data deleted using &lt;em&gt;delete&lt;/em&gt; statement OR as a result of updation(i.e. data that was there prior to updation) is available in &lt;em&gt;deleted &lt;/em&gt;logical table.&lt;br /&gt;&lt;br /&gt;Lets take one simple example now(simple because I feel that now you have a fair idea of what &lt;em&gt;output&lt;/em&gt; is all about). We wish to update the name of an employee and we want to get both the old and the new value of the employee name:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;}??\fs20 \cf1 UPDATE \cf0 Employees\par ??\tab \cf1 SET \cf0 [Name] = \cf4 &#39;Alex&#39;\par ??\cf1 OUTPUT \cf0 inserted.EmployeeID, deleted.[name] \cf1 as \cf0 OldName, inserted.[Name] \cf1 as \cf0 NewName\par ??\tab \cf1 WHERE \cf0 [Name] = \cf4 &#39;Alec&#39;} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;UPDATE &lt;/span&gt;Employees&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    &lt;span style=&quot;color:blue;&quot;&gt;SET &lt;/span&gt;[Name] = &lt;span style=&quot;color:#a31515;&quot;&gt;&#39;Alex&#39;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;OUTPUT &lt;/span&gt;inserted.EmployeeID, deleted.[name] &lt;span style=&quot;color:blue;&quot;&gt;as &lt;/span&gt;OldName, inserted.[Name] &lt;span style=&quot;color:blue;&quot;&gt;as &lt;/span&gt;NewName&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;[Name] = &lt;span style=&quot;color:#a31515;&quot;&gt;&#39;Alec&#39;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;Following is the output of the above mentioned query:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6cK3i7fwNFSRAk1UQNo9NJihcxXLfxLrvL2jQSbLTdDKwmNYgPSTd8oaS_gXHhzKf2aEThcIXY5yM7sj_xuSZ1Ts6XKyb1ir3FpgsOIHn0dg69y-yKHxYnL7-7gujvZSLxrzOug/s1600-h/Output_inserted_deleted.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5067403946499267314&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6cK3i7fwNFSRAk1UQNo9NJihcxXLfxLrvL2jQSbLTdDKwmNYgPSTd8oaS_gXHhzKf2aEThcIXY5yM7sj_xuSZ1Ts6XKyb1ir3FpgsOIHn0dg69y-yKHxYnL7-7gujvZSLxrzOug/s400/Output_inserted_deleted.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can see that we have the name that was updated, obtained from &lt;em&gt;deleted &lt;/em&gt;logical table in column named &quot;OldName&quot; and the new value for the name in &quot;NewName&quot; from &lt;em&gt;inserted &lt;/em&gt;logical table. Cool!!! Isn&#39;t it?&lt;br /&gt;&lt;br /&gt;One last thing, which I discussed in the beginning of this article: storing the affected records in a table data type variable. Lets take the example of updating the department IDs of employees:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green128\blue0;\red255\green255\blue255;\red0\green0\blue255;\red0\green0\blue0;}??\fs20 \cf1 -- Declare a temporary table to hold the updated records\par ??\cf3 DECLARE \cf0 @TempTable \cf3 Table\par ??\cf0 (\par ??\tab EmployeeID\tab \tab \cf3 INT\cf0 ,\par ??\tab [Name]\tab \tab \tab \cf3 VARCHAR\cf0 (50),\par ??\tab DepartmentID\tab \cf3 INT\cf0 ,\par ??\tab ManagerID\tab \tab \cf3 INT\par ??\cf0 )\par ??\cf1 -- Update the table and store the affected records in @tempTable via output\par ??\cf3 UPDATE \cf0 Employees\par ??    \cf3 SET \cf0 DepartmentID = 2\par ??\cf3 OUTPUT \cf0 inserted.EmployeeID, inserted.[Name], inserted.DepartmentID, inserted.ManagerID \cf3 INTO \cf0 @TempTable\par ??    \cf3 WHERE \cf0 ManagerID = 2 \cf3 AND \cf0 DepartmentID = 3\par ??\cf1 -- Select all the records to see which were updated\par ??\cf3 SELECT \cf0 * \cf3 FROM \cf0 @TempTable} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:12pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;-- Declare a temporary table to hold the updated records&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;DECLARE &lt;/span&gt;@TempTable &lt;span style=&quot;color:blue;&quot;&gt;Table&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;(&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    EmployeeID        &lt;span style=&quot;color:blue;&quot;&gt;INT&lt;/span&gt;,&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    [Name]            &lt;span style=&quot;color:blue;&quot;&gt;VARCHAR&lt;/span&gt;(50),&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    DepartmentID    &lt;span style=&quot;color:blue;&quot;&gt;INT&lt;/span&gt;,&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    ManagerID        &lt;span style=&quot;color:blue;&quot;&gt;INT&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;)&lt;br /&gt; &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;-- Update the table and store the affected records in @tempTable via output&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;UPDATE &lt;/span&gt;Employees&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    &lt;span style=&quot;color:blue;&quot;&gt;SET &lt;/span&gt;DepartmentID = 2&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;OUTPUT &lt;/span&gt;inserted.EmployeeID, inserted.[Name], inserted.DepartmentID, inserted.ManagerID &lt;span style=&quot;color:blue;&quot;&gt;INTO &lt;/span&gt;@TempTable&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;    &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;ManagerID = 2 &lt;span style=&quot;color:blue;&quot;&gt;AND &lt;/span&gt;DepartmentID = 3&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;-- Select all the records to see which were updated&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;* &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;@TempTable&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;Introduction of &lt;em&gt;Output&lt;/em&gt; gives a lot of opportunities to developers like me to write a better and manageable code. I think you must have already thought of a couple of places where you can use this... So what are you waiting for..give it a shot!&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dotnetkicks.com/kick/?url=http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_21.html&quot;&gt;&lt;img src=&quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_21.html&quot; border=&quot;0&quot; alt=&quot;kick it on DotNetKicks.com&quot; /&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/4806350696093942823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/4806350696093942823' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/4806350696093942823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/4806350696093942823'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_21.html' title='T-SQL New features in SQL Server 2005 - Part 4'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMstes3-0okCTRDwgxvn8StUMqrDlA5fXSV8grYPryup2pP8zf_Ql7xCT0xjwxkkIM39Zsx_99vn33E09zizm2Rz0YBR0kDUWeQmtV63NAZlA16WaKQqdQd_fKaKSDvssD4WKPaA/s72-c/Employees_Output.png" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-3036624486640539224</id><published>2007-05-18T22:24:00.000+05:30</published><updated>2008-12-13T09:11:08.220+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server"/><category scheme="http://www.blogger.com/atom/ns#" term="T-SQL"/><title type='text'>T-SQL New features in SQL Server 2005 - Part 3</title><content type='html'>Often times, during my career, I faced a situation where I had to recursively get data out of a table starting from a root. The classic example of such a situation is Employee-Manager relationship table, which I am sure everyone, having even a basic idea of SQL, is familiar with. In this case, we have a table containing the details like Name, Department ID, Salary etc of Employees. There is also another column called Manager ID, which is nothing but the Employee ID from same table ie. case of a self-join. In this table, the employee having highest designation(lets assume CEO) has it Manager ID as null making him the &lt;em&gt;root. &lt;/em&gt;Another such example is a table having the details/labels for a TreeView kind of structure (in other words, source for hierarchical data display)&lt;em&gt;. &lt;/em&gt;Now, prior to SQL Server 2005, the only way to get the data from such a table was by writing a stored procedure. However, introduction of &lt;a href=&quot;http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_3331.html&quot;&gt;CTEs&lt;/a&gt; has made it possible to get data recursively out of a table.&lt;br /&gt;&lt;br /&gt;As mentioned in the &lt;a href=&quot;http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_3331.html&quot;&gt;previous&lt;/a&gt; article, CTEs are nothing but an inline representation of a table whose source is a query written in the CTE. By having the join with itself , the CTE can fetch the data recursively. To take it more clearer, lets look at an example.&lt;br /&gt;&lt;br /&gt;Lets assume we have a table named Employees containing following data:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLUKQVYgiyP9YEtQGg4AQ-NG_FxYy-xnan8CJvf8uO9ZJYYoVyqLf1sLNAnqeZWuEe7l7EMrTAC9G1_pGjwnttqlsd_OgsfJT2kIMTNQEMtRZ62_gLBDsBlVTABbgsbwk2YGBclg/s1600-h/Employees.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5066586017222384290&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLUKQVYgiyP9YEtQGg4AQ-NG_FxYy-xnan8CJvf8uO9ZJYYoVyqLf1sLNAnqeZWuEe7l7EMrTAC9G1_pGjwnttqlsd_OgsfJT2kIMTNQEMtRZ62_gLBDsBlVTABbgsbwk2YGBclg/s400/Employees.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the above table, Jim is the CEO since his manager ID is &lt;em&gt;null.&lt;/em&gt; Now, we want to get all the people in the hierarchy starting from Jim. We can do that using the following query:&lt;br /&gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;WITH &lt;/span&gt;AllEmployees &lt;span style=&quot;color:blue;&quot;&gt;AS &lt;/span&gt;&lt;span style=&quot;color:green;&quot;&gt;-- (1)&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;( &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;Employees.EmployeeID, Employees.Name, Employees.ManagerID &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Employees &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;ManagerID &lt;span style=&quot;color:blue;&quot;&gt;IS NULL &lt;/span&gt;&lt;span style=&quot;color:green;&quot;&gt;-- (2)&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;UNION ALL &lt;/span&gt;&lt;span style=&quot;color:green;&quot;&gt;-- (3)&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;Employees.EmployeeID, Employees.Name, Employees.ManagerID &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;AllEmployees &lt;span style=&quot;color:blue;&quot;&gt;INNER JOIN &lt;/span&gt;Employees &lt;span style=&quot;color:blue;&quot;&gt;ON &lt;/span&gt;&lt;span style=&quot;color:green;&quot;&gt;-- (4)&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;AllEmployees.EmployeeID = Employees.ManagerID &lt;span style=&quot;color:green;&quot;&gt;-- (5)&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;* &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;AllEmployees &lt;span style=&quot;color:green;&quot;&gt;-- (6)&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This query will result in the following data:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjniFqz-GctF9ap0FYtrrCsDqZlEVuOW_P5oJT-2qMwf0ujsE7_FGfQmjEl36002mRbzTlI1KHNgoaXY7jLx8OJUMV4uZU6rZMvQcKhc_85pVtxYqr_7WojYnIcm7JUqV0usx4csA/s1600-h/CTE2.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5066595062423509682&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjniFqz-GctF9ap0FYtrrCsDqZlEVuOW_P5oJT-2qMwf0ujsE7_FGfQmjEl36002mRbzTlI1KHNgoaXY7jLx8OJUMV4uZU6rZMvQcKhc_85pVtxYqr_7WojYnIcm7JUqV0usx4csA/s400/CTE2.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Following is the explanation of the steps:&lt;br /&gt;&lt;br /&gt;1) WITH defines a name for the CTE.&lt;br /&gt;&lt;br /&gt;2) This query defines the anchor point. Notice we have the condition &quot;ManagerID IS NULL&quot; in WHERE clause. This defines/fetches the starting point. All the data will be fetched from this point onwards.&lt;br /&gt;&lt;br /&gt;3) It is mandatory to use UNION ALL in case you are writing a recursive query. Failing this will give you an error mentioning that &quot;&lt;em&gt;&lt;strong&gt;it&lt;/strong&gt; does not contain a top-level UNION ALL operator&lt;/em&gt;&quot;&lt;em&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;4) Makes a join with the data returned from the anchor query and in turn the CTE as a whole.&lt;br /&gt;&lt;br /&gt;5) We make the join on condition where the manager ID from Employees table is in EmployeeID of AllEmployees CTE.&lt;br /&gt;&lt;br /&gt;6) Selects all the records from the CTE as source. It is important that the &lt;em&gt;select&lt;/em&gt; is the immediate next statement after the CTE closing parentheses.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We can also restrict the recursion level to a desired value. In the above example, we have nesting upto 3 levels starting from Jim. Lets assume that we wish to get the data &lt;em&gt;only&lt;/em&gt; till the second level i.e. Jim-&gt;Thomas, Helena-&gt;Robert, Julian. We can do so by adding the following &lt;em&gt;option &lt;/em&gt;to the &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_0&quot;&gt;above mentioned&lt;/span&gt; query:&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;OPTION &lt;/span&gt;(&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_1&quot;&gt;MaxRecursion&lt;/span&gt; 2)&lt;/p&gt;&lt;p style=&quot;MARGIN-TOP: 0px; BACKGROUND: white&quot;&gt;This will result in the termination of the query as soon as the supplied nesting level is reached. If you look at the messages after executing the query, you will get:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family:courier new;font-size:85%;color:#ff0000;&quot;&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_2&quot;&gt;Msg&lt;/span&gt; 530, Level 16, State 1, Line 1&lt;br /&gt;The statement terminated. The maximum recursion 2 has been exhausted before statement completion.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;But in the results tab, you will still get the expected data. &lt;/p&gt;&lt;p&gt;Also, if you wish to get the nesting or recursion level along with the data, you can modify the query in following manner:&lt;/p&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;WITH &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_3&quot;&gt;AllEmployees&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;AS&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;( &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;Employees.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_4&quot;&gt;EmployeeID&lt;/span&gt;, Employees.Name, Employees.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_5&quot;&gt;ManagerID&lt;/span&gt;, 0 &lt;span style=&quot;color:blue;&quot;&gt;as Level &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Employees &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_6&quot;&gt;ManagerID&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;IS NULL &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;UNION ALL &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;Employees.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_7&quot;&gt;EmployeeID&lt;/span&gt;, Employees.Name, Employees.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_8&quot;&gt;ManagerID&lt;/span&gt;, &lt;span style=&quot;color:blue;&quot;&gt;Level &lt;/span&gt;+ 1 &lt;span style=&quot;color:blue;&quot;&gt;as Level &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_9&quot;&gt;AllEmployees&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;INNER JOIN &lt;/span&gt;Employees &lt;span style=&quot;color:blue;&quot;&gt;ON &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_10&quot;&gt;AllEmployees&lt;/span&gt;.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_11&quot;&gt;EmployeeID&lt;/span&gt; = Employees.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_12&quot;&gt;ManagerID&lt;/span&gt; &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;* &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_13&quot;&gt;AllEmployees&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;Notice that we have added another column named Level to display the nesting level of the given record. The &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_14&quot;&gt;dissection&lt;/span&gt; is as follows: the anchor query assigns the value of &quot;Level&quot; as 0(zero). In the second query (after &lt;em&gt;Union All&lt;/em&gt;), we set the &quot;Level&quot; as &quot;Level + 1&quot;. What it does is that takes the value of Level from previous recursion and adds 1 to it. The value of &quot;Level&quot; is not incremented on each record, but on each recursion. Now the data is &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_15&quot;&gt;displayed&lt;/span&gt; as shown in the following figure:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4hGzIowFfBNqWbVqJ-VRASAoUPO8w14GdanJ8ndyIoWleenR3dTf3ylnWpg2ueAAXOlngwLjf7gFoG8DQMpN9y4mQWD1iWLDfyc8BcBd9IXL7FDC8zfMjLSstN1CbHrVW-OxaFQ/s1600-h/CTE_Levels.png&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5066596338028796610&quot; style=&quot;CURSOR: hand&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4hGzIowFfBNqWbVqJ-VRASAoUPO8w14GdanJ8ndyIoWleenR3dTf3ylnWpg2ueAAXOlngwLjf7gFoG8DQMpN9y4mQWD1iWLDfyc8BcBd9IXL7FDC8zfMjLSstN1CbHrVW-OxaFQ/s400/CTE_Levels.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I hope that this tutorial will come in handy &lt;span class=&quot;blsp-spelling-corrected&quot; id=&quot;SPELLING_ERROR_16&quot;&gt;when&lt;/span&gt; you are in a situation where you need to fetch the data out of a table recursively.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dotnetkicks.com/kick/?url=http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_18.html&quot;&gt;&lt;img alt=&quot;kick it on DotNetKicks.com&quot; src=&quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_18.html&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/3036624486640539224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/3036624486640539224'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_18.html' title='T-SQL New features in SQL Server 2005 - Part 3'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLUKQVYgiyP9YEtQGg4AQ-NG_FxYy-xnan8CJvf8uO9ZJYYoVyqLf1sLNAnqeZWuEe7l7EMrTAC9G1_pGjwnttqlsd_OgsfJT2kIMTNQEMtRZ62_gLBDsBlVTABbgsbwk2YGBclg/s72-c/Employees.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-1741227965711189674</id><published>2007-05-13T13:06:00.000+05:30</published><updated>2007-05-15T20:32:10.253+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 2.0"/><category scheme="http://www.blogger.com/atom/ns#" term="GC"/><title type='text'>Managing unmanaged memory</title><content type='html'>The title of this post might seem confusing. Garbage Collector (or GC) in .Net is designed to take care of managed memory only, so what do you do in a case where you have a managed object that itself takes very small amount of memory but allocates significant amount of unmanaged resources? In that case, GC will not be aware of the actual memory allocated by your application and therefore will not be able to optimize the collection of unused resources.&lt;br /&gt;&lt;br /&gt;In .Net 2.0, a new feature has been introduced to take care of such an issue. Now it is possible to make the GC aware about the large amount of unmanaged resources that should be taken care of via &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.gc.addmemorypressure.aspx&quot; target=&quot;_blank&quot;&gt;GC.AddMemoryPressure&lt;/a&gt;. This method accepts a long &lt;em&gt;bytesallocated&lt;/em&gt; and informs GC that there are x bytes to be taken care of while scheduling garbage collection. Ideal place to use this method can be the object constructor.&lt;br /&gt;&lt;br /&gt;Since we are increasing the memory pressure on GC, so we have to release it too when the object is no longer required. This can be taken care of by using &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.gc.removememorypressure.aspx&quot; target=&quot;_blank&quot;&gt;GC.RemoveMemoryPressure&lt;/a&gt; after the unmanaged resources have been released. Two points should be taken care of in this kind of a situation: first, you should always release the same amount of memory pressure as much as you have added, failing which might adversely affect the application performance and second, since we are dealing with unmanaged resources, your object must be implementing the IDisposable interface and use it to release the object deterministically.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dotnetkicks.com/kick/?url=http://rajkwatra.blogspot.com/2007/05/managing-unmanaged-memory.html&quot;&gt;&lt;img alt=&quot;kick it on DotNetKicks.com&quot; src=&quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://rajkwatra.blogspot.com/2007/05/managing-unmanaged-memory.html&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/1741227965711189674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/1741227965711189674' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/1741227965711189674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/1741227965711189674'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/managing-unmanaged-memory.html' title='Managing unmanaged memory'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-3773713304813767987</id><published>2007-05-10T21:27:00.000+05:30</published><updated>2007-05-13T14:29:12.357+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server"/><category scheme="http://www.blogger.com/atom/ns#" term="T-SQL"/><title type='text'>T-SQL New features in SQL Server 2005 - Part 2</title><content type='html'>In continuation to the previous &lt;a href=&quot;http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_09.html&quot;&gt;post&lt;/a&gt;, today we will be discussing about two new enhancements, namely &lt;em&gt;Top&lt;/em&gt; and &lt;em&gt;Common Table Expressions&lt;/em&gt; (better known as CTEs).&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style=&quot;font-family:lucida grande;font-size:130%;&quot;&gt;Top&lt;/span&gt;:&lt;/u&gt;&lt;br /&gt;It isn&#39;t so that the Top clause is introduced in this version. Its about the new possibilities where you can use Top clause in an enhanced fashion. Take for example, you are using SQL Server 2000 and have to write a stored procedure for implementing server side paging. In a typical scenario, you will be passing a value to a parameter for defining the page size (i.e. number of records to be returned) along with other parameters like page index etc. Now an optimum way to use the value of page size would be to use &quot;SET ROWCOUNT&quot; with the page size parameter of the procedure, so that only the desired number of rows are returned:&lt;br /&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SET ROWCOUNT &lt;/span&gt;@pageSize &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;col1, col2 &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Table1&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;However, now you have the power of writing your query in following way:&lt;br /&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT TOP&lt;/span&gt;(@pageSize) col1, col2 &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Table1&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;This will result in same number of rows as specified by @pageSize. Note the use of parenthesis enclosing the @pageSize variable. These are mandatory if you are using a variable with Top clause. You can, however, omit these if using a fixed numeral.&lt;br /&gt;&lt;br /&gt;Top clause can now be combined with Insert, Update and Delete statements as well apart from Select. Reviewing following examples will provide a clearer view on this:&lt;br /&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;DECLARE &lt;/span&gt;@Count &lt;span style=&quot;color:blue;&quot;&gt;INT &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SET &lt;/span&gt;@Count = 50 &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT TOP &lt;/span&gt;(@Count) * &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Categories&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;This statement will return top 50 record from table named categories. Another usage can be as follows:&lt;br /&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;DECLARE &lt;/span&gt;@Count &lt;span style=&quot;color:blue;&quot;&gt;INT &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SET &lt;/span&gt;@Count = 2 &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;UPDATE TOP &lt;/span&gt;(@Count) Categories &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SET &lt;/span&gt;CategoryName = CategoryName + &lt;span style=&quot;color:#a31515;&quot;&gt;&#39;s&#39; &lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;This statement will update the first two records in &#39;Categories&#39; table and append an &#39;s&#39; to the CategoryName. In a real life scenario, the queries will be more complex than the above mentioned ones, but those will only be a variation (for eg. Update statement may have a &#39;Where&#39; clause to filter out the necessary records which needs to be modified.)&lt;br /&gt;&lt;br /&gt;It is also worth mentioning that Microsoft recommends using the Top clause in new development work since &#39;SET ROWCOUNT&#39; is slated to be removed from future versions of SQL Server. More information about the same can be found &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms188774.aspx&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;u&gt;Common Table Expressions:&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;Common Table Expressions(or CTEs) can be defined as &lt;em&gt;&quot;An expression that is referred to by name within the context of a single query.&quot;&lt;/em&gt; What this means is that you define a query, give it a name(or alias) and use that alias as if it is a physical table. An example will make it clear what I am referring to:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;WITH &lt;/span&gt;EvenNumbers &lt;span style=&quot;color:blue;&quot;&gt;AS &lt;/span&gt;&lt;span style=&quot;color:green;&quot;&gt;-- (1) &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;( &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;Col1 &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;Numbers &lt;span style=&quot;color:blue;&quot;&gt;WHERE &lt;/span&gt;Number%2=0 &lt;span style=&quot;color:green;&quot;&gt;-- (2) &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;) &lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;Col1 &lt;span style=&quot;color:blue;&quot;&gt;FROM &lt;/span&gt;EvenNumbers &lt;span style=&quot;color:green;&quot;&gt;-- (3) &lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Here, we have a physical table named &quot;Numbers&quot; which contains random numbers in &quot;Col1&quot; column. Lets dissect the query to understand how it works:&lt;br /&gt;(1) The syntax to define a CTE is by using keyword &quot;WITH&quot;. In the above statement, &quot;EvenNumbers&quot; is the alias that we wish to assign to the resultset from the query defined in (2).&lt;br /&gt;In line (2), we are selecting only those values of Col1 which are divisible by 2 i.e. even numbers. The statement in line (3) returns all the records found in (2). &lt;p&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;Looking at it the first time, you might not be able to visualize the numerous options CTEs provide. A very good use of CTEs can be in set-based operations. Imagine writing a complex query having join on may be 5-6 tables...can be difficult and time consuming. Looking at it from CTEs perspective, however changes it all. Internally it is doing just the same thing, but provides a better and easier mechanism to understand and write query. Another very useful application of CTEs is in writing recursive queries. Yes! I &lt;em&gt;mean&lt;/em&gt; recursive queries!!! We will be looking at that application of CTEs in coming days. Till then....happy querying!!!&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/3773713304813767987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/3773713304813767987' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/3773713304813767987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/3773713304813767987'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_3331.html' title='T-SQL New features in SQL Server 2005 - Part 2'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-3806860015342006385</id><published>2007-05-09T21:26:00.001+05:30</published><updated>2007-05-13T14:29:29.971+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server"/><category scheme="http://www.blogger.com/atom/ns#" term="T-SQL"/><title type='text'>T-SQL New features in SQL Server 2005 - Part 1</title><content type='html'>&lt;p align=&quot;left&quot;&gt;I have been working in SQL Server since past 3 years or so. I like solving complex problems and deriving the simplest, yet efficient, query. Though, I was always able to solve the problem at hand using the constructs provided in SQL Server 2000, but there were times when I felt myself restricted.. or wasn&#39;t particularly happy the way I solved a problem. With new constructs and clauses, now available, in SQL Server 2005 T-SQL, I feel that I am able to write the query in a neat, manageable way. This can be compared with the Generics introduced in .Net 2.0 in a way that it does not enable you to do something that wasn&#39;t at all possible earlier, but just that it provides a easy to maintain and efficient ways of doing the same thing. In coming days, we will be discussing the following features: &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;&lt;br /&gt;1. Error Handling&lt;br /&gt;2. Top clause&lt;br /&gt;3. Common Table Expression&lt;br /&gt;4. Recursive Queries&lt;br /&gt;5. Output clause&lt;br /&gt;6. Intersect and Except&lt;br /&gt;7. Apply&lt;br /&gt;8. Ranking Function&lt;br /&gt;&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;span style=&quot;font-family:lucida grande;font-size:130%;&quot;&gt;&lt;u&gt;Error Handling:&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;In prior version of SQL Server, the way to check if there was an error in a SQL statement was to use @@Error which should be used immediately after the SQL statement. It was mandatory to follow this practice since the value in @@Error was reset after every statement.&lt;br /&gt;With the new structured error handing mechanism provided in T-SQL 2005, it provides a straighter forward, simpler and better way to handle exceptions in code. This can be understood more clearly by the following example:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;Writing the following query will result in “Divide by zero” error:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;}??\fs20 \cf1 SELECT \cf0 1/0} --&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;1/0&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;If the statement which is expected to throw an exception is enclosed in a try-catch block, the same situation can be handled in an elegant manner:&lt;br /&gt;&lt;div style=&quot;BACKGROUND: white;font-family:Courier New;font-size:9pt;color:black;&quot;   &gt;&lt;br /&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;BEGIN &lt;/span&gt;TRY&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;SELECT &lt;/span&gt;1/0&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;END &lt;/span&gt;TRY&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;BEGIN &lt;/span&gt;CATCH&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;PRINT &lt;/span&gt;&lt;span style=&quot;color:#a31515;&quot;&gt;&#39;ErrorNumber= &#39; &lt;/span&gt;+ &lt;span style=&quot;color:blue;&quot;&gt;CONVERT&lt;/span&gt;(&lt;span style=&quot;color:blue;&quot;&gt;VARCHAR&lt;/span&gt;(10), Error_Number())&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;PRINT &lt;/span&gt;&lt;span style=&quot;color:#a31515;&quot;&gt;&#39;ErrorMessage= &#39; &lt;/span&gt;+ Error_Message()&lt;/p&gt;&lt;p style=&quot;MARGIN: 0px&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;END &lt;/span&gt;CATCH&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;This will now handle the exception and display the Error number along with the message.&lt;br /&gt;&lt;br /&gt;Apart from the above mentioned functions for obtaining the exception details, SQL Server also provides the following:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;ERROR_NUMBER() - Number of error&lt;br /&gt;ERROR_SEVERITY() - Severity of error&lt;br /&gt;ERROR_STATE() - State of error&lt;br /&gt;ERROR_MESSAGE() - Error Message&lt;br /&gt;ERROR_LINE() - Line on which error occurred&lt;br /&gt;ERROR_PROCEDURE() - Procedure in which error occurred&lt;br /&gt;XACT_STATE() - Transaction state&lt;/span&gt; &lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;left&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;The example shown here just gives an idea of what can be achieved using structured exception handing in SQL Server. I also feel, this approach should be a welcome feature by any .Net programmer since the construct is almost similar to that a .Net developer is familiar with.&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/3806860015342006385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/3806860015342006385' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/3806860015342006385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/3806860015342006385'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/t-sql-new-features-in-sql-server-2005_09.html' title='T-SQL New features in SQL Server 2005 - Part 1'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25106554.post-5615670635451569953</id><published>2007-05-06T20:34:00.000+05:30</published><updated>2007-06-12T21:59:39.156+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="General"/><title type='text'>First Post</title><content type='html'>It was difficult to decide &quot;&lt;em&gt;the first&lt;/em&gt;&quot; topic for my blog and after giving a lot of thought I was able to come to a decision. During this whole process of deciding a topic to write upon, I evaluated a lot many things which I like doing and on which I have been working lately. Here, in my blog, I will be covering many things including SQL Server programming, custom controls, new features in .Net 2.0 and similar topics. Since most of my experience is in .Net, so the topics will be more or less .Net centric but I also have interest in other languages, particularly Ruby, probably because of its nature..and dynamism...which again, is related to the latest version of .Net - .Net 3.0. I will try to post my experiences with Ruby as well. So, lets get rolling....</content><link rel='replies' type='application/atom+xml' href='http://rajkwatra.blogspot.com/feeds/5615670635451569953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/25106554/5615670635451569953' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/5615670635451569953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25106554/posts/default/5615670635451569953'/><link rel='alternate' type='text/html' href='http://rajkwatra.blogspot.com/2007/05/it-was-difficult-to-decide-first-topic.html' title='First Post'/><author><name>Rajdeep Kwatra</name><uri>http://www.blogger.com/profile/12729138165838394082</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>