<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Ken O' Bonn</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/kenobonn/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/kenobonn/feed.xml</link>
    <description />
    <lastBuildDate>Thu, 09 Apr 2015 20:45:29 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>HttpHandler for Excel file download</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/httphandler-for-excel-file-download</link>
      <pubDate>Sun, 09 Nov 2014 12:44:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2014/11/09/httphandler-for-excel-file-download/</guid>
      <description><![CDATA[// 
When providing html links to XML&nbsp;files, typically the HTTP Headers will&nbsp;set...]]></description>
      <content:encoded><![CDATA[<script type="text/javascript" language="javascript">// <![CDATA[
        function CopyCode(elemName) { var obj = document.getElementById(elemName); window.clipboardData.setData("Text", obj.innerText) }
// ]]]]><![CDATA[></script>
<p>When providing html links to XML&nbsp;files, typically the HTTP Headers will&nbsp;set ContentType = Plain / Text, and show up in the browser as text. The need is to provide links to&nbsp;Excel files in XML format, and prompt the user to download locally. Once downloaded, the user&nbsp;may&nbsp;open the XML file&nbsp;in Excel.</p>
<p>An alternate solution is to set the MIME type for files of XML extension, and open directly as a link from the browser yet rendered in Excel. This is less preferable as it dictates the behavior of all XML files, whereas the scope is for specific files as Excel and unspecified files to continue having default XML rendering.</p>
<p><strong>SOLUTION: CUSTOM HEADERS</strong></p>
<ul>
<li>Custom Headers to specify download as an attachment can easily be achieved by creating an Http Handler, and associating the path of required files. An Http Module could be written, but that is specific to the file extension, and there is need for some XML files to be treated as text, and others as Excel. In cases like this, a Handler is much more efficient than a Module, because it&rsquo;s execution is limited to the path.</li>
<li>We simply want to add a header for Content-Disposition as an attachment, and to specify the appropriate filename for download.</li>
<li>The remainder of this blog post is a demo of code for this solution. If you wish, you may download the attached ZIP file to see the completed solution.</li>
</ul>
<p><strong>CODE: HTTP HANDLER</strong></p>
<p>&nbsp;In Visual Studio 2013, create a class library project called &ldquo;WebCustomHttpHandler&rdquo; and add a class &ldquo;DownloadFileHandler&rdquo; as per code given below. Error handling / comments removed for brevity.</p>
<!-- BEGIN CODE 1 -->
<table style="background-color: #ededed;" border="2" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>
<div class="CopyCodeButton">
<table style="width: 100%;">
<tbody>
<tr>
<td style="align: left;">DownloadFileHandler.cs</td>
<td style="text-align: right;"><a class="copyCode" title="Copy Code" href="javascript:CopyCode('ctl00_HttpHandler1');"> Copy Code</a></td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td class="libSQLcode" style="word-wrap: break-word; word-break: break-all;">
<p id="ctl00_HttpHandler1">&nbsp;<code class="csharp">//Add a reference to System.Web in the project references.<br /> using System.Linq;<br /> using System.Web;<br /> <br /> namespace WebCustomHttpHandler<br /> {<br /> class DownloadFileHandler : IHttpHandler<br /> {<br /> public bool IsReusable<br /> {get { return true; } }<br /> <br /> public void ProcessRequest(HttpContext context)<br /> {<br /> var filePath = context.Request.FilePath;<br /> var fileName = filePath.Split('/').Last();<br /> context.Response.ContentType = "text/plain";<br /> context.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);<br /> context.Response.WriteFile(filePath);<br /> }<br /> }<br /> }<br />&nbsp;</code></p>
</td>
</tr>
</tbody>
</table>
<!-- END CODE 1 -->
<p><strong>CODE: WEB SITE</strong></p>
<p>Add a reference within the web site to the class library project created earlier. This is not required, but will simplify deployment by ensuring the DLL for the Http Handler is copied to the bin directory of the web site.<br />Where applicable, simply provide a link to the XML file for download.<br />Edit the web.config file as per below. Adjust values for the path as required.</p>
<!-- BEGIN CODE 2 -->
<table style="background-color: #ededed;" border="2" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>
<div class="CopyCodeButton">
<table style="width: 100%;">
<tbody>
<tr>
<td style="align: left;">Web.Config</td>
<td style="text-align: right;"><a class="copyCode" title="Copy Code" href="javascript:CopyCode('ctl00_HttpHandler2');"> Copy Code</a></td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td class="libSQLcode" style="word-break: break-all; word-wrap: break-word;">
<p id="ctl00_HttpHandler2"><code class="csharp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;configuration&gt;<br />&nbsp; &lt;system.web&gt;<br />&nbsp;&nbsp;&nbsp; &lt;compilation debug="true" targetFramework="4.5" /&gt;<br />&nbsp; &lt;/system.web&gt;<br />&nbsp; &lt;system.webServer&gt;<br />&nbsp;&nbsp;&nbsp; &lt;handlers&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name="ExcelHandler" verb="GET"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path="DemoExcelAsXmlSpreadsheet1.xml"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="WebCustomHttpHandler.DownloadFileHandler, WebCustomHttpHandler"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resourceType="File" /&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/handlers&gt;<br />&nbsp; &lt;/system.webServer&gt;<br />&lt;/configuration&gt;</code></p>
</td>
</tr>
</tbody>
</table>
<!-- END CODE 2 -->
<p><strong>CODE: CONFIGURATION - IIS</strong></p>
<p>The IIS server needs to have a Http Handler configured for the web site. This is done using the command appcmd.exe.<br />Reference <a href="https://technet.microsoft.com/en-us/library/jj635852.aspx">https://technet.microsoft.com/en-us/library/jj635852.aspx</a><br />Run this in a batch file, optionally output to a log file and / or parameterize the site name, handler name, etc.</p>
<!-- BEGIN CODE 3 -->
<table style="background-color: #ededed;" border="2" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>
<div class="CopyCodeButton">
<table style="width: 100%;">
<tbody>
<tr>
<td style="align: left;">InstallHttpHandler.bat</td>
<td style="text-align: right;"><a class="copyCode" title="Copy Code" href="javascript:CopyCode('ctl00_HttpHandler3');"> Copy Code</a></td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td class="libSQLcode" style="word-break: break-all; word-wrap: break-word;">
<p id="ctl00_HttpHandler3">ECHO OFF<br />REM Remove existing handler mapping.<br />%windir%\system32\inetsrv\appcmd set config "DemoExcel" /section:system.webServer/handlers /-"[name='ExcelXmlFile']"<br />REM Add new handler mapping.<br />%windir%\system32\inetsrv\appcmd set config "DemoExcel" /section:system.webServer/handlers /+"[name='ExcelXmlFile',path='DemoExcelAsXmlSpreadsheet1.xml',verb='GET',type='WebCustomHttpHandler.DownloadFileHandler, WebCustomHttpHandler',ResourceType='File']"</p>
</td>
</tr>
</tbody>
</table>
<!-- END CODE 3 -->
<p><strong>REFERENCES</strong></p>
<p>Appcmd.exe (IIS 8)</p>
<p><a href="https://technet.microsoft.com/en-us/library/jj635852.aspx">https://technet.microsoft.com/en-us/library/jj635852.aspx</a></p>
<p>Add a Managed Handler Mapping (IIS 7)<br /><a href="https://technet.microsoft.com/en-us/library/cc753249(v=WS.10).aspx">https://technet.microsoft.com/en-us/library/cc753249(v=WS.10).aspx</a></p>
<p>Remove a Handler Mapping (IIS 7)<br /><a href="https://technet.microsoft.com/en-us/library/cc754894(v=WS.10).aspx">https://technet.microsoft.com/en-us/library/cc754894(v=WS.10).aspx</a></p>
<p><br />&nbsp;</p>
<p><strong>CONCLUSION</strong></p>
<p>It's not difficult at all to create a custom Http Handler. In design of this type of functionality, it is advisable to understand when you would want a Http Handler versus Http Module.<br />&nbsp;</p>
<p>&nbsp;</p>
<p><br />&nbsp;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/57/08/72/OpenExcelFileDemo.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-57-08-72/OpenExcelFileDemo.zip">OpenExcelFileDemo.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Create Event Log Sources using PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/create-event-log-sources-using-powershell</link>
      <pubDate>Sat, 29 Mar 2014 09:50:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2014/03/29/create-event-log-sources-using-powershell/</guid>
      <description><![CDATA[Web applications, Windows services, and other applications frequently need to write to an event log...]]></description>
      <content:encoded><![CDATA[<p>Web applications, Windows services, and other applications frequently need to write to an event log on the server. In many cases, it is beneficial to create new event log sources or even new event logs. This allows easier searching for events. Another benefit, in the case of new event logs, this enables custom management of event log size or other maintenance needs. In order to create an event log or source, administrative privileges is required. Consequently, <span style="text-decoration: underline;"><strong>you should never write your application so that it creates an event log or source at run time</strong></span>, because that would require your application to run under administrative privileges. Requiring applications to run as administrator violates a critical rule:&nbsp;Applications should run under an account having least privileges necessary, so that if the service account is compromised, an attacker would not gain administrative privileges over your server.</p>
<p>By having event log sources already created, the application code will write to the event log, assuming the event log source already exists. The developer can choose to write the code in a try / catch block with error handling to alternatively write to a standard event log, text file, database log, etc. according to their design, but that is out of scope for this post. I will focus only on the PowerShell script and execution of it.</p>
<p>This blog posting provides a code example on how to author a PowerShell script that will create event logs and event log sources. If the source already exists, it will give a message indicating such. This script is designed to be executed at time of install of the application, not during run time of the application, thus <strong>eliminating the potential security vulnerability of elevation of privileges</strong>.</p>
<p>This PowerShell script works without user input, where the application configuration is entered directly into the script as an <span style="background-color: #ffcc00;">array of comma delimited pairs of event logs,event log sources. Simply modify the values in the variable $eventSources and run it</span>. In the example given, the $eventSources is configured to create 2 sources on the Application log, then create 2 new event logs with corresponding sources.</p>
<p>Note#1: For the development and test teams, it may be beneficial to use the PowerShell command <strong>Remove-eventLog</strong> with appropriate parameter <strong>-LogName</strong>&nbsp;to specify the event log name, or to use the parameter <strong>-Source</strong> to retain the event log but delete only the event log source. I highly recommend you become familiar with the usage of this command before&nbsp;attempting to delete anything. This functionality is useful for developing and testing purposes of this script, but is not part of the purpose of this blog, so be careful if you use this command for production systems.</p>
<p>Note#2&nbsp;On some systems, there may be a policy that denies execution of PowerShell scripts. You can override this when calling the PowerShell.exe command by adding&nbsp;<strong>-ExecutionPolicy ByPass</strong>&nbsp;as a parameter. Policies are there for a reason, but if the script is fully reviewed, tested, and certified, it may be helpful to specify this parameter.</p>
<p>Note#3. Although it is possible to create event logs having greater than 8 characters in the name, if you attempt to create a second event log where the first 8 characters are the same as an existing event log, you will get an error.</p>
<table style="width: 464px; height: 363px;" border="2" cellspacing="2" cellpadding="2" align="left">
<tbody>
<tr>
<td>
<pre class="scroll"><code class="csharp"># -----------------------------------------------------------------------------<br /> # CreateEventLogSources.ps1<br /> # AUTHOR: Ken O. Bonn<br /> # DATE: 03/29/2014<br /> # PURPOSE: Ensure Event Logs and Sources exist for application "MyApplication" to write events to.<br /> # NOTES: (1)The only customization required is to specify your event log, source pair.<br /> # (2)This can be run from a command prompt as below, assuming policy allows that<br /> # PowerShell.exe -File CreateEventLogSources.ps1<br /> # -----------------------------------------------------------------------------<br /> #<br /> # -----------------------------------------------------------------------------<br /> # CREATE EVENT LOG SOURCES IF THEY DO NOT EXIST.<br /> # -----------------------------------------------------------------------------<br /> #<br /> #eventSources is an array of comma delimited strings containing the Event Log followed by the event source.<br /> <br /> $eventSources = @(<br /> "<span style="background-color: #ffcc00;">Application,MyApplicationSource1</span>",<br /> "<span style="background-color: #ffcc00;">Application,MyApplicationSource2</span>",<br /> "<span style="background-color: #ffcc00;">MyAppLg1,MyApplicationSource3</span>",<br /> "<span style="background-color: #ffcc00;">MyAppLg1,MyApplicationSource4</span>",<br /> "<span style="background-color: #ffcc00;">MyAppLg2,MyApplicationSource5</span>"<br /> )<br /> <br /> #Loop through each event log,source pair to create the source on the specified log if it does not exist.<br /> <br /> foreach($logSource in $eventSources) {<br /> $log = $logSource.split(",")[0]<br /> $source = $logSource.split(",")[1]<br /> if ([System.Diagnostics.EventLog]::SourceExists($source) -eq $false) {<br /> write-host "Creating event source $source on event log $log"<br /> [System.Diagnostics.EventLog]::CreateEventSource($source, $log)<br /> write-host -foregroundcolor green "Event source $source created"<br /> }<br /> else<br /> {<br /> write-host -foregroundcolor yellow "Warning: Event source $source already exists. Cannot create this source on Event log $log"<br /> }<br /> }<br /> </code></pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/51/20/71/CreateEventLogSources.ps1" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-51-20-71/CreateEventLogSources.ps1">CreateEventLogSources.ps1</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Implementing "Most Recently Used" (MRU) in web sites</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/implementing-most-recently-used-mru-in-web-sites</link>
      <pubDate>Mon, 23 Dec 2013 17:06:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2013/12/23/implementing-most-recently-used-mru-in-web-sites/</guid>
      <description><![CDATA[Internet Explorer 9 (IE 9) introduced the ability to "Pin" a web site to the taskbar. With just...]]></description>
      <content:encoded><![CDATA[<p>Internet Explorer 9 (IE 9) introduced the ability to "Pin" a web site to the taskbar. With just a&nbsp;few images, meta tags, JavaScript, and JQuery, web content developers can implement the equivalent of a "Most Recently Used" (MRU)&nbsp;list of pages to their web sites. In so doing, users who frequently return to the same page can have a dynamic jump list to save efforts in navigation.</p>
<p>This&nbsp;blog post will teach you how to easily pin your site to the task bar, and to enable dynamic jump lists to enable MRU functionality. As there are related concepts of pinning via meta tags, I'm including a couple bonus features, which will be explained along the way&nbsp;as optional. The main features of this article are in yellow highlight below, and the bonus features are not highlighted.</p>
<ol>
<li><span style="background-color: #ffff00;">Pin to task bar.</span></li>
<li>Pin static jump list to task bar.</li>
<li><span style="background-color: #ffff00;">Pin dynamic jump list (MRU) of task bar.</span></li>
<li>Pin to Windows start screen.</li>
</ol>
<h2>INCLUDED IN THIS ARTICLE:</h2>
<ol>
<li><a href="#USER_HOW_WHY">User Benefits: How and why?</a></li>
<li><a href="#MRU_METHODS">MRU Methods</a></li>
<ol>
<li><a href="#Navigate_By_Key_Of_A_Query_String_Parameter">Navigate by key of query String parameter</a></li>
<li><a href="#Navigate_By_Attribute_Of_A_Page">Navigate by attribute of page</a></li>
<li><a href="#Navigate_By_Post">Navigate by post</a></li>
</ol>
<li><a href="#DEVELOPER_GIVE_ME_THE_CODE">Developer: Give me the code!</a></li>
<ol>
<li><a href="#META_TAGS_AND_XML">Meta Tags and XML</a></li>
<li><a href="#JavaScript">JavaScript</a></li>
<li><a href="#JQuery">JQuery</a></li>
<li><a href="#Images">Images</a></li>
</ol>
<li><a href="#DEVELOPER_REWORK_SUPPORT_USER_FRIENDLY_LISTS">Developer: Rework to support user friendly lists</a></li>
<ol>
<li><a href="#JAVASCRIPT_CHANGES">JavaScript Changes</a></li>
<li><a href="#JQUERY_CHANGES">JQuery Changes</a></li>
<li><a href="#FINAL_VIEW">Final View</a></li>
</ol>
<li><a href="#SPECIAL_CONSIDERATIONS">Special Considerations</a></li>
<li><a href="#REFERENCES">References</a></li>
<li><a href="#CONCLUSION">Conclusion</a></li>
</ol>
<h2><strong><a name="USER_HOW_WHY"></a>USER BENEFITS: HOW AND WHY</strong></h2>
<p>Users&nbsp;want to have an easy way to return to their favorite site (much like CTRL-D works to save a favorite page), yet&nbsp;they visit the same page multiple times (much like storing history). If you imagine a shopping experience, a user might have found 5 items but not added them to their shopping cart. The next day, instead of searching the history for the site,&nbsp;they might simply find the item bookmarked to the actual page!</p>
<ul>
<li><strong>Pinning to the task bar</strong> will give the user the ability to quickly reference the site from the task bar. The code provided in this article will enable users&nbsp;with the ability to see a static list of pages (such as help) and a dynamic list of pages (such as MRU pages).</li>
<li><strong>Pinning to the Windows start screen</strong> will give the user the ability to find the site simply by searching for it as an application&nbsp;(shortcut, Windows-Q) or as a tile on the windows start screen.</li>
</ul>
<h2><a name="MRU_METHODS"></a>MRU METHODS</h2>
<p>There are&nbsp;varying methods of pinning to the task bar and implementing MRU functionality, below is high level approach for three methods.&nbsp;The first method&nbsp;will get you quickly up to speed with working code and understand the concepts. The second&nbsp;method will be the most useful one, as this provides a friendly name to pin the pages to.&nbsp;The third method below possibly has limited value, despite ability to save queries, because the jump list functionality might best be used for specific results, not a table of results.</p>
<p>The biggest challenge to all of the methods below is to come up with a user friendly means to anchor the text of the MRU link to something that is meaningful to them.</p>
<h3><strong><a name="Navigate_By_Key_Of_A_Query_String_Parameter"></a>NAVIGATE BY KEY OF QUERY STRING PARAMETER</strong></h3>
<p>The first method in this blog is based on navigating through pinned jump lists whereby the friendly name for the jump list is derived from a query string parameter. This should be a unique key value to differentiate from other pages. For example, in case a book were pinned, the query string parameter might use the ISBN number for a key.</p>
<h3><strong><a name="Navigate_By_Attribute_Of_A_Page"></a>NAVIGATE BY ATTRIBUTE OF A PAGE</strong></h3>
<p>The next method in this blog will have the jump list friendly name display a key value that is embedded in the page. Using the example of a book again, we might realize that few people memorize ISBN numbers, so we instead want to display the name of the book. This name is part of the text within the document, and will be extracted from the page by Element ID.</p>
<h3><strong><a name="Navigate_By_Post"></a>NAVIGATE&nbsp; BY POST</strong></h3>
<p>The final method discussed is not being presented with code for this blog. It realizes that some people may want to refer back to common searches that they perform. In this case, you will want to enable searching by post and by query string, as the jump list is based on query string. This will get the parameters during the post, and the web site author will have to use some imagination to find a friendly name to display in the jump list. I might include code for this in a later blog, but before writing the code, take a moment to evaluate alternatives. It might best be achieved by providing a static jump list to the search page, and have the search page itself offer links to recent searches. As there is a finite number of items in a jump list, the developer will want to maximize use of the entries for the best user experience. It would be easy to clutter the jump list with search history that could be useless if the user does not know what the searches represent, as seen by the title.</p>
<h2><strong><a name="DEVELOPER_GIVE_ME_THE_CODE"></a>DEVELOPER: GIVE ME THE CODE!</strong></h2>
<p>The set of code below is an example of how to pin to the taskbar, as well as pin to the Windows 8 start screen tile. Although the purpose of this blog is to pin to the taskbar, with just a few extra lines of code, you can have a nice Start Screen Tile.</p>
<p>To understand the code, you should follow along this article according to the first&nbsp;version&nbsp;as the MRU is associated to the query string, and then the refactored code as the MRU is associated to&nbsp;the textual value of an element in the page. By following along, it is hoped to quickly teach the basics of pinning. Attached to this article is all the demo code in a VSTS solution, as many will learn faster by just&nbsp;taking the code&nbsp;directly from&nbsp;a working project.&nbsp;</p>
<h3><strong><a name="META_TAGS_AND_XML"></a>META TAGS AND XML</strong></h3>
<p>The meta tags below apply to the home page, or the page that is used to pin the site. I am including additional tags for pinning to the Start Screen Tile for IE 9/10 versus IE 11. The XML file could alternatively be implemented as meta tags, but the choice of an external file is due to the fact that it is cached static content.</p>
<p><strong>Site home page, to be pinned. This is within the header section.</strong></p>
<pre class="scroll"><code class="html">&lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;<br /> &lt;meta name="msapplication-config" content="/BrowserConfig.xml" /&gt;<br /> &lt;meta name="application-name" content="My Application Pin Demo" /&gt;<br /> &lt;meta name="msapplication-tooltip" content="MyApplication Web Pages" /&gt;<br /> &lt;meta name="msapplication-starturl" content="/Home.aspx" /&gt;<br /> &lt;meta content="name=Search for Exams;<br /> action-uri=/ExamSearch.aspx;<br /> icon-uri=/Static/Images/MyApplication-SiteIcon.ico;<br /> window-type=self"<br /> name="msapplication-task" /&gt;<br /> <br /> &lt;meta name="msapplication-TileImage" content="/Static/Images/MyApplication-Square.png" /&gt;<br /> </code></pre>
<p><strong>browserconfig.xml</strong></p>
<pre class="scroll"><code class="html">&lt;?xml version="1.0" encoding="utf-8"?&gt;<br /> &lt;browserconfig&gt;<br /> &lt;msapplication&gt;<br /> &lt;tile&gt;<br /> &lt;square70x70logo src="https://blogs.msdn.com/Static/Images/MyApplication-Tiny$.png"/&gt;<br /> &lt;square150x150logo src="https://blogs.msdn.com/Static/Images/MyApplication-Square$.png"/&gt;<br /> &lt;wide310x150logo src="https://blogs.msdn.com/Static/Images/MyApplication-Wide$.png"/&gt;<br /> &lt;square310x310logo src="https://blogs.msdn.com/Static/Images/MyApplication-Large$.png"/&gt;<br /> &lt;TileColor&gt;#ffc533&lt;/TileColor&gt;<br /> &lt;/tile&gt;<br /> &lt;/msapplication&gt;<br /> &lt;/browserconfig&gt;</code></pre>
<h3><strong><a name="JavaScript"></a>JAVASCRIPT</strong></h3>
<p>The include JavaScript is intended to be a simple method that is in an external file called "MyApplicationJSLibrary.js". There are some parameters that are coded internal to the function which you could expose if it were necessary to be configurable. For example, the WindowType attribute given below as&nbsp;"Self" could be "tab" or "window", or a parameter so that it could vary by page (see references section for link to documentation of this method). In this example, I am simplifying it so that only the minimum parameters need to be sent.</p>
<p>If you were to include this functionality for all pages, the jump list might be less predictable to the user, as there is a limited number of links by default. Notice that application specific logic is in the JavaScript, to represent the ExamId as well as other application specific text. This is generally a bad practice, if one were making a reusable library function to share with the developer community. However, we are assuming&nbsp;that in your web site, you are implementing "Most Recently Used" functionality for a limited number of pages, possibly even just one page in the entire web site.</p>
<pre class="scroll"><code class="js">// FILENAME: MyApplicationJsLibrary.js<br /> function MyApplicationJsLibrary() {<br /> /// &lt;summary&gt;MyApplicationJsLibrary is methods for pinning to the taskbar, such as for jump lists.&lt;/summary&gt;<br /> this.pinExam = function (jumpListTitle) {<br /> /// &lt;summary&gt;pinExam will add the current Exam.aspx page to the jump list of the task bar, referenced by Exam number.&lt;/summary&gt;<br /> /// &lt;param name="jumpListTitle" type="String"&gt;Optional. Entry title that is displayed in the Jump List. If not provided, jumpListTitle will be derived from the query string parameter.&lt;/param&gt;<br /> try {<br /> if (window.external.msIsSiteMode()) {<br /> var webUrl = window.location.href;<br /> var friendlyTitle;<br /> var webPage = window.external;<br /> if (jumpListTitle == undefined) {<br /> friendlyTitle = "ExamID " + getQuerystringNameValue(webUrl, 'ExamId');<br /> }<br /> else {<br /> friendlyTitle = jumpListTitle;<br /> }<br /> webPage.msSiteModeCreateJumpList("My Recent Exams");<br /> webPage.msSiteModeAddJumpListItem(<br /> friendlyTitle, webUrl, "/Static/Images/MyApplication-SiteIcon.ico", "self");<br /> }<br /> }<br /> catch (ex) {<br /> }<br /> }<br /> <br /> //PRIVATE METHODS (helper functions)<br /> function getQuerystringNameValue(webUrl, parameterName) {<br /> /// &lt;summary&gt;Get parameter from a url, which assumes querystring objects are name=value pairs, this will not work if querystring parameter is of format having just parameter name.&lt;/summary&gt;<br /> /// &lt;param name="webUrl" type="String"&gt;Full Web URL, including querystring.&lt;/param&gt;<br /> /// &lt;param name="parameterName" type="String"&gt;Querystring parameter name to extract value from.&lt;/param&gt;<br /> /// &lt;returns type="String" /&gt;<br /> var queryStringArray = webUrl.split("?");<br /> var queryStringParamArray = queryStringArray[1].split("&amp;");<br /> var nameValue = null;<br /> <br /> for (var iParamIndex = 0; iParamIndex &lt; queryStringParamArray.length; iParamIndex++) {<br /> queryStringNameValueArray = queryStringParamArray[iParamIndex].split("=");<br /> if (parameterName == queryStringNameValueArray[0]) {<br /> nameValue = queryStringNameValueArray[1];<br /> }<br /> }<br /> return nameValue;<br /> }<br /> }<br /> </code></pre>
<h3><strong><a name="JQuery"></a>JQUERY</strong></h3>
<p>There are several methods to pin the page to the taskbar using JavaScript. My preference is to use the JavaScript library JQuery. The code attached to this post uses&nbsp;JQuery as referenced from the CDN, which is best for caching instead of publishing your local version of JQuery.&nbsp;The simplest approach would be immediately executing JavaScript&nbsp;code, which&nbsp;is a bad practice&nbsp;that should always be avoided, especially&nbsp;whenever code accesses&nbsp;DOM elements. A better approach is to ensure that the page has loaded, then execute the function. An example of this would be as follows, to embed code example into the header of the&nbsp;web page that you wish to implement MRU for:</p>
<pre class="scroll"><code class="js">&lt;script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"&gt;&lt;/script&gt;<br /> &lt;script src="https://blogs.msdn.com/Static/JS/MyApplicationJsLibrary.js"&gt;&lt;/script&gt;<br /> &lt;script&gt;<br /> $(document).ready(function () {<br /> var pin = new MyApplicationJsLibrary();<br /> pin.pinExam();<br /> })<br /> &lt;/script&gt;<br /> </code></pre>
<h3><strong><a name="Images"></a>IMAGES</strong></h3>
<p>We want images for icons to appear by your browser address bar, history, pinned task bar, and jump lists. We also want images for the Start Screen Tile. The table of&nbsp;image sizes below apply to features as described in this post, as a recommended first draft during development. As you are developing the site, you will be testing images repeatedly, experimenting first with the images at 80% size, then 100%. The .png files could be other image types, but I favor this format for purposes of this post.&nbsp;If the cache seems to interfere with the development, a link to another person's blog about how to clear the cache is provided in the references section at the end of this post. For implementing MRU functionality, all you really need is the .ico file, and to take it further to implement start screen tile, the .png files are necessary.</p>
<p>To see what we are trying to accomplish with the icon images, the screen grabs below which were taken by right clicking the pinned site from the taskbar and by viewing the page in a browser window. The icons should be tested at all locations in the jump list, and all locations in the browser. I have observed times when the image looks great in the taskbar, but blurry in the address bar, or vice versa. It is also possible to use different icon files for different places, as referenced by the meta tags, in case you really need to optimize the images.</p>
<p>As you are developing the site, you may need several iterations of testing the icon images, where the differences may be subtle. If it appears that your changes are either not being accepted, or are too subtle to detect a difference, I use two approaches. The first approach is to have an icon handy that is radically different from the published icon, and temporarily load that in your browser before publishing the new image. This will verify that there was a difference. Sometimes though, you might not be getting refreshed icons loaded, so clear the browser cache (Tools, Delete Browsing History...).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/3630.PinToTaskBarDemo1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/3630.PinToTaskBarDemo1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/3630.PinToTaskBarDemo1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/315x379/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/3630.PinToTaskBarDemo1.png" alt="" border="0" /></a></p>
<p>The browser will represent the icon images at the top of the page as seen below.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5873.PinToTaskBarDemo1A.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5873.PinToTaskBarDemo1A.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5873.PinToTaskBarDemo1A.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x88/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5873.PinToTaskBarDemo1A.png" alt="" border="0" /></a></p>
<p>The secondary (optional) part of this article has to do with images for the Start Screen Tile, which is implemented by the .png files and not the .ico files detailed above. Depending on your system, you might see two possible sizes, Small and Medium, or 4 possible sizes, <strong>Small</strong>, <strong>Medium</strong>, <strong>Wide</strong>, <strong>Large</strong>. IE11 supports the 4 sizes, as rendered by the browserconfig.xml, and for IE9/10, only 2 sizes are supported, as rendered by the misapplication-TileImage meta tag.</p>
<p>Much like for icon images, the .png images used for the Start Screen Tiles will need to be tested and very likely refactored. In the course of development, the images will need to have their cache cleared, which is not the same cache as in the normal browser. To clear the cache, open the browser from the desktop, and hit the Windows-C keys to display the charms bar for the browser, and choose the Settings as it applies to Internet Explorer. Choose Options and then select the History to select browsing data that you want to delete. In the History taskbar, delete cached images, cookies and browsing history and hit the delete button.</p>
<p>Troubleshooting can be sometimes difficult, but some known issues are mentioned here.</p>
<ul>
<li>If your site expects the 4 sizes, yet you do not see all of them, it could be caused by incorrect size of the images. For example, if the large (square310x310logo) image is only 120x120 pixels, it will not be available, and you will see only 3 images.</li>
<li>If your site expects the 4 sizes, but only see 2 of them, verify that the link to the browserconfig.xml file is correct. The site will still function, but failure to find the browserconfig.xml file will result in implementing the deprecated IE10 meta tag, which supports only two sizes.</li>
</ul>
<p>Image size table.</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="165">
<p><strong>META TAG</strong></p>
</td>
<td valign="top" width="278">
<p><strong>PURPOSE / NOTES</strong></p>
</td>
<td valign="top" width="143">
<p><strong>IMAGE1 80%</strong></p>
</td>
<td valign="top" width="143">
<p><strong>IMAGE2 100%</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="165">
<p><strong>square70x70logo</strong></p>
</td>
<td valign="top" width="278">
<p>Small&nbsp;Tile, .png file, no background color.</p>
</td>
<td valign="top" width="143">
<p>56 x&nbsp;56 pixels</p>
</td>
<td valign="top" width="143">
<p>70 x 70 pixels</p>
</td>
</tr>
<tr>
<td valign="top" width="165">
<p><strong>square150x150logo</strong></p>
</td>
<td valign="top" width="278">
<p>Medium Tile, .png file, no background color.</p>
</td>
<td valign="top" width="143">
<p>120 x 120 pixels</p>
</td>
<td valign="top" width="143">
<p>150 x 150 pixels</p>
</td>
</tr>
<tr>
<td valign="top" width="165">
<p><strong>wide310x150logo</strong></p>
</td>
<td valign="top" width="278">
<p>Wide Tile, .png file, no background color.</p>
</td>
<td valign="top" width="143">
<p>248 x 120 pixels</p>
</td>
<td valign="top" width="143">
<p>310 x 150 pixels</p>
</td>
</tr>
<tr>
<td valign="top" width="165">
<p><strong>square310x310logo</strong></p>
</td>
<td valign="top" width="278">
<p>Large Tile, .png file, no background color.</p>
</td>
<td valign="top" width="143">
<p>248 x 248 pixels</p>
</td>
<td valign="top" width="143">
<p>310 x 310 pixels</p>
</td>
</tr>
<tr>
<td valign="top" width="165">
<p><strong>Favicon.ico</strong></p>
</td>
<td valign="top" width="278">
<p>Icon. You may generate this using <a href="https://www.xiconeditor.com/" target="_blank">https://www.xiconeditor.com/</a><br />&nbsp; using appropriate background color.</p>
</td>
<td valign="top" width="143">
<p>32 x 32 pixel icon</p>
</td>
<td valign="top" width="143">
<p>64 x 64 pixel icon</p>
</td>
</tr>
</tbody>
</table>
<h2><a name="DEVELOPER_REWORK_SUPPORT_USER_FRIENDLY_LISTS"></a>Developer: Rework to support user friendly lists</h2>
<p>Now that we understand the basic concepts, we might want to enhance the user experience to support MRU list with more friendly names, that are derived from the attributes of a page instead of the query string. Effectively, this can be perceived as the difference between users access by key name instead of key value. To do this, the following code changes would have to be done for the JavaScript function in the .js file, as well as the JQuery code on the page being indexed for MRU.</p>
<h3><a name="JAVASCRIPT_CHANGES"></a>JavaScript Changes:</h3>
<p>The original JavaScript presented above already supports user friendly lists, as the method pinExam effectively acts as an overloaded function by having logic to determine if the parameter jumpListTitle is provided or not. To ensure your code is as lightweight as possible, it is suggested that you remove the condition and implement the parameter or not, depending on your needs. As a reminder, your site is not using this code as a reusable library, rather a specific implementation of MRU list, so please take the code and tweak it according to your specific needs, removing any dead code.</p>
<h3><a name="JQUERY_CHANGES"></a>JQuery Changes:</h3>
<p>Assuming there is a form element whose ID is txtExamTitle, simply modifying the previously provided call to pinExam as below will implement the necessary change to pin by friendly name. Here, it is important to realize that this code would not work unless the entire DOM was loaded, so that the value for txtExamTitle is derived from the query string. Also, realize that this is behind the scenes logic that happens at time of page load, if it were necessary to pin to a title derived from user entry, the logic would have to be changed.</p>
<pre class="scroll"><code class="js">pin.pinExam($("#txtExamTitle").val());</code></pre>
<p>Sometimes, in ASP.NET, the clientID is not always predictable, so you could remove the client side derivation of the value to server side, as per &lt;%=txtExamTitle.Text%&gt;. Do yourself a favor, and make it predictable without having to resort to server side code embedded in your JavaScript and/or JQuery code. An ASP.NET textbox control could have the attribute ClientIDMode="Static" set to help if this were an issue.</p>
<h3><a name="FINAL_VIEW"></a>Final View:</h3>
<p>After some simple refactoring of the code, and using the friendly name of the title of the exams being displayed, we see the equivalent MRU jump list represented as below. Notice that the text of the titles exceeds the boundaries of the container. This minor issue is mitigated by users being able to hover over the jump list to see the full text of the title.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/8306.PinToTaskBarDemo2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/8306.PinToTaskBarDemo2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/8306.PinToTaskBarDemo2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x380/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/8306.PinToTaskBarDemo2.png" alt="" border="0" /></a></p>
<h2><strong><a name="SPECIAL_CONSIDERATIONS"></a>SPECIAL CONSIDERATIONS</strong></h2>
<p>In case of pinning to pages that require active sessions, or redirection after required login, you will have to alter your web page design, or else have pinning of limited value.</p>
<h2><a name="REFERENCES"></a>REFERENCES</h2>
<p>A few useful links that I use for pinning web sites and for authoring this blog post.</p>
<p><a title="Pinned sites for the desktop" href="https://msdn.microsoft.com/en-us/library/ie/dn455117(v=vs.85).aspx" target="_blank">Pinned sites for the desktop</a>. MSDN documentation, a must read.</p>
<p><a href="https://msdn.microsoft.com/en-us/library/ff976312(v=vs.85).aspx">msSiteModeAddJumpListItem method</a>. MSDN documentation on MRU part of the&nbsp;code.</p>
<p><a title="X-Icon Editor" href="https://www.xiconeditor.com/" target="_blank">X-Icon Editor</a>. &nbsp;I use this site to convert the source .png files to an .ico file, such as for favicon.ico.</p>
<p><a href="https://www.howto-connect.com/clear-cache-in-windows-8/">How to Clear Cache in Windows 8 Step by Step</a>. Changing image references while developing sometimes shows old code. Clear the cache if you see unexpected results.</p>
<p><a href="https://msdn.microsoft.com/en-us/library/vstudio/bb514138(v=vs.120).aspx">How to: Create JavaScript XML Documentation Comments</a>. Always document your code! Some simple tips to enable IntelliSense.</p>
<h2><strong><a name="CONCLUSION"></a>CONCLUSION</strong></h2>
<p>This explains how&nbsp;to implement "Most Recently Used" functionality in your web sites. This blog post&nbsp;is designed to get you quickly up to speed on the basic concepts, with working code. This covers Windows 8&nbsp;static tiles, and pinning to the task bar using IE 9,10, and 11.</p>
<p>A lot of functionality was covered, including pin to taskbar, static jump lists, dynamic jump lists, most recently used web pages, start screen tiles, and searching for web site locally as if it were a windows store application.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/47/14/02/PinToTaskbar.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-47-14-02/PinToTaskbar.zip">PinToTaskbar.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Code Snippets in SQL Server 2012 For Greater Team Productivity</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/code-snippets-in-sql-server-2012-for-greater-team-productivity</link>
      <pubDate>Wed, 15 May 2013 11:06:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2013/05/15/code-snippets-in-sql-server-2012-for-greater-team-productivity/</guid>
      <description><![CDATA[Included in this article:

What are snippets?
Overview
Configuration
How to use snippets
How...]]></description>
      <content:encoded><![CDATA[<pre class="scroll">Included in this article:</pre>
<ol>
<li><a href="#WhatAreSnippets">What are snippets?</a></li>
<li><a href="#Overview">Overview</a></li>
<li><a href="#Configuration">Configuration</a></li>
<li><a href="#HowToUseSnippets">How to use snippets</a></li>
<li><a href="#HowToCreateSnippets">How to create snippets</a></li>
<li><a href="#Example1SequenceFinder">Example Snippet - Find tables using Sequences</a></li>
</ol>
<p><strong><a name="WhatAreSnippets"></a>WHAT ARE SNIPPETS?</strong></p>
<p>SQL Server Code Snippets are what they sound like - they are snippets of code that may be accessed easily through a program such as SQL Server Management Studio or Visual Studio Team System. For the purposes of this article, we are focussing on using them in SQL Server Management Studio, in the 2012 edition.</p>
<p><strong><a name="Overview"></a>OVERVIEW:</strong></p>
<p>In my team, we use&nbsp;SQL Code&nbsp;Snippets in SQL Server 2012 to save time for authoring queries that may be reused many times in our development cycle. This post is to detail how to use Snippets in SQL 2012, and a simple means to share the snippets among the team. We gain a lot of productivity by sharing our snippets through a source control product,&nbsp;TFS (Team Foundation Server), and retrieving through VSTS (Visual Studio Team System) to a local hard drive. This provides a very simple procedure to share snippets across the team as well as the normal benefits of a source control product.</p>
<p>In my experience, I've used Insert Snippets and Surrounds With Snippets. I favor Insert Snippets whenever possible. You can still get the benefits of highlighting text that should be modified with Insert Snippets, the only practical difference is that you type your changes after you implement an Insert Snippet, and you type your changes before you implement a Surrounds With Snippet. This is definitely a personal opinion, so I encourage you to try both. I lean towards one or the other because if you have a large library of snippets, and hopefully you chose to arrange them in hierarchical folders, it can be difficult to remember if you need to navigate one way or the other.</p>
<p>In the example given later in this article, I will create an Insert Snippet that helps identify tables in your database which implement Sequences. Parameters given include SchemaName, TableName, and ColumnName. These parameters will act as filters, and only the Schema Name is required. For more practical information on SQL Server Sequences, please refer to my earlier blog post. <a href="https://blogs.msdn.com/b/kenobonn/archive/2013/05/14/sql-server-2012-sequences-in-vsts-projects.aspx">https://blogs.msdn.com/b/kenobonn/archive/2013/05/14/sql-server-2012-sequences-in-vsts-projects.aspx</a></p>
<p>We have two main hierarchies of user defined snippets. One is project specific, another is SQL specific. The project specific node has subnodes for features of the project, and can also be arranged by developer code versus troubleshooting code, where you may consider test and production support as users who may benefit as well. The SQL specific node is mainly for SQL tricks or common code that you may run in development or production.&nbsp;The root node of&nbsp;my Snippet library begins with a period, to place it at the top, alphabetically, as this is the most common set of snippets that I use.&nbsp;</p>
<p><strong><a name="Configuration"></a>CONFIGURATION:</strong></p>
<p>Assumption is that SQL Server 2012 Client Tools are installed, and Visual Studio (2008 or above) with Team features to integrate with a TFS project.</p>
<ol>
<li>First, make a note of the location in TFS Source Control Explorer where the SQL Snippets are stored. See Figure 1 below.</li>
<ol>
<li>Write down the Local Path that maps to the root of the Snippets directory.</li>
<li>In the example below, the location is &ldquo;C:\tfs\Tools\Team Standards\.Snippets&rdquo;.</li>
</ol>
<li>In SQL Server Management Studio (SSMS), go to "Tools", "Code Snippets Manager...". See Figure 2 below.</li>
<li>Add a reference to the directory where Snippets from TFS are located. See Figures 3 and 4 below.</li>
<li>In Visual Studio 2010, bring up the Code Snippets Manager by using the keys CTRL-K, CTRL-B (while holding down the CTRL key, press the K then the B keys). Change the language to SQL, and Add the directory for code snippets as identified earlier in step 1 b.</li>
</ol>
<p><strong>FIGURE 1: VSTS Source Control Mapping</strong></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5078.SnippetBlog1_VstsSourceControlMapping.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5078.SnippetBlog1_5F00_VstsSourceControlMapping.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5078.SnippetBlog1_VstsSourceControlMapping.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/543x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5078.SnippetBlog1_5F00_VstsSourceControlMapping.png" alt="" border="0" /></a></p>
<p><strong>FIGURE 2: Code Snippets Manager in SSMS - menu</strong></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5710.SnippetBlog2_CodeSnippetsManagerMenu.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5710.SnippetBlog2_5F00_CodeSnippetsManagerMenu.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5710.SnippetBlog2_CodeSnippetsManagerMenu.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5710.SnippetBlog2_5F00_CodeSnippetsManagerMenu.png" alt="" border="0" /></a></p>
<p><strong>FIGURE 3: Code Snippets Manager in SSMS &ndash; Add new directory</strong></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/1680.SnippetBlog3_CodeSnippetsManagerNewDirectory.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/1680.SnippetBlog3_5F00_CodeSnippetsManagerNewDirectory.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/1680.SnippetBlog3_CodeSnippetsManagerNewDirectory.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/531x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/1680.SnippetBlog3_5F00_CodeSnippetsManagerNewDirectory.png" alt="" border="0" /></a></p>
<p><strong>FIGURE 4: Mapping SSMS Snippets to local hard drive</strong></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/6560.SnippetBlog4_MappingSnippetsToLocalHardDrive.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/6560.SnippetBlog4_5F00_MappingSnippetsToLocalHardDrive.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/6560.SnippetBlog4_MappingSnippetsToLocalHardDrive.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/6560.SnippetBlog4_5F00_MappingSnippetsToLocalHardDrive.png" alt="" border="0" /></a></p>
<p><strong><a name="HowToUseSnippets"></a>HOW TO USE SQL SNIPPETS</strong><br />To use SQL 2012 snippets, there are two kinds of snippets, Insert and Surrounds With.</p>
<ol>
<li>For Insert, simply right click in query window, choose "Insert snippet..." and navigate the hierarchy of folders to the snippet of interest. See Figure 5 for an example of an Insert Snippet.</li>
<li>For Surrounds with, type a value or SQL statement and select it, so that it is the focus of the query window. Right click in the query window, and choose &ldquo;Surround with&hellip;&rdquo;.&nbsp; See Figure 6 for an example of a Surrounds With snippet.</li>
</ol>
<p><strong>FIGURE 5: How to use an Insert snippet</strong></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/3187.SnippetBlog5_UseInsertSnippet.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/3187.SnippetBlog5_5F00_UseInsertSnippet.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/3187.SnippetBlog5_UseInsertSnippet.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/480x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/3187.SnippetBlog5_5F00_UseInsertSnippet.png" alt="" border="0" /></a><br /><br /><strong>FIGURE 6: How to use a Surrounds With snippet</strong></p>
<p><strong></strong>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5315.SnippetBlog6_UseSurroundsWithSnippet.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5315.SnippetBlog6_5F00_UseSurroundsWithSnippet.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/5315.SnippetBlog6_UseSurroundsWithSnippet.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/328x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/5315.SnippetBlog6_5F00_UseSurroundsWithSnippet.png" alt="" border="0" /></a></p>
<p><strong><a name="HowToCreateSnippets"></a>HOW TO CREATE SQL SNIPPETS</strong></p>
<p>Templates for creating SQL Snippets are stored in the Snippets root directory. Included below are the templates for Insert and Surrouds With snippets. To create a new snippet, edit the template of interest by opening the file in Visual Studio. Store the changes in the appropriate directory, and save to source control. See the References section for help in creating snippets.</p>
<p>&nbsp;<br /><strong>INSERT SNIPPET TEMPLATE</strong><br />For an Insert Snippet, use the template below and modify the Title, Description, Author, and the code within the CDATA section below. The Title is what the user will click to select the snippet, the Description is hover text to help the user understand the purpose of the snippet. There may be zero or many Literals within the Declarations element. A Literal is something that will be used in substition in the resultant code, and is referenced by its name surrounded by $ symbols.</p>
<pre class="scroll"><code class="html">&lt;?xml version="1.0" encoding="utf-8" ?&gt;<br /> &lt;CodeSnippets xmlns="https://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&gt;<br /> &lt;CodeSnippet Format="1.0.0"&gt;<br /> &lt;Header&gt;<br /> &lt;Title&gt;Template - Insert&lt;/Title&gt;<br /> &lt;Description&gt;Demo for Insert Code Snippet.&lt;/Description&gt;<br /> &lt;Author&gt; Ken O. Bonn &lt;/Author&gt;<br /> &lt;SnippetTypes&gt;<br /> &lt;SnippetType&gt;Expansion&lt;/SnippetType&gt;<br /> &lt;/SnippetTypes&gt;<br /> &lt;/Header&gt;<br /> &lt;Snippet&gt;<br /> &lt;Declarations&gt;<br /> &lt;Literal&gt;<br /> &lt;ID&gt;DatabaseName&lt;/ID&gt;<br /> &lt;ToolTip&gt;Name of database.&lt;/ToolTip&gt;<br /> &lt;Default&gt;&lt;/Default&gt;<br /> &lt;/Literal&gt;<br /> &lt;/Declarations&gt;<br /> &lt;Code Language="SQL"&gt;<br /> &lt;![CDATA[<br /> ------------------------------------------------------<br /> -- FILENAME: Template-Expansion.snippet<br /> -- PURPOSE: Template for Expansion (Insert) snippets.<br /> -- AUTHOR: Ken O. Bonn<br /> -- DATE: May 15, 2013<br /> ------------------------------------------------------<br /> SET NOCOUNT ON;<br /> <br /> EXEC SP_HELPDB $DatabaseName$;<br /> <br /> ]]&gt;<br /> &lt;/Code&gt;<br /> &lt;/Snippet&gt;<br /> &lt;/CodeSnippet&gt;<br /> &lt;/CodeSnippets&gt;<br /> </code></pre>
<p><strong>SURROUNDS WITH SNIPPET TEMPLATE</strong>&nbsp;</p>
<p>&nbsp;The MSDN documentation has a nice example of a Surrounds With Snippet that you can use as a template. As I do not favor these snippets, I will refer to the link below in case you wish to create a Surrounds With snippet.</p>
<p><a href="https://msdn.microsoft.com/en-us/library/gg492130.aspx">https://msdn.microsoft.com/en-us/library/gg492130.aspx</a></p>
<p>&nbsp;</p>
<p><strong><a name="Example1SequenceFinder"></a>EXAMPLE - FIND TABLES USING SEQUENCES FOR DEFAULT VALUES</strong></p>
<p>Copy and paste the code below into a directory that you configured for Code Snippets. Afterwards, follow the procedures that I detailed for calling an Insert Snippet. If you don't have a Sequence in your database, you may want to do the exercises in my earlier article, at <a href="https://blogs.msdn.com/b/kenobonn/archive/2013/05/14/sql-server-2012-sequences-in-vsts-projects.aspx">https://blogs.msdn.com/b/kenobonn/archive/2013/05/14/sql-server-2012-sequences-in-vsts-projects.aspx</a></p>
<pre class="scroll"><code class="cplusplus">&lt;?xml version="1.0" encoding="utf-8" ?&gt;<br /> &lt;CodeSnippets xmlns="https://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&gt;<br /> &lt;CodeSnippet Format="1.0.0"&gt;<br /> &lt;Header&gt;<br /> &lt;Title&gt;Columns using Sequences&lt;/Title&gt;<br /> &lt;Description&gt;Find Columns that use Sequences as default values.&lt;/Description&gt;<br /> &lt;Author&gt; Ken O. Bonn &lt;/Author&gt;<br /> &lt;SnippetTypes&gt;<br /> &lt;SnippetType&gt;Expansion&lt;/SnippetType&gt;<br /> &lt;/SnippetTypes&gt;<br /> &lt;/Header&gt;<br /> &lt;Snippet&gt;<br /> &lt;Declarations&gt;<br /> &lt;Literal&gt;<br /> &lt;ID&gt;SchemaName&lt;/ID&gt;<br /> &lt;ToolTip&gt;Schema Name to find Sequence. Required.&lt;/ToolTip&gt;<br /> &lt;Default&gt;dbo&lt;/Default&gt;<br /> &lt;/Literal&gt;<br /> &lt;Literal&gt;<br /> &lt;ID&gt;TableName&lt;/ID&gt;<br /> &lt;ToolTip&gt;Table Name to find Sequence. Optional.&lt;/ToolTip&gt;<br /> &lt;Default&gt;&lt;/Default&gt;<br /> &lt;/Literal&gt;<br /> &lt;Literal&gt;<br /> &lt;ID&gt;ColumnName&lt;/ID&gt;<br /> &lt;ToolTip&gt;Column Name to find Sequence. Optional.&lt;/ToolTip&gt;<br /> &lt;Default&gt;&lt;/Default&gt;<br /> &lt;/Literal&gt;<br /> &lt;/Declarations&gt;<br /> &lt;Code Language="SQL"&gt;<br /> &lt;![CDATA[<br /> ---------------------------------------------------------------------<br /> -- FILENAME: ColumnsUsingSequences.snippet<br /> -- PURPOSE: Find tables having columns that implement Sequences.<br /> -- AUTHOR: Ken O. Bonn<br /> -- DATE: January 24, 2013<br /> ---------------------------------------------------------------------<br /> SET NOCOUNT ON;<br /> <br /> DECLARE @SchemaName sysname<br /> , @TableName sysname<br /> , @ColumnName sysname;<br /> SET @SchemaName = '$SchemaName$';<br /> SET @TableName = '$TableName$';<br /> SET @ColumnName = '$ColumnName$';<br /> <br /> SELECT<br /> [Schema Name] = scc.[name]<br /> , [Table Name] = so.[name]<br /> , [Column Name] = sc.[name]<br /> , [Constraint Name] = dc.[name]<br /> , [Sequence Name] = LTRIM(REPLACE(SUBSTRING(dc.[definition],<br /> CHARINDEX(dc.[definition], 'NEXT VALUE FOR') + 16, 100<br /> ), ')', ''))<br /> , [Sequence Object ID] = OBJECT_ID(LTRIM(REPLACE(SUBSTRING(dc.[definition],<br /> CHARINDEX(dc.[definition], 'NEXT VALUE FOR') + 16, 100<br /> ), ')', '')))<br /> FROM sys.schemas scc<br /> INNER JOIN sys.objects so<br /> ON scc.[schema_id] = so.[schema_id]<br /> INNER JOIN sys.columns sc<br /> ON so.[object_id] = sc.[object_id]<br /> INNER JOIN sys.default_constraints dc<br /> ON so.object_id = dc.parent_object_id<br /> AND sc.[object_id] = dc.parent_object_id<br /> AND sc.column_id = dc.parent_column_id<br /> WHERE dc.[type] = 'D'<br /> AND dc.[definition] LIKE '%NEXT VALUE FOR%'<br /> AND (scc.[name] = @SchemaName OR RTRIM(@SchemaName) = '')<br /> AND (so.[name] = @TableName OR RTRIM(@TableName) = '')<br /> AND (sc.[name] = @ColumnName OR RTRIM(@ColumnName) = '')<br /> ORDER BY scc.[name], so.[name], sc.[name];<br /> ]]&gt;<br /> &lt;/Code&gt;<br /> &lt;/Snippet&gt;<br /> &lt;/CodeSnippet&gt;<br /> &lt;/CodeSnippets&gt;</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>SQL Server 2012 Sequences in VSTS projects</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/sql-server-2012-sequences-in-vsts-projects</link>
      <pubDate>Mon, 13 May 2013 17:18:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2013/05/13/sql-server-2012-sequences-in-vsts-projects/</guid>
      <description><![CDATA[This post is intended to be a quick reference for creating and using Sequences in SQL Server 2012,...]]></description>
      <content:encoded><![CDATA[<p>This post is intended to be a quick reference for creating and using Sequences in SQL Server 2012, as authored in a Visual Studio 2010 project. It's really pretty simple, but there are a few things to do to make it work properly. While this article discusses Visual Studio 2010, it can easily be extended to Visual Studio 2012. For reference to what Sequences are, beyond the implementation described here, refer to the MSDN documentation at <a href="https://msdn.microsoft.com/en-us/library/ff878058.aspx">https://msdn.microsoft.com/en-us/library/ff878058.aspx</a> .</p>
<p>In this example, we are implementing a primary key using a Sequence as the key generator instead of Identity. As a Sequence does not generate a value for Scope_Identity, I will demonstrate an alternate technique to retrieve the value of the newly inserted key from the output clause of an insert statement, as saved to a temporary table variable.</p>
<p>There are plenty more scenarios to implement&nbsp;Sequences, such as having a unique key distributed among multiple tables. Performance improvements&nbsp;for&nbsp;large volume of inserts are a great use for Sequences. It would be a lengthy discussion to consider when to use Sequences and when not to,&nbsp;so I will defer that topic. I encourage readers to research on the appropriate cache size&nbsp;for their circumstances, I chose 1000 in the example, but that may be a bit large for most&nbsp;needs.&nbsp;Sequences are one of many reasons to upgrade to SQL Server 2012.</p>
<p><strong>1.&nbsp;Ensure that&nbsp;Visual Studio 2010 supports the latest SQL Server 2012 projects.</strong></p>
<p>Install SQL Server Data Tools (SSDT). A quick Bing search for SSDT should find it for you, but current location is at <a href="https://msdn.microsoft.com/en-us/data/tools.aspx">https://msdn.microsoft.com/en-us/data/tools.aspx</a></p>
<p><strong>2. Create a SQL Server Project (having extension .sqlproj, not the former .dbproj).</strong></p>
<p>See figures 1 and 2. After project creation, go to the properties of the project and ensure that the Target platform is "SQL Server 2012".</p>
<p><strong>3. Create a sequence.</strong></p>
<p>Use VSTS to import the file into the proper location. By following this method, the folder structure will automatically create the file in the proper folder.</p>
<ul>
<li>Create it as a file, outside of the project, with the Sequence create definition See below for an example.</li>
<li>Right click the project, and choose Import, then Script, and specify the newly created script file.</li>
<li>Go to the Specify Options section, and ensure correct Folder Structure is specified. My preference is for "Schema\Object Type".</li>
</ul>
<p>Code below is a simple sequence.</p>
<pre class="scroll"><code class="mysql">CREATE SEQUENCE dbo.SeqDemoTable1<br /> AS int<br /> START WITH 1<br /> INCREMENT BY 1<br /> MINVALUE 1<br /> NO MAXVALUE<br /> NO CYCLE<br /> CACHE 1000</code></pre>
<p><strong>4. Associate the Sequence to a table as a default rule.</strong></p>
<p>Code below will create the table and associate the primary key with the Sequence.</p>
<pre class="scroll"><code class="mysql">CREATE TABLE dbo.DemoTable1<br /> (<br /> Field1ID int NOT NULL CONSTRAINT df_DemoTable1_Field1ID DEFAULT NEXT VALUE FOR dbo.SeqDemoTable1,<br /> Field2 varchar(10) NULL,<br /> Field3 varchar(10) NULL<br /> )<br /> GO<br /> ALTER TABLE dbo.DemoTable1<br /> ADD CONSTRAINT PK_DemoTable1_Field1ID PRIMARY KEY CLUSTERED <br /> (<br /> Field1ID ASC<br /> )</code></pre>
<p><strong>&nbsp;5. Insert to a table and verify Sequence values unique and get latest value inserted.</strong></p>
<pre class="scroll"><code class="mysql">-- Cannot use scope_identity for Sequences.<br /> -- Instead, trap the Primary Key (Sequence) into a table.<br /> DECLARE @DemoTable1 table (Field1ID int) <br /> DECLARE @LatestInsertKey int<br /> --Insert two records in a single statement<br /> INSERT INTO dbo.DemoTable1(Field2, Field3)<br /> OUTPUT INSERTED.Field1ID INTO @DemoTable1 <br /> VALUES<br /> ('ABC','DEF')<br /> , ('GHI','JKL')<br /> -- Get latest value if multiple inserts.<br /> --If single insert can be assumed, not required to use MAX function.<br /> SELECT @LatestInsertKey = MAX(Field1ID) FROM @DemoTable1<br /> -- Verify results for Latest Insert Key<br /> SELECT @LatestInsertKey AS [@LatestInsertKey]<br /> -- Verify results for Sequence generation<br /> SELECT * FROM dbo.DemoTable1</code></pre>
<p><strong></strong>&nbsp;</p>
<p><strong>FIGURE 1 - PROJECT CREATION</strong></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/7357.SequenceBlog1_NewProject.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/7357.SequenceBlog1_5F00_NewProject.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/7357.SequenceBlog1_NewProject.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/7357.SequenceBlog1_5F00_NewProject.png" alt="" border="0" /></a></p>
<p><strong>FIGURE 2 - PROJECT PROPERTIES</strong></p>
<p><strong><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/4466.SequenceBlog2_ProjectProperties.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/4466.SequenceBlog2_5F00_ProjectProperties.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/4466.SequenceBlog2_ProjectProperties.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/4466.SequenceBlog2_5F00_ProjectProperties.png" alt="" border="0" /></a></strong></p>
<p><strong>FIGURE 3 - IMPORT SQL SCRIPT TO PROJECT</strong></p>
<p><strong><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/3312.SequenceBlog3_ImportScript.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/3312.SequenceBlog3_5F00_ImportScript.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/3312.SequenceBlog3_ImportScript.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/3312.SequenceBlog3_5F00_ImportScript.png" alt="" border="0" /></a></strong></p>
<p><strong>FIGURE&nbsp;4 - &nbsp;PROJECT STRUCTURE</strong></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/8154.SequenceBlog4_ProjectStructure.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/8154.SequenceBlog4_5F00_ProjectStructure.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/16/46/8154.SequenceBlog4_ProjectStructure.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/195x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-16-46/8154.SequenceBlog4_5F00_ProjectStructure.png" alt="" border="0" /></a></p>]]></content:encoded>
    </item>
    <item>
      <title>HOW TO: Link directly to TSWA (2008 or 2010 Beta1) work items or queries</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/how-to-link-directly-to-tswa-2008-or-2010-beta1-work-items-or-queries</link>
      <pubDate>Thu, 28 May 2009 17:17:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2009/05/28/how-to-link-directly-to-tswa-2008-or-2010-beta1-work-items-or-queries/</guid>
      <description><![CDATA[To link directly to work items or to run queries in TSWA (Team System Web Access, a component of...]]></description>
      <content:encoded><![CDATA[<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><FONT size=3><FONT face=Calibri>To link directly to work items or to run queries in TSWA (Team System Web Access, a component of Team Foundation Server), the following links may provide quick shortcuts. This information is relevant to TSWA 2008 and TFS/TSWA 2010 Beta 1. As 2010 is in beta, I cannot guarantee that the parameters or syntax will stay the same once it is released product (I am not on product team so cannot speak to that).<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></FONT></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Work Items:<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><FONT size=3 face=Calibri>For the direct URL, specify {TSWA_URL}/</FONT><SPAN style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-bidi-font-family: Consolas">wi.aspx?id={0}</SPAN><FONT size=3 face=Calibri> where </FONT><SPAN style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-bidi-font-family: Consolas">{0}</SPAN><FONT size=3><FONT face=Calibri> represents a <U>single work item ID</U> to edit. In TFS 2010 Beta 1, additional parameters such as pcname (project collection name), pname (project name), and tfs (tfs connection) may be specified to ensure work item selected from proper repository.<o:p></o:p></FONT></FONT></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Queries:<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><FONT size=3 face=Calibri>To query for a bug by ID, use </FONT><A href="https://msdn.microsoft.com/en-us/library/bb130198.aspx" mce_href="https://msdn.microsoft.com/en-us/library/bb130198.aspx"><FONT size=3 face=Calibri>WIQL</FONT></A><FONT size=3 face=Calibri> to search for ID and specify output columns. The URL will appear as: {TSWA_URL}/</FONT><SPAN style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-bidi-font-family: Consolas">q.aspx?wiql=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN({0})</SPAN><FONT size=3 face=Calibri> where </FONT><SPAN style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-bidi-font-family: Consolas">{0}</SPAN><FONT size=3><FONT face=Calibri> represents a <U>comma delimited list of work item IDs</U> to view. In TFS 2010 Beta 1, additional parameters mentioned above may be specified as well.<o:p></o:p></FONT></FONT></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Location of {TSWA_URL}:<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><FONT size=3><FONT face=Calibri>Using TSWA 2008, the base url is typically the same as the connection to the TFS connection, except you specify port 8090 instead of 8080 (assuming default installations). In TFS 2010 Beta 1, TSWA is tied closer to TFS, and the base url is the same port under a virtual directory called “web”. It is important to remember that TFS 2010 supports multiple collections of projects, whereas TFS 2008 does not have the concept of collections, so all projects are in one hierarchy.<o:p></o:p></FONT></FONT></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><FONT size=3><FONT face=Calibri>To illustrate the differences, the table below assumes you wish to edit work item 123, or&nbsp;query for work items 123 and 456. Querystring parameters are in orange highlighting to help understand the available parameters.</FONT></FONT></P>
<TABLE style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; WIDTH: 6in; BORDER-COLLAPSE: collapse; WORD-WRAP: break-word; BORDER-TOP: medium none; BORDER-RIGHT: medium none; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class=MsoTableGrid border=1 cellSpacing=0 cellPadding=0 width=576 class="MsoTableGrid">
<TBODY>
<TR style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: black 1pt solid; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: black 1pt solid; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: black 1pt solid; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>TFS connection<o:p></o:p></FONT></FONT></B></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: black 1pt solid; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Edit work items individually<o:p></o:p></FONT></FONT></B></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: black 1pt solid; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Query for work items using WIQL<o:p></o:p></FONT></FONT></B></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.8pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: black 1pt solid; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>View work items in read only mode.<o:p></o:p></FONT></FONT></B></P></TD></TR>
<TR style="mso-yfti-irow: 1">
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: black 1pt solid; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>TFS / TSWA 2008<o:p></o:p></FONT></FONT></B></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8080/" mce_href="https://tfsservername:8080/"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8080</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8090/wi.aspx?id=123" mce_href="https://tfsservername:8090/wi.aspx?id=123"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8090/wi.aspx?<FONT style="BACKGROUND-COLOR: #ff9900">id</FONT>=123</FONT></A><FONT size=3><FONT face=Calibri> <o:p></o:p></FONT></FONT></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8090/q.aspx?wiql=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN(123,456)" mce_href="https://tfsservername:8090/q.aspx?wiql=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN(123,456)"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8090/q.aspx?<FONT style="BACKGROUND-COLOR: #ff9900">wiql</FONT>=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN(123,456)</FONT></A><o:p></o:p></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.8pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=123" mce_href="https://tfsservername:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=123"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8080/WorkItemTracking/WorkItem.aspx?<FONT style="BACKGROUND-COLOR: #ff9900">artifactMoniker</FONT>=123</FONT></A><o:p></o:p></P></TD></TR>
<TR style="mso-yfti-irow: 2; mso-yfti-lastrow: yes">
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: black 1pt solid; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BACKGROUND: #9bbb59; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-background-themecolor: accent3; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>TFS / TSWA 2010 Beta 1<o:p></o:p></FONT></FONT></B></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8080/tfs" mce_href="https://tfsservername:8080/tfs"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8080/tfs</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8080/tfs/web/wi.aspx?id=123&amp;pcname=DefaultCollection&amp;pname=My%20Project&amp;tfs=https://TfsServername:8080/tfs" mce_href="https://tfsservername:8080/tfs/web/wi.aspx?id=28&amp;pcname=DefaultCollection&amp;pname=My%20Project&amp;tfs=https://TfsServername:8080/tfs"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8080/tfs/web/wi.aspx?<FONT style="BACKGROUND-COLOR: #ff9900">id</FONT>=123&amp;<FONT style="BACKGROUND-COLOR: #ff9900" color=#3333ff>pcname</FONT>=DefaultCollection&amp;<FONT style="BACKGROUND-COLOR: #ff9900">pname</FONT>=My%20Project&amp;<FONT style="BACKGROUND-COLOR: #ff9900">tfs</FONT>=https://TfsServername:8080/tfs</FONT></A><FONT size=3><FONT face=Calibri> <o:p></o:p></FONT></FONT></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.75pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8080/tfs/web/q.aspx?wiql=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN(123,456)&amp;pcname=DefaultCollection&amp;pname=My%20Project&amp;tfs=https://TfsServername:8080/tfs" mce_href="https://tfsservername:8080/tfs/web/q.aspx?wiql=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN(123,456)&amp;pcname=DefaultCollection&amp;pname=My%20Project&amp;tfs=https://TfsServername:8080/tfs"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8080/tfs/web/q.aspx?<FONT style="BACKGROUND-COLOR: #ff9900">wiql</FONT>=SELECT%20ID,Title,State%20FROM%20WorkItems%20WHERE%20ID%20IN(123,456)&amp;<FONT style="BACKGROUND-COLOR: #ff9900">pcname</FONT>=DefaultCollection&amp;<FONT style="BACKGROUND-COLOR: #ff9900">pname</FONT>=My%20Project&amp;<FONT style="BACKGROUND-COLOR: #ff9900">tfs</FONT>=https://TfsServername:8080/tfs</FONT></A><FONT size=3><FONT face=Calibri> <o:p></o:p></FONT></FONT></P></TD>
<TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #d4d0c8; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.8pt; PADDING-RIGHT: 5.4pt; WORD-WRAP: break-word; BORDER-TOP: #d4d0c8; BORDER-RIGHT: black 1pt solid; PADDING-TOP: 0in; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=128>
<P style="MARGIN: 0in 0in 0pt; WORD-WRAP: break-word" class=MsoNormal><A href="https://tfsservername:8080/tfs/DefaultCollection/WorkItemTracking/WorkItem.aspx?artifactMoniker=123" mce_href="https://tfsservername:8080/tfs/DefaultCollection/WorkItemTracking/WorkItem.aspx?artifactMoniker=123"><FONT color=#0000ff size=3 face=Calibri>https://TfsServername:8080/tfs/DefaultCollection/WorkItemTracking/WorkItem.aspx?<FONT style="BACKGROUND-COLOR: #ff9900">artifactMoniker</FONT>=123</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P></TD></TR></TBODY></TABLE>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><FONT size=3><FONT face=Calibri>I haven’t yet found official documentation on parameters available for direct links in TSWA 2008 or 2010, yet the links below may be handy. Some of them may be outdated yet useful regardless.<o:p></o:p></FONT></FONT></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>TSWA tip: How to use the new TSWA template URL feature (initial value URL)<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><A href="https://blogs.msdn.com/buckh/comments/8506227.aspx" mce_href="https://blogs.msdn.com/buckh/comments/8506227.aspx"><FONT size=3 face=Calibri>https://blogs.msdn.com/buckh/comments/8506227.aspx</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Using Team System Web Access<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><A href="https://msdn.microsoft.com/en-us/library/bb822087.aspx" mce_href="https://msdn.microsoft.com/en-us/library/bb822087.aspx"><FONT size=3 face=Calibri>https://msdn.microsoft.com/en-us/library/bb822087.aspx</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Updates to Team System Web Access<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><A href="https://blogs.msdn.com/bharry/archive/2008/04/15/updates-to-team-system-web-access.aspx" mce_href="https://blogs.msdn.com/bharry/archive/2008/04/15/updates-to-team-system-web-access.aspx"><FONT size=3 face=Calibri>https://blogs.msdn.com/bharry/archive/2008/04/15/updates-to-team-system-web-access.aspx</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>How to: Add New Work Items (Team System Web Access)<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><A href="https://msdn.microsoft.com/en-us/library/bb822136.aspx" mce_href="https://msdn.microsoft.com/en-us/library/bb822136.aspx"><FONT size=3 face=Calibri>https://msdn.microsoft.com/en-us/library/bb822136.aspx</FONT></A><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><o:p><FONT size=3 face=Calibri>&nbsp;</FONT></o:p></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><B style="mso-bidi-font-weight: normal"><FONT size=3><FONT face=Calibri>Team System Web Access 2008 Power Tool is now available<o:p></o:p></FONT></FONT></B></P>
<P style="MARGIN: 0in 0in 0pt" class=MsoNormal><A href="https://blogs.msdn.com/buckh/archive/2007/11/29/team-system-web-access-2008-power-tool-is-now-available.aspx" mce_href="https://blogs.msdn.com/buckh/archive/2007/11/29/team-system-web-access-2008-power-tool-is-now-available.aspx"><FONT size=3 face=Calibri>https://blogs.msdn.com/buckh/archive/2007/11/29/team-system-web-access-2008-power-tool-is-now-available.aspx</FONT></A></P>]]></content:encoded>
    </item>
    <item>
      <title>My first MSDN article</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/my-first-msdn-article</link>
      <pubDate>Thu, 09 Apr 2009 16:20:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2009/04/09/my-first-msdn-article/</guid>
      <description><![CDATA[I just published an article entitled "Testing SQL-XML Output by Using XQuery". I will likely add a...]]></description>
      <content:encoded><![CDATA[<P>I just published an article entitled "Testing SQL-XML Output by Using XQuery". I will likely add a few extra notes to the tutorial in my blog site.</P>
<P>Please see my article at <A href="https://msdn.microsoft.com/en-us/library/dd637842.aspx">https://msdn.microsoft.com/en-us/library/dd637842.aspx</A></P>]]></content:encoded>
    </item>
    <item>
      <title>PIVOT on two or more fields in SQL Server</title>
      <link>https://docs.microsoft.com/archive/blogs/kenobonn/pivot-on-two-or-more-fields-in-sql-server</link>
      <pubDate>Sun, 22 Mar 2009 19:46:00 GMT</pubDate>
      <dc:creator><![CDATA[kenobonn]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kenobonn/2009/03/22/pivot-on-two-or-more-fields-in-sql-server/</guid>
      <description><![CDATA[function CopyCode(elemName) { var obj = document.getElementById(elemName);...]]></description>
      <content:encoded><![CDATA[
<SCRIPT language=javascript type=text/javascript>
        function CopyCode(elemName) { var obj = document.getElementById(elemName); window.clipboardData.setData("Text", obj.innerText) }
    </SCRIPT>

<STYLE type=text/css>
        DIV.libCScode
        {
            border-top: #fff 5px solid;
            display: block;
            padding-bottom: 20px;
            width: 98.9%;
        }
        DIV.libCScode TABLE
        {
            border-top-width: 0px;
            border-left-width: 0px;
            font-size: 95%;
            border-bottom-width: 0px;
            margin-bottom: 5px;
            width: 100%;
            border-right-width: 0px;
        }
        DIV.libCScode TABLE TH
        {
            font-weight: bold;
            background: #ddd;
            color: #006;
            border-bottom: #c8cdde 1px solid;
        }
        DIV.libCScode TABLE TD
        {
            padding-right: 5px;
            border-top: #c8cdde 1px solid;
            display: block;
            padding-left: 5px;
            background: #ddd;
            margin: 0px 0px 10px;
            padding-top: 5px;
            font-family: Verdana,Arial,Helvetica,sans-serif;
        }
        DIV.libSQLcode
        {
            font-size: 105%;
            overflow: hidden;
            color: #006;
            font-family: Verdana,Arial,Helvetica,sans-serif;
            word-wrap: break-word;
            padding-right: 5px;
            border-top: #c8cdde 1px solid;
            display: block;
            padding-left: 5px;
            background: #ddd;
            margin: 0px 0px 10px;
            padding-top: 5px;
            font-family: Verdana,Arial,Helvetica,sans-serif;
        }
        PRE.libCScode
        {
            padding-right: 5px;
            border-top: #c8cdde 1px solid;
            display: block;
            padding-left: 5px;
            background: #ddd;
            margin: 0px 0px 10px;
            padding-top: 5px;
            font-family: Verdana,Arial,Helvetica,sans-serif;
        }
        DIV.libSQLcode DIV
        {
            font-size: 105%;
            overflow: hidden;
            color: #006;
            font-family: Verdana,Arial,Helvetica,sans-serif;
            word-wrap: break-word;
        }
        DIV.libCScode PRE
        {
            font-size: 105%;
            overflow: hidden;
            color: #006;
            font-family: Verdana,Arial,Helvetica,sans-serif;
            word-wrap: break-word;
        }
        .CodeSnippetTitleBar
        {
            padding-right: 3px;
            padding-left: 3px;
            padding-bottom: 3px;
            word-spacing: normal;
            padding-top: 3px;
            border-bottom: #aaa 1px solid;
            white-space: nowrap;
            letter-spacing: normal;
            height: 15px;
            background-color: #ddd;
        }
        .CodeDisplayLanguage
        {
            float: left;
            text-align: left;
        }
        .CopyCodeButton
        {
            float: right;
            text-align: right;
        }
        SPAN.copyCode
        {
            display: inline;
            font-weight: normal;
            font-size: 90%;
            float: right;
            cursor: hand;
            color: #00f;
            text-align: right;
        }
        A.copyCode
        {
            cursor: pointer;
            color: blue;
            text-align: right;
            text-decoration: none;
        }
        .LibC_copy_off
        {
            background: url($LibC[2].gif) -320px 0px;
            width: 15px;
            height: 13px;
        }
        .style1
        {
            /*width: 100%;*/
            border-style: solid;
            border-width: 1px;
        }
        .styleHeaderCell
        {
            background-color: #999999;
            border-style: groove;
            border-color: Black;
            border-width: thin;
        }
        .styleDataCell
        {
            border-style: outset;
            border-color: InactiveBorder;
            border-width: thin;
        }
    </STYLE>

<P>The <A href="https://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx" target=_blank mce_href="https://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx">PIVOT</A> function in SQL Server is not used very often in projects I work on, but can be extremely useful for specific kinds of pages, especially when consumed in ASP.NET using GridView objects. Some people struggle with PIVOT on one field, the online documentation should be sufficient for that need. Here is an example of pivoting on two fields for the SQL community. Having a need to show multiple properties for an entity is a good case for such.</P>
<P>To demonstrate this technique, I will create some contrived data, and show pivoting on it. Note that you must pivot on an aggregate function, which may or may not be relevant, such as the case where you want to pivot on a text field. We will use a table of pets with their owners, and another table containing properties of the pets, and show a report for properties of them, such as name, breed and gender. To make this demo even more contrived, we will assume no more than 3 pets per owner (I'm demonstrating the technique, you need to fit it into your requirements).</P>
<P>Below is a script to create two relational tables, Pet and PetDetail. Note, the database schema would likely need a more generic animal table if this were a real application, and we would display the owner names, not their ID's. It may seem obvious that the data model should be optimized, but remember this is a demo of a SQL skill, it is not a demo for data modelling. The insert statements use a syntax new to SQL Server 2008.</P>
<P>The data in the @Pet table has records representing distinct Pets. This has a one to many relationship to the @PetDetail table. Further complicating this is the fields DetailType and DetailValue are effectively key / value pairs. Thus, we have a model with a parent record having multiple key / value pairs. For our report, we only care about data pertaining to the Gender and Breed keys (DetailType).</P>
<DIV id=Div10 class=libCScode>
<DIV class=CodeSnippetTitleBar>
<DIV class=CodeDisplayLanguage>SQL 2008 -Data Creation - Pivot Demo</DIV>
<DIV class=CopyCodeButton><A class=copyCode title="Copy Code" href="javascript:CopyCode('ctl00_Sql2008DdlAndInserts');" mce_href="javascript:CopyCode('ctl00_Sql2008DdlAndInserts');"><IMG class=LibC_copy_off border=0 align=middle src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif" original-url="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif" height=9 mce_src="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif"> Copy Code</A></DIV></DIV>
<DIV dir=ltr>
<DIV style="WORD-WRAP: break-word; WORD-BREAK: break-all" id=ctl00_Sql2008DdlAndInserts class=libSQLcode space="preserve"><SPAN style="FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 10pt">--SQL to create tables and insert data here...</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">DECLARE</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> @Pet <SPAN style="COLOR: blue">Table</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp; PetID <SPAN style="COLOR: blue">INT</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> OwnerID <SPAN style="COLOR: blue">INT</SPAN> <SPAN style="COLOR: green">--FK to fictitious PetOwner table</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> PetName <SPAN style="COLOR: blue">NVARCHAR</SPAN><SPAN style="COLOR: gray">(</SPAN>50<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> AnimalType <SPAN style="COLOR: blue">NVARCHAR</SPAN><SPAN style="COLOR: gray">(</SPAN>10<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">)</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">DECLARE</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> @PetDetail <SPAN style="COLOR: blue">Table</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp; PetDetailID <SPAN style="COLOR: blue">INT</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> PetID <SPAN style="COLOR: blue">INT</SPAN> <SPAN style="COLOR: green">-- FK to @Pet table</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> DetailType <SPAN style="COLOR: blue">NVARCHAR</SPAN><SPAN style="COLOR: gray">(</SPAN>50<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> DetailValue <SPAN style="COLOR: blue">NVARCHAR</SPAN><SPAN style="COLOR: gray">(</SPAN>50<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">)</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">INSERT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">INTO</SPAN> @Pet<SPAN style="COLOR: gray">(</SPAN>PetID<SPAN style="COLOR: gray">,</SPAN> OwnerID<SPAN style="COLOR: gray">,</SPAN> PetName<SPAN style="COLOR: gray">,</SPAN> AnimalType<SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">VALUES</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">&nbsp; </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">1<SPAN style="COLOR: gray">,</SPAN> 1<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Sonya'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Dog'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">2<SPAN style="COLOR: gray">,</SPAN> 2<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Bessy'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Cat'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">3<SPAN style="COLOR: gray">,</SPAN> 2<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Speedy'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Cat'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">4<SPAN style="COLOR: gray">,</SPAN> 3<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Nema'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Cat'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">5<SPAN style="COLOR: gray">,</SPAN> 3<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Milo'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Cat'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">6<SPAN style="COLOR: gray">,</SPAN> 3<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Naala'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Cat'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">INSERT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">INTO</SPAN> @PetDetail<SPAN style="COLOR: gray">(</SPAN>PetDetailID<SPAN style="COLOR: gray">,</SPAN> PetID<SPAN style="COLOR: gray">,</SPAN> DetailType<SPAN style="COLOR: gray">,</SPAN> DetailValue<SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">VALUES</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">&nbsp; </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">1<SPAN style="COLOR: gray">,</SPAN> 1<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Breed'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Norwegian Samoyed'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">2<SPAN style="COLOR: gray">,</SPAN> 1<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Gender'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'F'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">3<SPAN style="COLOR: gray">,</SPAN> 2<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Breed'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Holstein Hybrid'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">4<SPAN style="COLOR: gray">,</SPAN> 2<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Gender'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'F'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">5<SPAN style="COLOR: gray">,</SPAN> 3<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Breed'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'DSH'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">6<SPAN style="COLOR: gray">,</SPAN> 3<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Gender'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'F'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">7<SPAN style="COLOR: gray">,</SPAN> 4<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Breed'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Manx'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">8<SPAN style="COLOR: gray">,</SPAN> 4<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Gender'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'M'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">9<SPAN style="COLOR: gray">,</SPAN> 5<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Breed'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'DSH'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">10<SPAN style="COLOR: gray">,</SPAN> 5<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Gender'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'F'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">11<SPAN style="COLOR: gray">,</SPAN> 6<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Breed'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Lynx-Point Siamese'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">12<SPAN style="COLOR: gray">,</SPAN> 6<SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'Gender'</SPAN><SPAN style="COLOR: gray">,</SPAN> <SPAN style="COLOR: red">'F'</SPAN><SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt"></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">SELECT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> PetID<SPAN style="COLOR: gray">,</SPAN> OwnerID<SPAN style="COLOR: gray">,</SPAN> PetName<SPAN style="COLOR: gray">,</SPAN> AnimalType <SPAN style="COLOR: blue">FROM</SPAN> @Pet <SPAN style="COLOR: blue">ORDER</SPAN> <SPAN style="COLOR: blue">BY</SPAN> PetID</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">SELECT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> PetDetailID<SPAN style="COLOR: gray">,</SPAN> PetID<SPAN style="COLOR: gray">,</SPAN> DetailType<SPAN style="COLOR: gray">,</SPAN> DetailValue <SPAN style="COLOR: blue">FROM</SPAN> @PetDetail <SPAN style="COLOR: blue">ORDER</SPAN> <SPAN style="COLOR: blue">BY</SPAN> PetDetailID</SPAN> <BR></DIV></DIV>
<P>This data may be easier to visualize graphically as below:</P>
<P><BR><IMG alt="Data in relational tables" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_RelationalTables_1.jpg" original-url="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_RelationalTables_1.jpg" width=325 height=445 mce_src="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_RelationalTables_1.jpg"> </P></DIV>
<P><I>Note: The remaining queries below assume data generated as per the insert statements above.</I></P>
<P>A typical query would give accurate data as below, however would lead to multiple records per pet owner. This would require looping or other logic in the front end to translate to a nice report of each owner and their pets. <I>To gain a better understanding of <A href="https://msdn.microsoft.com/en-us/library/ms189798.aspx" target=_blank mce_href="https://msdn.microsoft.com/en-us/library/ms189798.aspx">Ranking Functions</A> , experiment with the <A href="https://msdn.microsoft.com/en-us/library/ms176102.aspx" target=_blank mce_href="https://msdn.microsoft.com/en-us/library/ms176102.aspx">RANK</A> function as in the commented out code below, and compare to the <A href="https://msdn.microsoft.com/en-us/library/ms173825.aspx" target=_blank mce_href="https://msdn.microsoft.com/en-us/library/ms173825.aspx">DENSE_RANK</A> function. This will show why this report requires the DENSE_RANK function in order to be usable by the PIVOT function in the subsequent example.</I></P>
<DIV id=Div1 class=libCScode>
<DIV class=CodeSnippetTitleBar>
<DIV class=CodeDisplayLanguage>SQL 2008 -Simple Joins - Pivot Demo</DIV>
<DIV class=CopyCodeButton><A class=copyCode title="Copy Code" href="javascript:CopyCode('ctl00_Sql2008SimpleJoin');" mce_href="javascript:CopyCode('ctl00_Sql2008SimpleJoin');"><IMG class=LibC_copy_off border=0 align=middle src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif" original-url="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif" height=9 mce_src="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif"> Copy Code</A></DIV></DIV>
<DIV dir=ltr>
<DIV style="WORD-WRAP: break-word; WORD-BREAK: break-all" id=ctl00_Sql2008SimpleJoin class=libSQLcode space="preserve"><SPAN style="FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 10pt">--Simple Join SQL HERE... </SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">SELECT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> p<SPAN style="COLOR: gray">.</SPAN>OwnerID<SPAN style="COLOR: gray">,</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetName<SPAN style="COLOR: gray">,</SPAN> p<SPAN style="COLOR: gray">.</SPAN>AnimalType </SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> pd<SPAN style="COLOR: gray">.</SPAN>DetailType<SPAN style="COLOR: gray">,</SPAN> pd<SPAN style="COLOR: gray">.</SPAN>DetailValue</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: fuchsia; FONT-SIZE: 10pt">DENSE_RANK</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">()</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">OVER </SPAN><SPAN style="COLOR: gray">(</SPAN><SPAN style="COLOR: blue">PARTITION</SPAN> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>OwnerID <SPAN style="COLOR: blue">ORDER</SPAN> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetName <SPAN style="COLOR: blue">ASC</SPAN><SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">AS</SPAN> [Pet#]</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 10pt">--,RANK() OVER (PARTITION BY p.OwnerID ORDER BY p.PetName ASC) AS [Pet# by RANK]</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">FROM</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> @Pet p</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">INNER</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: gray">JOIN</SPAN> @PetDetail pd <SPAN style="COLOR: blue">ON</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetID <SPAN style="COLOR: gray">=</SPAN> pd<SPAN style="COLOR: gray">.</SPAN>PetID</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">ORDER</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>OwnerID<SPAN style="COLOR: gray">,</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetName<SPAN style="COLOR: gray">,</SPAN> pd<SPAN style="COLOR: gray">.</SPAN>DetailType</SPAN><BR></DIV></DIV><IMG alt="Simple Query, yields multiple records be pet" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_SimpleQuery.jpg" original-url="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_SimpleQuery.jpg" width=437 height=248 mce_src="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_SimpleQuery.jpg"> </DIV>
<P>Now, on to the report using the PIVOT function. To understand what's going on, the DENSE_RANK function affords us the ability to distinguish key fields sequentially so that we can pivot on them using predictable names. The predictable names will be the key name plus 1, 2, or 3. </P>
<P>Observe how there are two pivots in this query. The first one pivots from the concatenation of the key name as described above. This is necessary so we can differentiate the data belonging to that key. However, the second pivot is at a higher level, for the distinct pet. Since we don't need to distinguish one value from the other, because the PetName will be the same for each record, we simply generate a pivot based on an arbitrary string value concatenated with the DENSE_RANK value.</P>
<P>Also observe the use of the GROUP clause. Here, I want to group by the OwnerID to create a unique record by owner, however the PetName field is removed from the grouping because we are pivoting on it. For further explanation of the PIVOT function, see the online documentation at <A href="https://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx" target=_blank mce_href="https://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx">https://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx</A></P>
<DIV id=Div2 class=libCScode>
<DIV class=CodeSnippetTitleBar>
<DIV class=CodeDisplayLanguage>SQL 2008 -PIVOT Function - Pivot Demo</DIV>
<DIV class=CopyCodeButton><A class=copyCode title="Copy Code" href="javascript:CopyCode('ctl00_Sql2008PivotReport');" mce_href="javascript:CopyCode('ctl00_Sql2008PivotReport');"><IMG class=LibC_copy_off border=0 align=middle src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif" original-url="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif" height=9 mce_src="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/clear_2.gif"> Copy Code</A></DIV></DIV>
<DIV dir=ltr>
<DIV style="WORD-WRAP: break-word; WORD-BREAK: break-all" id=ctl00_Sql2008PivotReport class=libSQLcode space="preserve"><SPAN style="FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 10pt">--PIVOT QUERY HERE... </SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">SELECT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> </SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">OwnerID</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> AnimalType</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet1Name <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[PetName1]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet1Gender <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[Gender1]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet1Breed <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[Breed1]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet2Name <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[PetName2]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet2Gender <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[Gender2]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet2Breed <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[Breed2]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet3Name <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[PetName3]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet3Gender <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[Gender3]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> Pet3Breed <SPAN style="COLOR: gray">=</SPAN> <SPAN style="COLOR: fuchsia">MAX</SPAN><SPAN style="COLOR: gray">(</SPAN>[Breed3]<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">FROM </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">SELECT</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> </SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p<SPAN style="COLOR: gray">.</SPAN>OwnerID</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: gray">,</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetName</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: gray">,</SPAN> p<SPAN style="COLOR: gray">.</SPAN>AnimalType </SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: gray">,</SPAN> pd<SPAN style="COLOR: gray">.</SPAN>DetailType</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: gray">,</SPAN> pd<SPAN style="COLOR: gray">.</SPAN>DetailValue</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: gray">,</SPAN>pd<SPAN style="COLOR: gray">.</SPAN>DetailType <SPAN style="COLOR: gray">+</SPAN> <SPAN style="COLOR: fuchsia">CAST</SPAN><SPAN style="COLOR: gray">(</SPAN><SPAN style="COLOR: fuchsia">DENSE_RANK</SPAN><SPAN style="COLOR: gray">()</SPAN> <SPAN style="COLOR: blue">OVER </SPAN><SPAN style="COLOR: gray">(</SPAN><SPAN style="COLOR: blue">PARTITION</SPAN> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>OwnerID <SPAN style="COLOR: blue">ORDER</SPAN> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetName <SPAN style="COLOR: blue">ASC</SPAN><SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">AS</SPAN> <SPAN style="COLOR: blue">NVARCHAR</SPAN><SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">AS</SPAN> [PetNumber]</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: gray">,</SPAN><SPAN style="COLOR: red">'PetName'</SPAN> <SPAN style="COLOR: gray">+</SPAN> <SPAN style="COLOR: fuchsia">CAST</SPAN><SPAN style="COLOR: gray">(</SPAN><SPAN style="COLOR: fuchsia">DENSE_RANK</SPAN><SPAN style="COLOR: gray">()</SPAN> <SPAN style="COLOR: blue">OVER </SPAN><SPAN style="COLOR: gray">(</SPAN><SPAN style="COLOR: blue">PARTITION</SPAN> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>OwnerID <SPAN style="COLOR: blue">ORDER</SPAN> <SPAN style="COLOR: blue">BY</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetName <SPAN style="COLOR: blue">ASC</SPAN><SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">AS</SPAN> <SPAN style="COLOR: blue">NVARCHAR</SPAN><SPAN style="COLOR: gray">)</SPAN> <SPAN style="COLOR: blue">AS</SPAN> [PetNamePivot]</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">FROM</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> @Pet p</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">INNER</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: gray">JOIN</SPAN> @PetDetail pd <SPAN style="COLOR: blue">ON</SPAN> p<SPAN style="COLOR: gray">.</SPAN>PetID <SPAN style="COLOR: gray">=</SPAN> pd<SPAN style="COLOR: gray">.</SPAN>PetID</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">)</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">AS</SPAN> query</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">PIVOT</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: fuchsia; FONT-SIZE: 10pt">MAX</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">DetailValue<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: blue">FOR</SPAN> PetNumber <SPAN style="COLOR: gray">IN</SPAN><SPAN style="COLOR: blue"> </SPAN><SPAN style="COLOR: gray">(</SPAN>[Gender1]<SPAN style="COLOR: gray">,</SPAN>[Gender2]<SPAN style="COLOR: gray">,</SPAN>[Gender3]<SPAN style="COLOR: gray">,</SPAN> [Breed1]<SPAN style="COLOR: gray">,</SPAN> [Breed2]<SPAN style="COLOR: gray">,</SPAN> [Breed3]<SPAN style="COLOR: gray">))</SPAN> <SPAN style="COLOR: blue">AS</SPAN> Pivot1</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">PIVOT</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt"> </SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: fuchsia; FONT-SIZE: 10pt">MAX</SPAN><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">(</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">PetName<SPAN style="COLOR: gray">)</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: blue">FOR</SPAN> PetNamePivot <SPAN style="COLOR: gray">IN</SPAN><SPAN style="COLOR: blue"> </SPAN><SPAN style="COLOR: gray">(</SPAN>[PetName1]<SPAN style="COLOR: gray">,</SPAN>[PetName2]<SPAN style="COLOR: gray">,</SPAN>[PetName3]<SPAN style="COLOR: gray">))</SPAN> <SPAN style="COLOR: blue">AS</SPAN> Pivot2</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">GROUP</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">BY</SPAN></SPAN><BR><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt">&nbsp; OwnerID</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: gray; FONT-SIZE: 10pt">,</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> AnimalType</SPAN><BR><SPAN style="FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 10pt">ORDER</SPAN><SPAN style="FONT-FAMILY: Courier New; FONT-SIZE: 10pt"> <SPAN style="COLOR: blue">BY</SPAN> OwnerID</SPAN><BR></DIV></DIV><IMG alt="Pivot Query, up to 3 pets per owner" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_PivotQuery.jpg" original-url="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_PivotQuery.jpg" width=640 height=57 mce_src="https://blogs.msdn.com/blogfiles/kenobonn/WindowsLiveWriter/PIVOTontwoormorefieldsinSQLServer_EBDD/SqlPivot_PivotQuery.jpg"> </DIV>
<H2>Concluding Remarks</H2>
<P>The PIVOT function is a powerful tool for transforming data into simplified structures. It may seem difficult at first to grasp what is being pivoted, and how to do so. Hopefully the example above will bring clarity for pivoting on two or more fields. It should be considered whether to transform the data in SQL Server or the client, as there are tradeoffs to each approach. The PIVOT function would likely have a performance impact on the query based on complexity of the pivot and / or the size of the data being transformed. This performance impact may be less than you might imagine if appropriate filters are applied. At any rate, performance testing would be critical, whether you use the PIVOT function or implement equivalent functionality in the business layer. A well constructed PIVOT statement could lessen the chances of downstream bugs, as the code required to pivot outside of SQL could be very complex, especially if NULLs are allowed in the key fields.</P>
<P>However, this potential for performance impact could be offset by simplifying the code and processing at the client layer, as doing such a transformation in your favorite programming language could be very complex and have just as much of a performance impact. By pivoting in the SQL layer, databinding to a GridView object can be done very straightforward, whereas the alternative would require transformations in the code prior to the databinding event, or hijack the onrowdatabound or other events to do secondary processing.</P>
<P>Regardless of the approach taken for PIVOT, whether it be in SQL Server or programmatically in a .NET language, testing is critical. Be sure to do performance testing as well as accuracy of results, and to do so with a wide range of data to ensure the system can handle real data.</P>]]></content:encoded>
    </item>
  </channel>
</rss>