<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>&#8235;Madeira &#187; איתן בלומין&#8236;</title>	<atom:link href="http://www.madeira.co.il/author/eitan/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.madeira.co.il</link>
	<description>&#8235;SQL Server Services&#8236;</description>	<lastBuildDate>Sat, 19 May 2012 09:04:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>he</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>&#8235;Suggestion: &quot;USE&quot; keyword with Linked Servers&#8236;</title>		<link>http://www.madeira.co.il/suggestion-use-keyword-with-linked-servers/</link>
		<comments>http://www.madeira.co.il/suggestion-use-keyword-with-linked-servers/#comments</comments>
		<pubDate>Wed, 16 May 2012 12:40:50 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[כללי]]></category>
		<category><![CDATA[Linked Server]]></category>
		<category><![CDATA[remote queries]]></category>
		<category><![CDATA[sp_executesql]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/suggestion-use-keyword-with-linked-servers/</guid>
		<description><![CDATA[&#8235;I’ve posted a suggestion on Microsoft Connect for a feature allowing you to connect to databases on linked servers with the "USE" keyword. Technically, it would be like "opening a new session" from one SQL Server to another.&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/5011.png&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<p style="text-align: left;" dir="ltr">Using special functions for querying and executing commands at linked servers is not very convenient, and sometimes even very problematic.<br />
For example, I need to execute some code on several linked servers but the linked server names are dynamic (queried from a table for example).<br />
On each such linked server I need to execute a dynamic query.<br />
However because I must use the <strong>EXECUTE() AT [...]</strong> command I'm exposing a big hole here for SQL Injection.<br />
I found myself wishing I could use<strong> sp_executesql</strong> with linked servers but there's no such way as far as I know.</p>
<p style="text-align: left;" dir="ltr">For example, this is what I’m forced to do:</p>
<div id="codeSnippetWrapper" style="line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; text-align: left; padding: 4px; border: 1px solid silver;">
<div id="codeSnippet" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> BackupOnRemoteServer</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    @<span style="color: #0000ff;">Path</span> NVARCHAR(4000)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">AS</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">DECLARE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        @<span style="color: #0000ff;">Statement</span>    NVARCHAR(<span style="color: #0000ff;">MAX</span>)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">SET</span> @<span style="color: #0000ff;">Statement</span> = N<span style="color: #006080;">'    </span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    BACKUP DATABASE [MyDB]</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    TO DISK = '<span style="color: #006080;">''</span> + @<span style="color: #0000ff;">Path</span> + <span style="color: #006080;">''</span><span style="color: #006080;">''</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">EXECUTE</span> (@<span style="color: #0000ff;">Statement</span>) <span style="color: #0000ff;">AT</span> [SQLINS1]</pre>
<p><!--CRLF--></p>
</div>
</div>
<p style="text-align: left;" dir="ltr">I’ve <a href="https://connect.microsoft.com/SQLServer/feedback/details/742327/use-keyword-with-linked-servers#details" target="_blank">posted a suggestion on Microsoft Connect</a> for the following feature:</p>
<p style="text-align: left;" dir="ltr">It would be very helpful if we were able to connect to databases on linked servers with the &quot;<strong>USE</strong>&quot; keyword.</p>
<p style="text-align: left;">Technically, it would be like &quot;opening a new session&quot; from one SQL Server to another.</p>
<p style="text-align: left;">The sample I’ve posted above could be executed like this:</p>
<div id="codeSnippetWrapper" style="line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; text-align: left; padding: 4px; border: 1px solid silver;">
<div id="codeSnippet" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> BackupOnRemoteServer</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    @<span style="color: #0000ff;">Path</span> NVARCHAR(4000)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">AS</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">DECLARE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        @ServerName <span style="color: #0000ff;">VARCHAR</span>(200),</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        @<span style="color: #0000ff;">Statement</span>    NVARCHAR(<span style="color: #0000ff;">MAX</span>),</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        @<span style="color: #0000ff;">Parameters</span> NVARCHAR(<span style="color: #0000ff;">MAX</span>)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">SET</span> @ServerName = <span style="color: #006080;">'SQLINS1'</span>;</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">SET</span> @<span style="color: #0000ff;">Parameters</span> = N<span style="color: #006080;">'@Path NVARCHAR(4000)'</span>;</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">SET</span> @<span style="color: #0000ff;">Statement</span> = N<span style="color: #006080;">'</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    USE [' + @ServerName + N<span style="color: #006080;">'].[MyDB]</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    BACKUP DATABASE [MyDB]</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    TO DISK = @Path'</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">EXEC</span> sp_executesql @<span style="color: #0000ff;">Statement</span>, @<span style="color: #0000ff;">Parameters</span>, @Path</pre>
<p><!--CRLF--></p>
</div>
</div>
<p style="text-align: left;" dir="ltr">Once the USE command was executed, theoretically it's like I'm connected directly to the linked server using a query window.</p>
<p style="text-align: left;" dir="ltr">Security could be improved versus SQL Injection (use <strong>sp_executesql </strong>with parameters instead of <strong>EXECUTE() AT</strong>) like the example above.</p>
<p style="text-align: left;">Usability could be improved due to cleaner and more readable code.</p>
<p style="text-align: left;" dir="ltr">If you like this idea, please visit this page and vote for it so it’ll get higher priority on Microsoft’s to-do list:</p>
<p style="text-align: left;" dir="ltr"><a href="https://connect.microsoft.com/SQLServer/feedback/details/742327/use-keyword-with-linked-servers#details">https://connect.microsoft.com/SQLServer/feedback/details/742327/use-keyword-with-linked-servers#details</a></p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/suggestion-use-keyword-with-linked-servers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8235;Service Broker Sample: Multi-Threading&#8236;</title>		<link>http://www.madeira.co.il/service-broker-sample-multi-threading/</link>
		<comments>http://www.madeira.co.il/service-broker-sample-multi-threading/#comments</comments>
		<pubDate>Mon, 07 May 2012 09:01:00 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[כללי]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[Fast]]></category>
		<category><![CDATA[Multi-Threading]]></category>
		<category><![CDATA[Parallel Queries]]></category>
		<category><![CDATA[Parallel Querying]]></category>
		<category><![CDATA[Samples]]></category>
		<category><![CDATA[Service Broker]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=4961</guid>
		<description><![CDATA[&#8235;Here's a cool sample of how you can use Service Broker to your benefit by implementing multi-threading in SQL Server&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/4961.jpg&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<h2 dir="ltr">Introduction</h2>
<p dir="ltr">Service Broker is a cool new feature since SQL Server 2005. Yes, SQL 2012 just came out so it’s hardly “new” anymore. But in reality, many DBAs and DB users are still not aware of this feature, or don’t know how to utilize it, or are afraid to do so because they’re not familiar with it.</p>
<p dir="ltr">Using this short series of posts, I’m hoping to ease the minds of such people</p>
<p dir="ltr">In short, Service Broker is an asynchronous queuing engine working inside SQL Server. Using this engine we can send and receive binary or XML messages between queues. When a message is inserted in a queue, Service Broker executes an “activation procedure” that you specified, which is supposed to handle messages from that queue.</p>
<p dir="ltr">Since we have a lot to cover in our sample, I won’t go into too much detail introducing Service Broker. But Microsoft has an excellent and detailed chapter about Service Broker available right here: <a href="http://msdn.microsoft.com/en-us/library/bb522893.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/bb522893.aspx</a></p>
<h2 dir="ltr">Sample 1: Multi-Threading</h2>
<p dir="ltr">I managed to encounter several times a scenario where an application needed to execute several queries independent of each other, and then group them together somehow. However, each of these queries takes a while to execute.   <br />One might wonder: If only we could use some kind of multi-threading mechanism to execute them in parallel, and then the total running time will be of the slowest query only and not the total of them.</p>
<p dir="ltr">Well, it just so happens that our first sample will show how you can implement “multi-threading” in SQL Server using Service Broker queues!</p>
<h3 dir="ltr">The Design</h3>
<p dir="ltr">First, I’ll explain the general idea of the design:</p>
<p dir="ltr">Since Service Broker only works with binary or XML messages, we’ll use XML to send a “<strong>query request</strong>”, and wait for a “<strong>query response</strong>”.    <br />Specifically, we’ll send a message containing some kind of a dynamic query. But that dynamic query must return its result in XML form using an output parameter. Then, Service Broker will execute the query, retrieve the result from the output parameter, and send the result back as the response.    <br />After that, it’s up to us to gather all the responses together and do whatever it is we wanted to do with it.</p>
<p dir="ltr">Also, for the sake of our sample, we’ll need to simulate long execution times. We’ll do this simply by adding a WAITFOR DELAY command into our dynamic queries which will cause the query to wait for a random number of seconds (between 10 and 30).</p>
<h3 dir="ltr">The Scripts</h3>
<p dir="ltr">Available below is a ZIP file with the two scripts we’ll use:   <br />One is the installation script, responsible for creating all the objects we require – the database, the service broker procedures, endpoints and queues. Everything you need to implement multi-threading in SQL Server.    <br />The other is a sample of how to use this mechanism, using simple queries and a WAITFOR DELAY command to simulate long execution times.</p>
<p dir="ltr"><a href="http://www.madeira.co.il/?dl_name=Service_Broker_Multi-Threading_v3.zip" target="_blank"><img style="margin: 0px 0px 10px" class="alignnone" title="Download" alt="" src="http://www.madeira.co.il/wp-content/uploads/2009/12/zip.png" width="128" height="128" /></a></p>
<p dir="ltr">The scripts are commented to help you understand what’s going on. But we’ll go over them bit by bit just in case.</p>
<h3 dir="ltr">The Installation Script</h3>
<p dir="ltr">In order to explain the installation script, I’ll list all the objects that we’re creating and explain the purpose of each object. More detailed information about the implementation can be found in the script itself.</p>
<p dir="ltr">
<ul dir="ltr">
<li>
<div><strong>SB_PQ_Test</strong>:          <br />That’s the database we’ll be using to create all the necessary objects.</div>
</li>
<li>
<div><strong>SB_PQ_ServiceBrokerLogs</strong>:          <br />This is a logging table which will be used to log the start and end of each query execution, and any errors that may occur.</div>
</li>
<li>
<div><strong>SB_PQ_ExecuteDynamicQuery</strong>:          <br />This is the procedure which will actually execute the dynamic queries. It builds the dynamic command, uses <a href="http://msdn.microsoft.com/en-us/library/ms188001.aspx" target="_blank">sp_executesql</a> to execute it, and returns the result as an output parameter. The name of the output parameter itself can be dynamic.</div>
</li>
<li>
<div><strong>SB_PQ_HandleQueue</strong>:          <br />This is the activation procedure that Service Broker executes when it creates a “reader instance”. Or in other words, when there’s something in the request queue.          <br />This procedure is the most important part because it’s responsible for retrieving messages from the request queue, execute the query (using SB_PQ_ExecuteDynamicQuery), and handle any errors that may occur in-between.</div>
</li>
<li>
<div><strong>SB_PQ_Request_Queue</strong>:</div>
</li>
<li>
<div>This is the queue where all query requests will be waiting to be processed. Its activation procedure is SB_PQ_HandleQueue.</div>
</li>
<li>
<div><strong>SB_PQ_Response_Queue</strong>:          <br />This is the queue into which query responses will be sent. Its doesn't have an activation procedure because query response extraction is done manually.</div>
</li>
<li>
<div><strong>[//SB_PQ/Message]</strong>:          <br />This is a simple message type of “Well Formed XML”. We’ll be using it to verify our messages.</div>
</li>
<li>
<div><strong>[//SB_PQ/Contract]</strong>:          <br />This is a contract defining that both target and initiator must send messages of type [//SB_PQ/Message].</div>
</li>
<li>
<div><strong>[//SB_PQ/ProcessReceivingService]</strong>:          <br />This is the service endpoint working as the “address” of request queries. We will be sending messages <em>into </em>this service. The queue it’ll be using to receive messages is SB_PQ_Request_Queue.</div>
</li>
<li>
<div><strong>[//SB_PQ/ProcessStartingService]</strong>:          <br />This is the service endpoint working as the “address” of response queries.          <br />We will be sending messages <em>from</em> this service. The queue it’ll be using to receive messages is SB_PQ_Response_Queue.</div>
</li>
<li>
<div><strong>SB_PQ_Start_Query</strong>:          <br />This is the public procedure that will used for starting an execution thread, by sending a request query to [//SB_PQ/ProcessStartingService].          <br />You can think of it as an API simplifying our use of all the above objects.          <br />It receives as parameters the SQL command that should be executed, the name of the output parameter (without the @), and the conversation group ID.</div>
</li>
<li>
<div><strong>SB_PQ_Get_Response_One</strong>:          <br />This is the public procedure that will be used to retrieve the results of our queries. It receives as a parameter the conversation group ID to be used, and returns the first result it finds as an output parameter. You may also think of it as part of the API simplifying our use of the above objects.</div>
</li>
</ul>
<p dir="ltr">Whew, that was a long list! Please note that since Service Broker works asynchronously in the background, error handling is extremely important. Note all the error handling, especially in the <strong>SB_PQ_HandleQueue</strong> procedure.</p>
<h3 dir="ltr">The Sample Script</h3>
<p dir="ltr">Now we can really get down to business. I’ll go over the important parts in the script and explain each of them:</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- random workload simulation settings</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @MinDelay = 10</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @MaxDelay = 30</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @ConvGroup = NEWID();    <span style="color: #008000">-- the messages will be grouped in a specific conversation group</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @NumOfSegments = 3;        <span style="color: #008000">-- number of &quot;threads&quot; to use</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- create several segments</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @Segment = 1;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">WHILE</span> @Segment &lt;= @NumOfSegments</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">BEGIN</pre>
<p><!--CRLF--></div>
</p></div>
<p>In our sample, we create several “segments” (or threads) where each of them will have a random delay between 10 and 30 seconds, and execute a simple query returning its details. In the above script we define the minimum and maximum delay in seconds, set the conversation group ID by which our threads will be grouped, total number of threads (3 in our case), and we start looping per each of the threads.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- random delay between @MinDelay and @MaxDelay seconds to simulate long execution time</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @Delay = <span style="color: #006080">'00:00:'</span> + <span style="color: #0000ff">CONVERT</span>(<span style="color: #0000ff">varchar</span>(8), ROUND(RAND() * (@MaxDelay - @MinDelay),0) + @MinDelay)</pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script simply prepares the delay representation by generating a random number of seconds as we defined earlier (between 10 and 30).</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- build our dynamic SQL command. note the use of XML as the result.</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @<span style="color: #0000ff">SQL</span> = N<span style="color: #006080">'</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">WAITFOR DELAY '</span><span style="color: #006080">''</span> + @Delay + <span style="color: #006080">''</span><span style="color: #006080">';</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">SET @SB_PQ_Result = </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">(</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    SELECT</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">        Segment = '</span> + <span style="color: #0000ff">CONVERT</span>(nvarchar(<span style="color: #0000ff">max</span>), @Segment) + N<span style="color: #006080">',</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">        Delay = '</span><span style="color: #006080">''</span> + @Delay + N<span style="color: #006080">''</span><span style="color: #006080">',</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">        StartDate = GETDATE(),</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">        Name = QUOTENAME(name),</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">        object_id, type, modify_date</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    FROM</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">        SB_PQ_Test.sys.tables AS Tab</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    FOR XML AUTO, ELEMENTS</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">'</span>;</pre>
<p><!--CRLF--></div>
</p></div>
<p>In the script above we create the dynamic SQL command which will be executed by the current thread. Note the use of <strong>XML AUTO, ELEMENTS </strong>to format the results in XML and put them in the output parameter.</p>
<p dir="ltr">Also note the use of <strong>WAITFOR DELAY </strong>at the start to simulate long execution time.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- Send request to queue</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">EXEC</span> SB_PQ_Start_Query @<span style="color: #0000ff">SQL</span>, @OutputParam, @ConvGroup;</pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script executes the API procedure <strong>SB_PQ_Start_Query</strong> with the SQL command we prepared, the name of the output parameter, and the conversation group ID. This will put the message in the request queue and continue executing without waiting for a response (the magic of asynchronous work).</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    <span style="color: #008000">-- increment segment index</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">SET</span> @Segment = @Segment + 1;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">END</span></pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script increases the thread index so we can continue to the next one.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- init final result</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">DECLARE</span> @TotalResult XML;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @TotalResult = <span style="color: #006080">'&lt;Tables&gt; &lt;/Tables&gt;'</span></pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script initializes an XML variable called @TotalResult which will contain all the results we’re about to receive.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- count based on number of segments that we created earlier</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @Segment = 1;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">WHILE</span> @Segment &lt;= @NumOfSegments</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">BEGIN</pre>
<p><!--CRLF--></div>
</p></div>
<p>In this part of the script we’re resetting the @Segment index and looping again based on the number of threads in @NumOfSegments.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    <span style="color: #008000">-- Get segment from response queue</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">EXEC</span> SB_PQ_Get_Response_One @ConvGroup, @CurrentResult <span style="color: #0000ff">OUTPUT</span></pre>
<p><!--CRLF--></div>
</p></div>
<p>In the above script, we use the API procedure SB_PQ_Get_Response_One to retrieve a single result from any of the threads (whichever finished executing first). The result will be returned in the output variable @CurrentResult.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- insert into TotalResults using XML DML (syntax for SQL2008 and newer)</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SET</span> @TotalResult.<span style="color: #0000ff">modify</span>(<span style="color: #006080">'</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">insert sql:variable(&quot;@CurrentResult&quot;)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">into (/Tables)[1] '</span>);</pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script uses XML DML language with reference to the @CurrentResult variable to insert its contents into the @TotalResult variable.</p>
<p dir="ltr">Please note that this method of “inserting” a SQL variable into an XML document is <strong>SQL 2008 </strong>syntax and won’t work in older versions.</p>
<p dir="ltr">If you have SQL Server 2005, you will need to work a little harder to collect the results (for example, declaring @TotalResult as nvarchar(4000) without a closing tag, concatenating the results one-by-one, and only at the end concatenate the closing tag as well).</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    <span style="color: #008000">-- increment segment index</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">SET</span> @Segment = @Segment + 1;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">END</pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script increases the thread index so we can continue to the next one.</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- return final result (as XML)</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SELECT</span> @TotalResult.query(<span style="color: #006080">'.'</span>) <span style="color: #0000ff">AS</span> FinalResult</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- return final result (as relational table)</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SELECT</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    Segment        = T.XRecord.query(<span style="color: #006080">'.'</span>).<span style="color: #0000ff">value</span>(<span style="color: #006080">'(/Tab/Segment)[1]'</span>,<span style="color: #006080">'varchar(100)'</span>),</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    Delay        = T.XRecord.query(<span style="color: #006080">'.'</span>).<span style="color: #0000ff">value</span>(<span style="color: #006080">'(/Tab/Delay)[1]'</span>,<span style="color: #006080">'varchar(8)'</span>),</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    StartDate    = T.XRecord.query(<span style="color: #006080">'.'</span>).<span style="color: #0000ff">value</span>(<span style="color: #006080">'(/Tab/StartDate)[1]'</span>,<span style="color: #006080">'datetime'</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">FROM</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">    @TotalResult.nodes(<span style="color: #006080">'/Tables/Tab'</span>) <span style="color: #0000ff">AS</span> T(XRecord)</pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script shows two methods of how you can return your final data.</p>
<p dir="ltr">The first method returns the simple XML representation of @TotalResult.</p>
<p dir="ltr">The second method shows how you can break down each element in @TotalResult (using the <em>nodes()</em> method) and display the values of each element (using the <em>value()</em> method).</p>
<p dir="ltr">
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #008000">-- check the SB logs to see how many unique sessions executed our requests</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">DECLARE</span> @NumOfSessions <span style="color: #0000ff">INT</span>;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SELECT</span> @NumOfSessions = <span style="color: #0000ff">COUNT</span>(<span style="color: #0000ff">DISTINCT</span> SPID)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">FROM</span> SB_PQ_ServiceBrokerLogs</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">WHERE</span> LogDate &gt;= @StartTime</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">PRINT</span> <span style="color: #0000ff">CONVERT</span>(nvarchar(100),@NumOfSessions) + <span style="color: #006080">' unique sessions participated in execution'</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">&#160;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">SELECT</span> *</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">FROM</span> SB_PQ_ServiceBrokerLogs</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">WHERE</span> LogDate &gt;= @StartTime</pre>
<p><!--CRLF--></div>
</p></div>
<p>The above script is a sort of “debug” script which will display information from our Service Broker logging table, specifically showing how many unique sessions participated in execution since the start of the script, and displays the contents of the logging table from that period of time.</p>
<h3 dir="ltr">Execution Delay</h3>
<p dir="ltr">It takes Service Broker several seconds before activating more than one reader instance. However, because our activation procedure continues waiting for new requests even after finishing an execution, once a reader instance is activated it’ll stay active until it’s manually shut down.</p>
<p dir="ltr">As a result of this behavior, your first execution in multi-threading may not be as fast as you’d expect. But from the second try onwards it shouldn’t take longer than the longest running query.</p>
<h3 dir="ltr">Customizing for Your Version</h3>
<p dir="ltr">The above sample script is a very crude sample of how to use the API we created using the installation script. But this architecture can be used for just about anything you want to execute multi-threaded.</p>
<p dir="ltr">Your own implementation will probably be much different.</p>
<p dir="ltr">You may want to perform a query on a large range of records, and prefer to break down that range to several sub-ranges, where each sub-range will be a separate thread / segment.</p>
<p dir="ltr">Maybe you have several different queries and you need to do different things with them, so you’ll have several different executions of the API procedures (you’d need to think how to identify each query though, perhaps by adding that information in the XML somewhere).</p>
<p dir="ltr">Maybe you’re not even performing queries. Maybe it’s some maintenance tasks you wish to perform simultaneously (you still should expect a response of some kind, for example a message notifying of success or failure).</p>
<p dir="ltr">In any case, you’ll need to follow these rules:</p>
<p dir="ltr">
<ul dir="ltr">
<li>
<div>Your SQL command must make use of an output parameter of type XML. You don’t need to declare it inside your command, but simply put into it the XML result you want to expect.</div>
</li>
<li>
<div>Take note of the name of the output parameter you’re using and provide it during the execution of the <strong>SB_PQ_Start_Query </strong>procedure.</div>
</li>
<li>
<div>If there’s a chance other sessions will be using this API at the same time, it’s extremely important to make use of the Conversation Group ID parameter so you’d have a way of separating between the data of different sessions.</div>
</li>
<li>
<div>In any case, the thread will try to return a response even if there was an error in your query (NULL will be returned). So in order to prevent clogging on the response queue, don’t forget to use the <strong>SB_PQ_Get_Response_One </strong>procedure to take them out of the queue.</div>
</li>
</ul>
<h3 dir="ltr">Conclusion</h3>
<p dir="ltr">This was but one example of how you can use Service Broker to improve your work with SQL Server. I’ll be working on new examples so check back soon!</p>
<p dir="ltr">I hope my post wasn’t too complicated or confusing. But if you have any questions, please post them in the comment section below, and I’d be happy to help!</p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/service-broker-sample-multi-threading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8235;Using Reporting Services as your Software Frontend&#8236;</title>		<link>http://www.madeira.co.il/using-reporting-services-as-your-software-frontend/</link>
		<comments>http://www.madeira.co.il/using-reporting-services-as-your-software-frontend/#comments</comments>
		<pubDate>Wed, 08 Feb 2012 10:17:31 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[כללי]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[Application]]></category>
		<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Manage Data]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Reporting Services]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=4073</guid>
		<description><![CDATA[&#8235;Reporting Services is an excellent platform for reports. But you can also use it for managing data. Recommended when you lack programmers, budget and / or time.&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/4073.jpg&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<p dir="ltr">Microsoft SQL Server Reporting Services is an excellent and easy-to-use platform for creating, viewing, managing, and subscribing to reports of all shapes and sizes.</p>
<p dir="ltr">Technically, this platform is meant for nothing more than reports. It’s true that reporting is a huge field and you can do all kinds of cool stuff with it, but it’s still just reporting – or in other words: Viewing data.</p>
<p dir="ltr">However, it’s also possible to use this platform for updating data. Whether it’s deleting items, updating them, or even inserting new records.<br />
It’s especially good when your organization doesn’t have skilled programmers that can create a pretty-looking graphical user interface (GUI). Or when there are budget and / or time restrictions.</p>
<p dir="ltr">The key to this special usage of Reporting Services is the Data Sets of type “<strong>Stored Procedure</strong>”. In SQL Server Reporting Services, one form of getting data for your report is executing a stored procedure in your database.<br />
However, a stored procedure (as you probably know) can do a lot more than just querying data. Technically, when you use stored procedures in SSRS, all they need to do is:</p>
<p dir="ltr">
<ol dir="ltr">
<li>
<div>Receive parameter values.</div>
</li>
<li>Do some processing.</li>
<li>Return a set of data.</li>
</ol>
<p dir="ltr">The 2nd step can be absolutely anything. It can be an insertion of new data, updating or deleting, and even some complex combination of everything.</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/02/image.png" rel="wp-prettyPhoto[g4073]"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://www.madeira.co.il/wp-content/uploads/2012/02/image_thumb.png" border="0" alt="image" width="326" height="134" /></a></p>
<p dir="ltr">Actually, you don’t really need a stored procedure to do this. You can also use the <strong>Text</strong> data set and write all your logic directly in the report. But in my opinion it’s not so comfortable and a lot more cumbersome to work like that, especially when you need to debug your logic, or when the same logic is used in several reports.</p>
<p dir="ltr">Also, it’s important to remember that your stored procedure <strong><em>must return a single result set</em></strong> at the end. Don’t forget this is Reporting Services we’re dealing with, and it expects to receive a single result set for the data it needs to display.</p>
<p dir="ltr">Personally, I like implementing this using what I call an “output temporary table”. The idea is that throughout your logic, you may have several steps, and you want to know the outcome of each of these steps (success or failure, number of rows affected etc.),. To do so, I create a temporary table (best if it’s a variable table), and at the success or failure of each step, I insert a record with a message in that table. At the end, I simply SELECT the entire table and display it in the report.</p>
<h2 dir="ltr"><strong><span style="text-decoration: underline;">Updating Rows</span></strong></h2>
<p dir="ltr">For example, here is a sample procedure that I wrote which transfers all the employees from one manager to another (in the AdventureWorks database):</p>
<div id="codeSnippetWrapper" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;">
<div id="codeSnippet" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> MoveEmployeesFromManagerToManager</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    @SourceManagerID <span style="color: #0000ff;">INT</span>,</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    @DestinationManagerID <span style="color: #0000ff;">INT</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">AS</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">DECLARE</span> @RCount <span style="color: #0000ff;">INT</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">DECLARE</span> @<span style="color: #0000ff;">Output</span> <span style="color: #0000ff;">AS</span> <span style="color: #0000ff;">TABLE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    ( Msg NVARCHAR(<span style="color: #0000ff;">MAX</span>) )</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">BEGIN</span> TRY</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">VALUES</span>(</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    N<span style="color: #006080;">'Moving employees from ManagerID '</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    + <span style="color: #0000ff;">CONVERT</span>(nvarchar(50), @SourceManagerID)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    + <span style="color: #006080;">' to ManagerID '</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    + <span style="color: #0000ff;">CONVERT</span>(nvarchar(50), @DestinationManagerID)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    + <span style="color: #006080;">'...'</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    )</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">BEGIN</span> <span style="color: #0000ff;">TRANSACTION</span></pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">UPDATE</span> Employees</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">SET</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        ManagerID = @DestinationManagerID</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">OUTPUT</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        N<span style="color: #006080;">'Moved EmployeeID '</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        + <span style="color: #0000ff;">CONVERT</span>(nvarchar(50), INSERTED.EmployeeID)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">INTO</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">FROM</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        HumanResources.Employee <span style="color: #0000ff;">AS</span> Employees</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">WHERE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        ManagerID = @SourceManagerID</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">SET</span> @RCount = @@<span style="color: #0000ff;">ROWCOUNT</span>;</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">IF</span> @RCount &gt; 0</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">BEGIN</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        <span style="color: #0000ff;">VALUES</span>(</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        N<span style="color: #006080;">'Moved '</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        + <span style="color: #0000ff;">CONVERT</span>(nvarchar(50), @RCount)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        + <span style="color: #006080;">' employee(s).'</span>)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">END</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">ELSE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">BEGIN</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        <span style="color: #0000ff;">VALUES</span>(N<span style="color: #006080;">'No employees were updated.'</span>)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">END</span></pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">COMMIT</span> <span style="color: #0000ff;">TRANSACTION</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">END</span> TRY</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">BEGIN</span> CATCH</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">IF</span> <span style="color: #cc6633;">@@TRANCOUNT</span> &gt; 0</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        <span style="color: #0000ff;">ROLLBACK</span> <span style="color: #0000ff;">TRANSACTION</span>;</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">VALUES</span>(N<span style="color: #006080;">'CRITICAL ERROR: '</span> + ERROR_MESSAGE())</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">END</span> CATCH</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> @Output</pre>
<p><!--CRLF--></p>
</div>
</div>
<p dir="ltr">As you can see, before performing the actual update, I put a message into the @Output table informing of the operation. Then I use the <a href="http://msdn.microsoft.com/en-us/library/ms177564.aspx" target="_blank">UPDATE…OUTPUT…INTO</a> syntax to save in the @Output table all the employees that were updated. Finally, I insert another message in @Output informing of the success or failure of the operation.</p>
<p dir="ltr">Most importantly, note that the entire logic is enveloped in a <a href="http://msdn.microsoft.com/en-us/library/ms175976.aspx" target="_blank">TRY..CATCH</a> block, and in the CATCH segment I put into the @Output table the error message that occurred.</p>
<p dir="ltr">When you create a Reporting Services report which uses this procedure, you specify this procedure as the source of the data set, and add a table which will display the contents of the query (from the @Output table).</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/02/image1.png" rel="wp-prettyPhoto[g4073]"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border-width: 0px;" title="image" src="http://www.madeira.co.il/wp-content/uploads/2012/02/image_thumb1.png" border="0" alt="image" width="239" height="244" /></a></p>
<p dir="ltr">Defining the stored procedure as the source of the data set.</p>
<p dir="ltr">It will look something like this:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/02/image3.png" rel="wp-prettyPhoto[g4073]"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://www.madeira.co.il/wp-content/uploads/2012/02/image_thumb3.png" border="0" alt="image" width="289" height="193" /></a></p>
<h2 dir="ltr"><span style="text-decoration: underline;">Deleting Rows</span></h2>
<p dir="ltr">Here is  another sample where I have two reports:</p>
<p dir="ltr">
<ol dir="ltr">
<li>
<div>A report displaying the contents of the DatabaseLog table.</div>
</li>
<li>
<div>A report which deletes a record from DatabaseLog table.</div>
</li>
</ol>
<p dir="ltr">The first report will feature a button which will navigate me to the second report, and on the way pass on the DatabaseLogID which I want to delete. The second report will use a procedure which will delete the record with the provided ID, and display a message about it.</p>
<p dir="ltr">The first report:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/02/image4.png" rel="wp-prettyPhoto[g4073]"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://www.madeira.co.il/wp-content/uploads/2012/02/image_thumb4.png" border="0" alt="image" width="372" height="124" /></a></p>
<p dir="ltr">The second report:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/02/image5.png" rel="wp-prettyPhoto[g4073]"><img style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://www.madeira.co.il/wp-content/uploads/2012/02/image_thumb5.png" border="0" alt="image" width="244" height="90" /></a></p>
<p dir="ltr">And here is the script for its procedure:</p>
<div id="codeSnippetWrapper" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;">
<div id="codeSnippet" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> DeleteDatabaseLogRow</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    @DatabaseLogID <span style="color: #0000ff;">INT</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">AS</span></pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">DECLARE</span> @<span style="color: #0000ff;">Output</span> <span style="color: #0000ff;">AS</span> <span style="color: #0000ff;">TABLE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">(Msg NVARCHAR(<span style="color: #0000ff;">MAX</span>))</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">BEGIN</span> TRY</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">VALUES</span> (<span style="color: #006080;">'Deleting record with DatabaseLogID '</span> + <span style="color: #0000ff;">CONVERT</span>(<span style="color: #0000ff;">varchar</span>(50),@DatabaseLogID))</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">DELETE</span> <span style="color: #0000ff;">FROM</span> DatabaseLog</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">WHERE</span> DatabaseLogID = @DatabaseLogID</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">IF</span> <span style="color: #cc6633;">@@ROWCOUNT</span> &gt; 0</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        <span style="color: #0000ff;">VALUES</span>(<span style="color: #006080;">'Successfully deleted record.'</span>)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">ELSE</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        <span style="color: #0000ff;">VALUES</span>(<span style="color: #006080;">'Error: No such record found.'</span>)</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">END</span> TRY</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">BEGIN</span> CATCH</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">IF</span> <span style="color: #cc6633;">@@TRANCOUNT</span> &gt; 0</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">        <span style="color: #0000ff;">ROLLBACK</span> <span style="color: #0000ff;">TRANSACTION</span>;</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    INSERT <span style="color: #0000ff;">INTO</span> @<span style="color: #0000ff;">Output</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">    <span style="color: #0000ff;">VALUES</span>(N<span style="color: #006080;">'CRITICAL ERROR: '</span> + ERROR_MESSAGE())</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">END</span> CATCH</pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> @Output</pre>
<p><!--CRLF--></p>
</div>
</div>
<h2 dir="ltr"><span style="text-decoration: underline;">Inserting Data</span></h2>
<p dir="ltr">Another example (which I will not demonstrate here), is performing an INSERT to a table, where the report parameters represent the values you wish to enter into each column.</p>
<h2 dir="ltr"><span style="text-decoration: underline;">XP_CMDSHELL</span></h2>
<p dir="ltr">Another interesting example would be to execute something that’s even outside SQL Server. That could be a standalone EXE file, or some DOS command that copies or deletes files, etc.. These commands will be executed using XP_CMDSHELL (assuming  it’s enabled and your login has the correct permissions). Remember that XP_CMDSHELL returns a query which contains the resulting output from the operation. This output can be saved in our @Output table and then displayed in the report.</p>
<p dir="ltr">For example, suppose we have a table with file or folder paths, and we create a report where we move these files or folders to a new location.</p>
<p dir="ltr">For this you’d need to be familiar with the basic CMD commands such as XCOPY, DEL, MOVE and possibly DIR. But that is beyond the scope of this blog post. Don’t worry though, there’s plenty of resources on the internet for this.</p>
<p dir="ltr">Here is a sample of using XP_CMDSHELL in conjunction with our @Output table in order to move an entire folder from one location to another. It’s pretty straightforward, so I’ll leave the rest to you:</p>
<div id="codeSnippetWrapper" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.71%; font-family: 'Courier New', courier, monospace; direction: ltr; height: 112px; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;">
<div id="codeSnippet" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">SET</span> @CMD = <span style="color: #006080;">'xcopy /E /C "'</span> + @Source + N<span style="color: #006080;">'\*.*" "'</span> + @Destination + <span style="color: #006080;">'\*.*"'</span></pre>
<p><!--CRLF--></p>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">INSERT <span style="color: #0000ff;">INTO</span> @Msg</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #0000ff;">EXEC</span> xp_cmdshell @CMD</pre>
<p><!--CRLF--></p>
</div>
</div>
<h2 dir="ltr"><span style="text-decoration: underline;">Conclusion</span></h2>
<p dir="ltr">As you can guess, the possibilities are  almost endless. The only problem I could think of is when you need to insert a large amount of rows into some table. Using the report parameters is convenient for providing column values of a single row, but a group of rows is another matter altogether. At the least you could use Microsoft Access linked to a SQL Server to easily enter groups of rows in a grid view. Theoretically, you can use SSIS to import Excel files with multiple records to insert, but that’s also outside our scope of Reporting Services. Other than that, and the built-in graphical interface of SQL Server Management Studio, I don’t know a simpler way to do this (without programming your own GUI obviously).</p>
<p dir="ltr">Thoughts? More interesting ideas? Post them in the comments!</p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/using-reporting-services-as-your-software-frontend/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>&#8235;LOOP, HASH and MERGE Join Types&#8236;</title>		<link>http://www.madeira.co.il/loop-hash-and-merge-join-types/</link>
		<comments>http://www.madeira.co.il/loop-hash-and-merge-join-types/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 11:22:00 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[כללי]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[Hash]]></category>
		<category><![CDATA[Join]]></category>
		<category><![CDATA[Join types]]></category>
		<category><![CDATA[Loops]]></category>
		<category><![CDATA[Match]]></category>
		<category><![CDATA[Merge]]></category>
		<category><![CDATA[Nested Loops]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=3143</guid>
		<description><![CDATA[&#8235;Today I'll talk about the available JOIN operator types in SQL Server (Nested Loops, Hash and Merge Joins), their differences, best practices and complexity.&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/3143.jpg&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<h3 dir="ltr" align="center">Today I'll talk about the available JOIN operator types in SQL Server (Nested Loops, Hash and Merge Joins), their differences, best practices and complexity.</h3>
<p dir="ltr">For the samples in this post, we'll use the free <strong>AdventureWorks</strong> database sample available here: <a href="http://msftdbprodsamples.codeplex.com/releases/view/4004" target="_blank">http://msftdbprodsamples.codeplex.com/releases/view/4004</a></p>
<h2 dir="ltr">Introduction: What are Join Operators?</h2>
<p dir="ltr">A join operator is a type of an algorithm which the SQL Server Optimizer chooses in order to implement logical joins between two sets of data.</p>
<p dir="ltr">The SQL Server Optimizer may choose a different algorithm for different scenarios based on the requested query, available indexes, statistics and number of estimated rows in each data set.</p>
<p dir="ltr">It's possible to find the operator which was used by looking at the execution plan that SQL Server has prepared for your query.</p>
<p dir="ltr">For more information on execution plans and how to read them, I recommend checking out the first chapter out of Grant Fritchey's excellent book:    <br /><a href="http://www.simple-talk.com/sql/performance/execution-plan-basics/" target="_blank">http://www.simple-talk.com/sql/performance/execution-plan-basics/</a></p>
<h2 dir="ltr">NESTED LOOPS</h2>
<p dir="ltr">&quot;Nested Loops&quot; is the simplest operator of the bunch.</p>
<p dir="ltr">We'll take the following query as an example (which gets some order detail columns for orders placed during July 2001):</p>
<pre dir="ltr" class="csharpcode"><span class="kwrd">SELECT</span>
OH.OrderDate, OD.OrderQty, OD.ProductID, OD.UnitPrice
<span class="kwrd">FROM</span>
    Sales.SalesOrderHeader <span class="kwrd">AS</span> OH
<span class="kwrd">JOIN</span>
    Sales.SalesOrderDetail <span class="kwrd">AS</span> OD
<span class="kwrd">ON</span>
    OH.SalesOrderID = OD.SalesOrderID
<span class="kwrd">WHERE</span>
    OH.OrderDate <span class="kwrd">BETWEEN</span> <span class="str">'2001-07-01'</span> <span class="kwrd">AND</span> <span class="str">'2001-07-31'</span></pre>
<p dir="ltr">The resulting execution plan looks like this:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image0022.jpg" rel="wp-prettyPhoto[g3143]"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image002_thumb2.jpg" width="368" height="122" /></a></p>
<p dir="ltr">The operator on the top right is called the <strong>outer input</strong> and the one just below it is called the <strong>inner input</strong>.</p>
<p dir="ltr">What the &quot;Nested Loops&quot; operator basically does is: <span style="text-decoration: underline">For each record</span> from the <strong>outer input</strong> – find matching rows from the <strong>inner input</strong>.</p>
<p dir="ltr">Technically, this means that the clustered index scan you see as the outer input is executed once to get all the relevant records, and the clustered index seek you see below it is executed <span style="text-decoration: underline">for each record</span> from the outer input.</p>
<p dir="ltr">We'll verify this information by placing the cursor over the Clustered Index Scan operator and looking at the tooltip:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image0041.jpg" rel="wp-prettyPhoto[g3143]"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image004_thumb1.jpg" width="216" height="288" /></a></p>
<p dir="ltr">We can see that the estimated number of executions is 1. We'll look at the tooltip of the Clustered Index Seek:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image0061.jpg" rel="wp-prettyPhoto[g3143]"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image006_thumb1.jpg" width="214" height="300" /></a></p>
<p dir="ltr">This time we can see that the estimated number of executions is 179 which is the approximate number of rows returned from the outer input.</p>
<p dir="ltr">In terms of complexity (assume <strong>N</strong> is the number of rows from the outer output and <strong>M</strong> is the total number of rows in the SalesOrderDetail table): The complexity of this query is: <strong>O(NlogM) w</strong>here &quot;logM&quot; is the complexity of each seek in the inner input.</p>
<p dir="ltr">The SQL Server Optimizer will prefer to choose this operator type when the outer input is small and the inner input has an index on the column(s) by which the two data sets are joined. The bigger the difference in number of rows between the outer and inner inputs, the more benefit this operator will provide over the other operator types.</p>
<p dir="ltr">Having indexes and up-to-date statistics is crucial for this join type, because you don't want SQL Server to accidently think there's a small number of rows in one of the inputs when in fact there are a whole lot. For example: Performing 10 times index seek is nothing like performing 100,000 times index seek, especially if the table size of the inner input is around 120,000 and you'd be better off doing one table scan instead.</p>
<h2 dir="ltr">MERGE Join</h2>
<p dir="ltr">The &quot;Merge&quot; algorithm is the most efficient way to join between two very large sets of data which are both sorted on the join key.</p>
<p dir="ltr">We'll use the following query as an example (which returns a list of customers and their sale order identifiers):</p>
<pre dir="ltr" class="csharpcode"><span class="kwrd">SELECT</span>
    OC.CustomerID, OH.SalesOrderID
<span class="kwrd">FROM</span>
    Sales.SalesOrderHeader <span class="kwrd">AS</span> OH
<span class="kwrd">JOIN</span>
    Sales.Customer <span class="kwrd">AS</span> OC
<span class="kwrd">ON</span>
    OH.CustomerID = OC.CustomerID</pre>
<p dir="ltr">The execution plan for this query is:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image0081.jpg" rel="wp-prettyPhoto[g3143]"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image008_thumb1.jpg" width="357" height="114" /></a></p>
<p dir="ltr">
<ul dir="ltr">
<li>
<div>First, we'll notice that both of the data sets are sorted on the CustomerID column: The Customer table because that's the clustered primary key, and the SalesOrderHeader table because there's a nonclustered index on the CustomerID column.</div>
</li>
<li>
<div>By the width of the arrows between the operators (and by placing the cursor over them), we can see that the number of rows returned from each set is rather large.</div>
</li>
<li>
<div>In addition, we used the equality operator (=) in the ON clause (the Merge join requires an equality operator).</div>
</li>
</ul>
<p dir="ltr">These three factors cause SQL Server Optimizer to choose the Merge Join for this query.</p>
<p dir="ltr">The biggest performance gain from this join type is that both input operators are executed only once. We can verify this by placing the cursor over them and see that the number of executions is 1 for both of the operators. Also, the algorithm itself is very efficient:</p>
<p dir="ltr">The Merge Join simultaneously reads a row from each input and compares them using the join key. If there's a match, they are returned. Otherwise, the row with the smaller value can be discarded because, since both inputs are sorted, the discarded row will not match any other row on the other set of data.</p>
<p dir="ltr">This repeats until one of the tables is completed. Even if there are still rows on the other table, they will clearly not match any rows on the fully-scanned table, so there is no need to continue. Since both tables can potentially be scanned, the maximum cost of a Merge Join is the sum of both inputs. Or in terms of complexity: <strong>O(N+M)</strong></p>
<p dir="ltr">If the inputs are not both sorted on the join key, the SQL Server Optimizer will most likely not choose the Merge join type and instead prefer the Hash join (will be explained soon). However if it does anyway (whether it's because it was forced to due to a join hint, or because it was still the most efficient), then SQL will need to sort the table which is not already sorted on the join key.</p>
<h2 dir="ltr">HASH Match</h2>
<p dir="ltr">The &quot;Hash&quot; join type is what I call &quot;the go-to guy&quot; of the join operators. It's the one operator chosen when the scenario doesn't favor in any of the other join types. This happens when the tables are not properly sorted, and/or there are no indexes. When SQL Server Optimizer chooses the Hash join type, it's usually a bad sign because something probably could've been done better (for example, adding an index). However, in some cases (complex queries mostly), there's simply no other way.</p>
<p dir="ltr">We'll use the following query as an example (which gets the first and last names of contacts starting with &quot;John&quot; and their sales order identifiers):</p>
<pre dir="ltr" class="csharpcode"><span class="kwrd">SELECT</span>
    OC.FirstName, OC.LastName, OH.SalesOrderID
<span class="kwrd">FROM</span>
    Sales.SalesOrderHeader <span class="kwrd">AS</span> OH
<span class="kwrd">JOIN</span>
    Person.Contact <span class="kwrd">AS</span> OC
<span class="kwrd">ON</span>
    OH.ContactID = OC.ContactID
<span class="kwrd">WHERE</span>
    OC.FirstName <span class="kwrd">LIKE</span> <span class="str">'John%'</span></pre>
<p dir="ltr">The execution plan looks like this:</p>
<p dir="ltr"><a href="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image0101.jpg" rel="wp-prettyPhoto[g3143]"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://www.madeira.co.il/wp-content/uploads/2012/01/clip_image010_thumb1.jpg" width="373" height="124" /></a></p>
<p dir="ltr">Because there's no index on the ContactID column in the SalesOrderHeader table, SQL Server chooses the Hash join type.</p>
<p dir="ltr">Before diving into the example, I'll first explain two important concepts: A ”Hashing&quot; function and a &quot;Hash Table&quot;.</p>
<p dir="ltr">&quot;Hashing&quot; is a programmatic function which takes one or more values and converts them to a single symbolic value (usually numeric). The function is usually one-way meaning you can't convert the symbolic value back to its original value(s), but it's deterministic meaning if you provide the same value as input you will always get the same symbolic value as output. Also, it's possible for several different inputs to result in the same output hash value (meaning, the function isn't necessarily unique).</p>
<p dir="ltr">A &quot;Hash Table&quot; is a data structure that divides all rows into equal-sized &quot;buckets&quot;, where each &quot;bucket&quot; is represented by a hash value. This means that when you activate the hash function on some row, using the result you'll know immediately to which bucket it belongs.</p>
<p dir="ltr">As with the Merge join, the two input operators are executed only once. We can verify this by looking at the tooltips of the input operators.</p>
<p dir="ltr">Using available statistics, SQL Server will choose the smaller of the two inputs to serve as the <strong>build input</strong> and it will be the one used to build the hash table in memory. If there's not enough memory for the hash table, SQL Server will use physical disk space in TEMPDB. After the hash table is built, SQL Server will get the data from the larger table, called the <strong>probe input</strong>, compare it to the hash table using a <em>hash match function</em>, and return any matched rows. In graphical execution plans, the <strong>build input</strong> will always be the one on top, and the <strong>probe input</strong> will be the one below.</p>
<p dir="ltr">As long as the smaller table is very small, this algorithm can be very efficient. But if both tables are very large, this can be a very costly execution plan.</p>
<p dir="ltr">SQL Server Optimizer uses statistics to figure out the cardinality of the values. Using that information, it <em>dynamically creates a hash function </em>which will divide the data into as many buckets with sizes as equal as possible.</p>
<p dir="ltr">Because&#160; it’s so dynamic,&#160; it’s difficult to estimate the complexity of the creation of the hash table and the&#160; complexity of each hash match. Because SQL Server Optimizer performs this dynamic operation during execution time and not during compilation time, sometimes the values you see in the execution plan are incorrect. In some cases, you could compare a hash join and a nested loops join, see that according to the execution plans the nested loop is more expensive (in terms of logical reads etc.), when in fact the hash join executes much slower (because its cost estimation is incorrect).</p>
<p dir="ltr">For our complexity terms, we’ll assume <strong>h<sub>c</sub> </strong>is the complexity of the hash table creation, and <strong>h<sub>m</sub> </strong>is the complexity of the hash match function. Therefore, the complexity of the Hash join will be <strong>O(N*h<sub>c</sub> + M*h<sub>m</sub> + J)</strong> where <strong>N</strong> is the smaller data set, <strong>M</strong> is the larger data set and <strong>J</strong> is a “joker” complexity addition for the dynamic calculation and creation of the hash function.</p>
<p dir="ltr">Microsoft has an interesting page in Books Online that describes further Hash Join sub-types and additional aspects about them. I highly recommend you read it: <a href="http://msdn.microsoft.com/en-us/library/ms189313.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/ms189313.aspx</a></p>
<h2 dir="ltr">Query Hints</h2>
<p dir="ltr">Using Query Hints, it's possible to force SQL Server to use specific join types. However, <strong>it's highly not recommended</strong> to do so especially in production environments, because the same join type may not be the best choice forever (because data can change), and SQL Server Optimizer usually has it right (assuming statistics are up-to-date).</p>
<p dir="ltr">I'll talk about them just so you can experiment with the different join types on your test environment and see the differences.</p>
<p dir="ltr">To force SQL Server to use specific join types using query hints, you add the <strong>OPTION</strong> clause at the end of the query, and use the keywords<strong> LOOP JOIN</strong>, <strong>MERGE JOIN</strong> or <strong>HASH JOIN</strong>.</p>
<p dir="ltr">Try executing the above queries with different join hints and see what happens:</p>
<pre dir="ltr" class="csharpcode"><span class="kwrd">SELECT</span> OC.CustomerID, OH.SalesOrderID
<span class="kwrd">FROM</span> Sales.SalesOrderHeader <span class="kwrd">AS</span> OH
<span class="kwrd">JOIN</span> Sales.Customer <span class="kwrd">AS</span> OC
<span class="kwrd">ON</span> OH.CustomerID = OC.CustomerID
<span class="kwrd">OPTION</span> (HASH <span class="kwrd">JOIN</span>)

<span class="kwrd">SELECT</span> OC.FirstName, OC.LastName, OH.SalesOrderID
<span class="kwrd">FROM</span> Sales.SalesOrderHeader <span class="kwrd">AS</span> OH
<span class="kwrd">JOIN</span> Person.Contact <span class="kwrd">AS</span> OC
<span class="kwrd">ON</span> OH.ContactID = OC.ContactID
<span class="kwrd">WHERE</span> OC.FirstName <span class="kwrd">LIKE</span> <span class="str">'John%'</span>
<span class="kwrd">OPTION</span> (LOOP <span class="kwrd">JOIN</span>)

<span class="kwrd">SELECT</span> OC.FirstName, OC.LastName, OH.SalesOrderID
<span class="kwrd">FROM</span> Sales.SalesOrderHeader <span class="kwrd">AS</span> OH
<span class="kwrd">JOIN</span> Person.Contact <span class="kwrd">AS</span> OC
<span class="kwrd">ON</span> OH.ContactID = OC.ContactID
<span class="kwrd">WHERE</span> OC.FirstName <span class="kwrd">LIKE</span> <span class="str">'John%'</span>
<span class="kwrd">OPTION</span> (MERGE <span class="kwrd">JOIN</span>)</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<h2 dir="ltr">Summary</h2>
<h3 dir="ltr">Nested Loops</h3>
<p dir="ltr">
<ul dir="ltr">
<li>
<div>Complexity: O(NlogM)</div>
</li>
<li>
<div>Used usually when one table is significantly small</div>
</li>
<li>
<div>The larger table has an index which allows seeking it using the join key</div>
</li>
</ul>
<h3 dir="ltr">Merge Join</h3>
<p dir="ltr">
<ul dir="ltr">
<li>
<div>Complexity: O(N+M)</div>
</li>
<li>
<div>Both inputs are sorted on the join key</div>
</li>
<li>
<div>An equality operator is used</div>
</li>
<li>
<div>Excellent for very large tables</div>
</li>
</ul>
<h3 dir="ltr">Hash Match</h3>
<p dir="ltr">
<ul dir="ltr">
<li>
<div>Complexity: O(N*h<sub>c</sub>+M*h<sub>m</sub>+J)</div>
</li>
<li>
<div>Last-resort join type</div>
</li>
<li>
<div>Uses a hash table and a dynamic hash match function to match rows</div>
</li>
</ul>
<h2 dir="ltr">Resources</h2>
<p dir="ltr">The following resources were used for the making of this post:</p>
<p dir="ltr">
<ul dir="ltr">
<li>
<div><strong><a href="http://www.simple-talk.com/books/sql-books/inside-the-sql-server-query-optimizer/" target="_blank">Inside the SQL Server Query Optimizer</a></strong> by Benjamin Nevarez</div>
</li>
<li>
<div><strong><a href="http://www.sqlservercentral.com/articles/books/65831/" target="_blank">SQL Server Execution Plans</a></strong> by Grant Fritchey</div>
</li>
<li>
<div><strong><a href="http://msdn.microsoft.com/en-us/library/ms191426.aspx" target="_blank">Advanced Query Tuning Concepts</a> </strong>at Microsoft's SQL Server Books Online</div>
</li>
<li>
<div><a href="http://blogs.msdn.com/b/craigfr/archive/2006/08/10/687630.aspx" target="_blank"><strong>Blog post about Hash Joins</strong></a> by Craig Freedman</div>
</li>
</ul>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/loop-hash-and-merge-join-types/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8235;Collations vs. Performance&#8236;</title>		<link>http://www.madeira.co.il/collations-vs-performance/</link>
		<comments>http://www.madeira.co.il/collations-vs-performance/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 14:19:51 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[Hebrew_CI_AS]]></category>
		<category><![CDATA[Latin1_General_CI_AS]]></category>
		<category><![CDATA[SQL Collations Performance ANSI Windows Binary]]></category>
		<category><![CDATA[SQL_Latin1_General_CP1_CI_AS]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=2459</guid>
		<description><![CDATA[&#8235;During a real-world scenario, I found out that SQL Collations and Windows Collations affect performance a lot more than I thought was possible.&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/2459.png&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<p style="direction: ltr;">Recently I've stumbled upon an apparently little known fact about SQL Server &#8211; specifically SQL Server collations and how they affect performance.</p>
<p style="direction: ltr;">During a normalization upgrade to their database, one of my clients had weird and inconsistent performance problems and couldn't find a solution for it for quite a while.</p>
<p style="direction: ltr;">They had two queries:</p>
<ol>
<li style="direction: ltr;">The Original (Un-Normalized) Query: Scanned 2.5 million rows and executed for 3 seconds.</li>
<li style="direction: ltr;">The New (Normalized) Query: Scanned 10 million similar rows and executed for 50 seconds.</li>
</ol>
<p style="direction: ltr;">Each query was executed against a different table, but the data in the tables was identical (the difference was due to the normalization). The column we searched against was varchar(255) in both tables.</p>
<p style="direction: ltr;">For a while we couldn't wrap our heads around the reason for the huge difference in performance.</p>
<p style="direction: ltr;">Something just didn't seem right.</p>
<p style="direction: ltr;">During my investigation I noticed an intriguing difference in the execution plans, and that is in the first query (the fast one) an implicit conversion was performed for the varchar column, but no such conversion occurred in the slow query. At first I didn't pay attention to it because, as a DBA, I was trained to think that implicit or explicit conversions HURT performance, and not the other way around &#8211; so this couldn't have been the reason.</p>
<p style="direction: ltr;">But eventually (and with a little push from Shy Engelberg – Thank you Shy!) I took a closer look to find out why this conversion was happening in the first place.</p>
<p style="direction: ltr;">We found that the collation of the varchar column was different between the two tables.</p>
<p style="direction: ltr;">The first table had a Latin SQL collation, yet the second table had an ANSI collation (or windows collation if you prefer to call it that).</p>
<p style="direction: ltr;">We tried to change the collation of the second table to the SQL collation as well &#8211; and presto! The query now executed for 5 seconds &#8211; 10 times faster! (and only 2 times slower than the 3 second query, a lot more logical difference)</p>
<p style="direction: ltr;">I looked for materials regarding this issue, and couldn't find much except this (apparently important) white paper:</p>
<p style="direction: ltr;"><span style="color: #0000ff;"><a href="http://support.microsoft.com/kb/322112"><span style="color: #0000ff;">http://support.microsoft.com/kb/322112</span></a></span></p>
<p style="direction: ltr;">The highlight:</p>
<p style="direction: ltr;"><em>Unicode sorting rules are much more complex than the rules for a non-Unicode SQL sort order. When SQL Server compares Unicode data, the characters are assigned a weight that is dynamically modified based on the collation's locale. The data is also modified by comparison style settings such as width, accent, or Kana-sensitivity. The Unicode sort routines support more intelligent sort behaviors like word sorting.</em></p>
<p style="direction: ltr;">[…]</p>
<p style="direction: ltr;"><em>•        If you are storing and handling your data by using non-Unicode data types (char, varchar, text), and you are<strong> using a SQL collation, string comparisons will be performed with a non-Unicode SQL sort order</strong>.</em></p>
<p style="direction: ltr;"><em>•        If you are storing and handling your data by using non-Unicode data types (char, varchar, text), and you are <strong>using a Windows collation, string comparisons will be performed with the Unicode sorting rules</strong>. This may cause certain operations that are unusually dependent on string sorting performance to take longer and to use more CPU than a similar operation that is performed with a SQL collation.</em></p>
<p style="direction: ltr;"><em>•        If you are using Unicode data types (nchar, nvarchar, ntext), there is no difference in the sorting behavior for the SQL and the Windows collations. Both will use Unicode sorting rules.</em></p>
<p style="direction: ltr;">In short, windows collations perform as slow as Unicode data types, and SQL collations perform much faster.</p>
<div style="direction: ltr;">However, the sorting order must be taken into consideration because it could change the results.</div>
<div style="direction: ltr;">Though in the case of this client, the first table was the original way to go anyway, so we're actually &quot;fixing&quot; the sorting order difference (in case such existed).</div>
<p style="direction: ltr;">Later we also tested the performance of a binary collation and saw that it was even faster in queries that required comparison and grouping, but it performed worse in queries that required sorting. This makes sense since binary collations must be parsed textually before being sorted &#8211; a heavier operation than doing the same for SQL collations – as opposed to a comparison operation which can be as fast as doing XOR of two values.</p>
<p style="direction: ltr;"><strong><span style="text-decoration: underline;">Conclusion</span></strong></p>
<p style="direction: ltr;">SQL or Windows Collations seem like another consideration we need to take when designing a database and checking for performance &#8211; but beware! Changing the collation may change the sorting order of your text, so if your application depends on a certain form of sorting &#8211; you need to make sure the new collation matches it.</p>
<p style="direction: ltr;">The same white paper mentioned above claims that changing indexes or how a query is written will make a bigger difference than changing collations, but it's surprising what a huge difference in performance a collation caused in the case of my client, and we did try to rewrite the query several times and changing indexes, but nothing made a big difference such as the collation.</p>
<p style="direction: ltr;">Did you encounter a similar scenario? Did you have similar (or even more interestingly – different) results? Tell us about it in the comments!</p>
<p style="direction: ltr;">Thanks again to<span style="color: #0000ff;"> <a href="http://www.madeira.co.il/author/shy/" target="_blank"><span style="color: #0000ff;">Shy Engelberg</span></a></span> for his very helpful advice on this one.</p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/collations-vs-performance/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>&#8235;Efficiently UPDATE and DELETE using TOP and ORDER BY&#8236;</title>		<link>http://www.madeira.co.il/efficiently-update-and-delete-using-top-and-order-by/</link>
		<comments>http://www.madeira.co.il/efficiently-update-and-delete-using-top-and-order-by/#comments</comments>
		<pubDate>Mon, 04 Apr 2011 07:39:12 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[DELETE]]></category>
		<category><![CDATA[ORDER BY]]></category>
		<category><![CDATA[SUBQUERIES]]></category>
		<category><![CDATA[TOP]]></category>
		<category><![CDATA[UPDATE]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=1801</guid>
		<description><![CDATA[&#8235;Find out how to avoid self-joins and bad performance when executing DML statements on a limited number of rows based on specific ordering&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/1801.jpg&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<p dir="ltr">Since SQL Server 2005, Microsoft added the nice addition to the common DML statements UPDATE and DELETE by allowing the use of the TOP keyword. Unfortunately for many of us, SQL Server doesn't support the use of this keyword in conjunction with the ORDER BY clause. So when we do need to update or delete the top x rows in a table based on a specific order, we're bound to use all kinds of workarounds.</p>
<p dir="ltr">However, many of the commonly used workarounds are not very efficient as they can be.</p>
<p dir="ltr">Here's an example of a common method to update the top x rows in a table based on a specific order:</p>
<pre dir="ltr"><span style="color: #0000ff;">UPDATE </span>MyTable <span style="color: #0000ff;">SET </span>Col1 = Whatever
<span style="color: #0000ff;">WHERE </span>ID <span style="color: #808080;">IN </span>(<span style="color: #0000ff;">SELECT </span><span style="color: #0000ff;">TOP </span>(100) ID <span style="color: #0000ff;">FROM </span>MyTable <span style="color: #0000ff;">ORDER BY</span> Col2 <span style="color: #0000ff;">DESC</span>)</pre>
<p dir="ltr">As you can see, this method uses a subquery to get the list of unique IDs of the top 100 rows that we want to update. The problem with this method is that we're accessing the table <strong>twice</strong> and performing a JOIN between the two sets of data (even though we didn't explicitly write &quot;JOIN&quot; in the statement, that's what SQL Server does in the background).</p>
<p dir="ltr">There are actually several variations to this method. Here's another example:</p>
<pre dir="ltr"><span style="color: #0000ff;">UPDATE </span>MyTable <span style="color: #0000ff;">SET </span>Col1 <span style="color: #808080;">=</span> Whatever
<span style="color: #0000ff;">FROM</span>
MyTable
<span style="color: #808080;">JOIN</span>
<span style="color: #808080;">(</span><span style="color: #0000ff;">SELECT </span><span style="color: #0000ff;">TOP </span><span style="color: #808080;">(</span>100<span style="color: #808080;">)</span> ID <span style="color: #0000ff;">FROM </span>MyTable <span style="color: #0000ff;">ORDER BY</span> Col2 <span style="color: #0000ff;">DESC</span><span style="color: #808080;">)</span> <span style="color: #0000ff;">AS </span>ToDelete
<span style="color: #0000ff;">ON</span>
MyTable.ID = ToDelete.ID</pre>
<p dir="ltr">This is an explicit JOIN statement with a subquery. This practically results in the same execution plan as the previous method, except that it allows the use of composite primary keys in the JOIN condition.</p>
<p dir="ltr">Another method is to do the same by first putting the results of the subquery in a <strong>temporary table</strong> and then doing the UPDATE by joining with that temporary table, but that would result in even worse performance due to the extra overhead.</p>
<p dir="ltr">Another method is to use the <strong>SET ROWCOUNT</strong> statement which would limit any statement to affect a specific maximum number of rows. However, this method is not recommended because unlike the TOP keyword, SQL Server doesn't take it into consideration when building the execution plan – which could result in an execution plan optimized for many rows of data even though we put a small number in SET ROWCOUNT.</p>
<p dir="ltr">All of the above is relevant to DELETE statements as well.</p>
<p dir="ltr"><strong><span style="text-decoration: underline;">So, what's the best way to do this?</span></strong></p>
<p dir="ltr">I found that the best way to execute a DML statement on a limited number of rows based on specific ordering is actually <strong>by updating the subquery itself</strong>. This ability in SQL Server is not trivial to all DBAs, which is a shame. Here's an example of what I mean:</p>
<pre dir="ltr"><span style="color: #0000ff;">UPDATE </span><strong><span style="text-decoration: underline;">TheSubQuery</span></strong> <span style="color: #0000ff;">SET </span>Col1 = Col1 + Col3
<span style="color: #0000ff;">FROM </span><span style="color: #808080;">(</span>
<span style="color: #0000ff;">SELECT TOP</span><span style="color: #808080;">(</span>100<span style="color: #808080;">)</span> Col1, Col3
<span style="color: #0000ff;">FROM </span>MyTable
<span style="color: #0000ff;">ORDER BY</span> Col2 <span style="color: #0000ff;">DESC</span>
<span style="color: #808080;">)</span> <span style="color: #0000ff;">AS </span><strong><span style="text-decoration: underline;">TheSubQuery</span></strong></pre>
<p dir="ltr">Note that I need to select in the subquery all the columns used outside the subquery (such as Col1 and Col3). All the data that you're using outside the subquery must be available (so, suppose you perform a JOIN with another table, the columns used in the join must also be queried in the sub query).</p>
<p dir="ltr">Notice how I'm accessing the table only once (you can see it in the execution plan), and obviously not doing any self-joins as a result of that.</p>
<p dir="ltr">This method works similarly using CTE:</p>
<pre dir="ltr"><span style="color: #0000ff;">WITH </span>TheCTEQuery
<span style="color: #0000ff;">AS</span>
<span style="color: #808080;">(</span>
<span style="color: #0000ff;">SELECT TOP</span>(100) Col1, Col3
<span style="color: #0000ff;">FROM </span>MyTable
<span style="color: #0000ff;">ORDER BY</span> Col2 <span style="color: #0000ff;">DESC</span>
)
<span style="color: #0000ff;">UPDATE </span>TheCTEQuery <span style="color: #0000ff;">SET </span>Col1 = Col1 + Col3
<span style="color: #0000ff;">FROM </span>TheCTEQuery</pre>
<p dir="ltr">And even by creating a VIEW instead of the subquery, and updating that view:</p>
<pre dir="ltr"><span style="color: #0000ff;">CREATE VIEW</span> MyView
<span style="color: #0000ff;">AS</span>
<span style="color: #0000ff;">SELECT TOP</span>(100) Col1, Col3
<span style="color: #0000ff;">FROM</span> MyTable
<span style="color: #0000ff;">ORDER BY</span> Col2 <span style="color: #0000ff;">DESC</span>
<span style="color: #0000ff;">GO</span>
<span style="color: #0000ff;">UPDATE</span> MyView <span style="color: #0000ff;">SET</span> Col1 = Col1 + Col3
<span style="color: #0000ff;">FROM </span>MyView</pre>
<p dir="ltr">The result and performance of all three methods are practically the same.</p>
<p dir="ltr">Again, all of the above is relevant to DELETE statements as well.</p>
<p dir="ltr"><strong><span style="text-decoration: underline;">Conclusion</span></strong></p>
<p dir="ltr">It is indeed a shame that Microsoft added the TOP keyword to DML statements but castrated it this much, since the combination of TOP and ORDER BY seems quite trivial. So until this ability will be built-in, I hope you can make good use of the above workarounds that I've showed you.</p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/efficiently-update-and-delete-using-top-and-order-by/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8235;Remove the IDENTITY property from an existing column&#8236;</title>		<link>http://www.madeira.co.il/remove-the-identity-property-from-an-existing-column-using-t-sql/</link>
		<comments>http://www.madeira.co.il/remove-the-identity-property-from-an-existing-column-using-t-sql/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 12:19:09 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[ALTER TABLE]]></category>
		<category><![CDATA[IDENTITY]]></category>
		<category><![CDATA[Partitioning]]></category>
		<category><![CDATA[SWITCH TO]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[פתרונות יעילים]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=1768</guid>
		<description><![CDATA[&#8235;Presenting a rarely known method to quickly and efficiently remove the IDENTITY property from an existing column&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/1768.jpg&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<h2 style="text-align: center;" dir="ltr">How To:<br />
Remove the IDENTITY property from an existing column using T-SQL</h2>
<h4 style="text-align: center;" dir="ltr">(without changing the order of the columns or moving the data into a new table)</h4>
<p dir="ltr">Recently I had a scenario at a client where I needed to remove the IDENTITY property of a column in an existing table. The two common methods to do this were quite problematic and were no good for us:</p>
<p dir="ltr"><strong>1.       </strong><strong><span style="text-decoration: underline;">Move the data into a new table</span></strong></p>
<p dir="ltr">This is the most common method, and it's the one performed behind the scenes when you try to remove the IDENTITY property using SQL Server Management Studio.</p>
<p dir="ltr"><span style="text-decoration: underline;">Algorithm:</span></p>
<ol dir="ltr">
<li>Create an identical new table (excluding the IDENTITY property) with a temporary name.</li>
<li>Copy/move all the data from the old table to the new one.</li>
<li>Rename the tables to replace the old with the new.</li>
</ol>
<p dir="ltr"><span style="text-decoration: underline;">Problem:</span></p>
<p dir="ltr">The main problem with this method is that it's a pain in the a** if your table is huge. It could take hours to move or copy the data between the tables, and it's especially a problem if your table needs to be operational 24/7 (as was the case with my client).</p>
<p dir="ltr"> <strong>2.       </strong><strong><span style="text-decoration: underline;">Add a new column</span></strong></p>
<p dir="ltr">This is the second most common method, and it's the one most commonly found on the internet when looking for solutions to the problem of the previous method.</p>
<p dir="ltr"><span style="text-decoration: underline;">Algorithm:</span></p>
<ol dir="ltr">
<li>Add a new column with a temporary name, with identical properties as the identity column (besides the IDENTITY property of course).</li>
<li>Execute an UPDATE statement to set the value of the new column to the value of the identity column in each row.</li>
<li>Drop the identity column.</li>
<li>Rename the new column to replace the original identity column.</li>
</ol>
<p dir="ltr"><span style="text-decoration: underline;">Problem:<br />
</span>The problem is that the only way to add a new column to a table without recreating the entire table is to the <span style="text-decoration: underline;">end</span> of the column list. This means that if your identity column was first in the columns list, it will be the <span style="text-decoration: underline;">last</span> after the above algorithm is executed. You can't add a new column using ALTER TABLE… ADD … in the middle of the column list.</p>
<p dir="ltr">Most of my client's stored procedures relied on the order of the columns. Then it's easy to see that this method is also out of the question.</p>
<p dir="ltr">Then I came up with a workaround that worked extremely well.</p>
<p dir="ltr"><strong><span style="text-decoration: underline;">The workaround: ALTER TABLE… SWITCH TO…</span></strong></p>
<p dir="ltr">After coming up with this workaround, I was surprised that it's not more commonly used. I tried to look in the internet to see if anyone else came up with this, and found around 2-3 sites and blogs that mention this method. Also, it's practically impossible to find these sites unless you know exactly what to look for.</p>
<p dir="ltr"> <span style="text-decoration: underline;">Algorithm:</span></p>
<p dir="ltr">a.  Create a new table with a temporary name, identical to the original table (excluding the IDENTITY property).<br />
Let's assume the name of our original table is &quot;OriginalTableWithIdentity&quot;, and the name of our new table is &quot;NewTableWithoutIdentity&quot;.</p>
<p dir="ltr">b.  Execute the following command:</p>
<pre dir="ltr"><span style="color: #0000ff;">ALTER TABLE</span> OriginalTableWithIdentity SWITCH <span style="color: #0000ff;">TO</span> NewTableWithoutIdentity</pre>
<p dir="ltr">c.  Rename the tables to replace the old with the new (using sp_rename).</p>
<p dir="ltr"><span style="text-decoration: underline;">Restrictions:</span></p>
<ol dir="ltr">
<li>This method only works in SQL Server 2005 and newer. It won't work in SQL 2000 and older.</li>
<li>The SWITCH TO command has several restrictions (most notably regarding foreign keys and indexes). Please visit here for more information about this command: <a href="http://msdn.microsoft.com/en-us/library/ms191160(v=SQL.90).aspx"><span style="color: #0000ff;">http://msdn.microsoft.com/en-us/library/ms191160(v=SQL.90).aspx</span></a></li>
</ol>
<p dir="ltr">What SWITCH TO does is simply changing the meta data of the partition underlining the table, by changing the ownership on the block of data to another table. There's no data movement or modification involved at all.</p>
<p dir="ltr">Although this command is related to partitions (a feature which is available in Enterprise edition only), the SWITCH TO command actually works in all other editions of SQL Server as well. So even if you have Standard edition it will work just fine (I didn't test it in other editions though, but I think it should work, so let me know if it doesn't).</p>
<p dir="ltr">Using this method, I was able to remove the identity property instantly and efficiently, and without locking the table for more than several milliseconds.</p>
<p dir="ltr">If you have any comments let me know!</p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/remove-the-identity-property-from-an-existing-column-using-t-sql/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>&#8235;נעים מאוד, איתן&#8236;</title>		<link>http://www.madeira.co.il/nice-to-meet/</link>
		<comments>http://www.madeira.co.il/nice-to-meet/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 09:28:55 +0000</pubDate>
		<dc:creator>&#8235;איתן בלומין&#8236;</dc:creator>				<category><![CDATA[בלוגים]]></category>
		<category><![CDATA[מקודמות]]></category>
		<category><![CDATA[להיות DBA]]></category>
		<category><![CDATA[קריירה]]></category>

		<guid isPermaLink="false">http://www.madeira.co.il/?p=1752</guid>
		<description><![CDATA[&#8235;איתן בלומין בפוסט ראשון באתר.  בואו להכיר את האדם מאחורי התשובות בפורום&#8236;]]></description>			<content:encoded><![CDATA[<div dir="rtl"><p><img src='http://www.madeira.co.il/wp-content/plugins/simple-post-thumbnails/timthumb.php?src=/wp-content/thumbnails/1752.jpg&amp;w=214&amp;h=129&amp;zc=1&amp;ft=jpg' alt='post thumbnail' /></p>
<p>אהלן חברים, שמי איתן בלומין.</p>
<p>את דרכי בעולם ההיי-טק התחלתי בתור מתכנת אתרים חובבן עוד בתקופת התיכון.<br />
בעקבות גיוסי לצבא וכניסתי למסלול ממר&quot;ם, זכיתי לרכוש מיומנויות רבות בתחום התכנות (וביניהן גם DB באופן כללי), וחיזקתי את כישוריי בלימוד עצמי.<br />
לעולם בסיסי הנתונים בכלל, ו-SQL Server בפרט, נכנסתי כבר בסיום הקורס כשתקופת השירות שלי התחילה באופן רשמי.<br />
במהלך השירות הצבאי, כולל תקופת קבע של שנתיים וחצי, צברתי כשש שנים של ניסיון מעשי נרחב בעולם ה-SQL Server והשתכשכתי בכל התחומים הקשורים אליו.</p>
<p>ל-Madeira &quot;אותרתי&quot; עוד כשנה לפני השיחרור שלי, והצטרפתי לחברה כמעט מיד אחר כך.<br />
במהלך עבודתי עבדתי עם חברות שונות ברחבי הארץ, נתקלתי בהמון מקרים מעניינים, שעליהם אשמח לכתוב בבלוג בזמן הקרוב (ובעתיד הרחוק).</p>
<p>ניתן למצוא אותי מדי פעם משוטט בפורום הרשמי של SQL Server הישראלי (של MSDN) עונה לשאלות כשאפשר, וכמובן ניתן ליצור איתי קשר אם ברצונכם לשאול שאלות.</p>
<p>נשתמע בקרוב&#8230;</p>
</div>]]></content:encoded>			<wfw:commentRss>http://www.madeira.co.il/nice-to-meet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

