﻿<?xml version="1.0" encoding="utf-8"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><ttl>60</ttl><title>My SQL Server Blog</title><link>http://mysqlserverblog.com</link><lastBuildDate>Wed, 08 Sep 2010 22:24:18 GMT</lastBuildDate><pubDate>Wed, 08 Sep 2010 22:24:18 GMT</pubDate><language>en</language><copyright /><itunes:subtitle> </itunes:subtitle><itunes:author /><itunes:summary /><description /><itunes:owner><itunes:name /><itunes:email>gryphonsclaw@gmail.com</itunes:email></itunes:owner><itunes:explicit>no</itunes:explicit><itunes:category text="Arts" /><item><title>Passing a temp table to a stored procedure</title><link>http://mysqlserverblog.com/2009/07/05/passing-a-temp-table-to-a-stored-proceedure.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>With SQL 2008, table variables can now be passed into stored procedures.&amp;nbsp; Temp tables can also be passed into stored procedures from other stored procedures and triggers.&amp;nbsp; This is true in 2008 and earlier versions like SQL 2005 and 2000.&amp;nbsp;&amp;nbsp; This allows for cleaner code as many lined stored procedures can now be broken up into multiple sub-procedures.&amp;nbsp; &lt;br&gt;&lt;br&gt;A child stored procedure can see its parent's temp table. This child procedure can INSERT, DELETE and UPDATE rows just like a normal temp table.&amp;nbsp; When the child returns to the parent, the data is changed and can be passed into more child stored procedures.&lt;br&gt;&lt;br&gt;Using a temp table and passing it to another procedure, in most cases, will be faster than looping through a result set with a cursor and calling a stored procedure with parameters.&amp;nbsp; &lt;br&gt;&lt;br&gt;An example:&lt;br&gt;&lt;br&gt;&lt;font face="Courier New"&gt;CREATE PROC dbo.udfParent &lt;br&gt;AS&lt;br&gt;BEGIN&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;SELECT 1 AS MyInt,&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;'Hello' AS MyChar&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;INTO #myTemp&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;EXEC dbo.udfChild&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;FROM #myTemp&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;DROP TABLE #myTemp&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;RETURN (0)&lt;br&gt;END&lt;br&gt;&lt;br&gt;GO&lt;br&gt;&lt;br&gt;CREATE PROC dbo.udfChild&lt;br&gt;AS&lt;br&gt;BEGIN&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;FROM #myTemp&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;UPDATE #myTemp&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;SET MyInt = 2&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;RETURN (0)&lt;br&gt;END&lt;br&gt;&lt;br&gt;GO &lt;br&gt;&lt;br&gt;EXEC dbo.udfParent&lt;/font&gt;</description><category>Performance</category><category>Queries</category><comments>http://mysqlserverblog.com/2009/07/05/passing-a-temp-table-to-a-stored-proceedure.aspx#Comments</comments><guid isPermaLink="false">ce3b4403-b012-4df3-a388-8ea406c426c1</guid><pubDate>Mon, 06 Jul 2009 04:31:00 GMT</pubDate></item><item><title>Extending TSQL ROW_NUMBER to Find MAX Rows or Row Deltas</title><link>http://mysqlserverblog.com/2009/02/10/extending-tsql-row_number.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>Some common queries in a database involve grabbing the last value entered into a table for a set of items or comparing a row to its previous row.&amp;nbsp; In the past this involved nasty sub queries one to find the max date and then use that value in outer query.&amp;nbsp;&amp;nbsp;This did not provide the cleanest of code or the&amp;nbsp;best performance.&amp;nbsp; Using the ROW_NUMBER function allows us to simplfy the code and improve performance.&lt;br&gt;&lt;br&gt;Let's make a CTE first off&amp;nbsp;our query to simplify our code:&lt;br&gt;&lt;br&gt;&lt;pre&gt;WITH cteTranLog (Item, LogValue, MaxDateNum, Date)&lt;br&gt;AS &lt;br&gt;(&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;Item,	&amp;nbsp;&amp;nbsp; &lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; LogValue,&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MaxDateNum = ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Date DESC),&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Date&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM dbo.TransactionLog&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE ProcessID = 514	&lt;br&gt;) &lt;/pre&gt;To grab the last values entered in a table:&lt;br&gt;&lt;br&gt;&lt;pre&gt;SELECT Item, LogValue, Date&lt;br&gt;FROM cteTranLog&lt;br&gt;WHERE MaxDateNum = 1  -- we grab the top row only since we are sorted by max date on top&lt;/pre&gt;Notice there is only one table seek or scan.&amp;nbsp; A subquery to grab the max date for each item would involve 2 seeks or scans of the table.&lt;br&gt;&lt;br&gt;The other query involves using row number to look at the current row.&amp;nbsp; This can be handy with running totals or finding deltas between rows. &lt;br&gt;&lt;br&gt;&lt;pre&gt;SELECT cur.Item, cur.LogValue, cur.Date, prev.Date, prev.LogValueFROM cteTranLog cur	&lt;br&gt;INNER JOIN cteTranLog prev ON (prev.MaxDateNum - 1) = cur.MaxDateNum	-- using a -1 because of sort order of desc, dates are descending so 1 is the current making a lesser date 2&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;</description><category>Performance</category><category>Queries</category><comments>http://mysqlserverblog.com/2009/02/10/extending-tsql-row_number.aspx#Comments</comments><guid isPermaLink="false">fa203bd1-1650-445c-b247-66a458e3a2ef</guid><pubDate>Wed, 11 Feb 2009 04:39:00 GMT</pubDate></item><item><title>Searching All Fields in a Database for a Text String</title><link>http://mysqlserverblog.com/2009/01/21/searching-all-fields-in-a-database-for-a-text-string.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>The other day a person in my QA department came to me with a request for a script that searches all fields in a database for a text string.&amp;nbsp; They were unsure where a configuration value was being stored on the system.&amp;nbsp; While you could use SQL Profiler to find this information, I thought writing the script would be fun.&amp;nbsp; &lt;br&gt;&lt;br&gt;Below is the script:&lt;br&gt;&lt;br&gt;&lt;font face="Courier New"&gt;DECLARE @tblTables TABLE (Col varchar(128), Tab varchar(128), Sch varchar(128))&lt;br&gt;DECLARE @Tab varchar(128), @Col varchar(128), @Sch varchar(128), @SearchValue varchar(MAX), @Query varchar(MAX)&lt;br&gt;&lt;br&gt;SET @SearchValue = 'Smith' --set this to the string you wish to find&lt;br&gt;&lt;br&gt;INSERT INTO @tblTables (Col, Tab, Sch)&lt;br&gt;SELECT c.Name AS Col, t.Name AS Tab, s.[Name] AS Sch&lt;br&gt;FROM sys.columns c&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN sys.tables t ON t.[object_id] = c.[object_id]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN sys.types ty ON ty.[user_type_id] = c.[user_type_id]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN sys.schemas s ON s.[schema_id] = t.[schema_id]&lt;br&gt;WHERE t.[type] = 'U'&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AND ty.[name] IN ('varchar','char','nvarchar','nchar')&lt;br&gt;&lt;br&gt;-- use temp table for persistence with executing dynamic sql&lt;br&gt;CREATE TABLE #tblValues (Col varchar(128), Tab varchar(128), Sch varchar(128), ColValue varchar(MAX))&lt;br&gt;&lt;br&gt;WHILE EXISTS (SELECT 1 FROM @tblTables)&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT TOP(1) @Col = Col, @Tab = Tab, @Sch = Sch&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM @tblTables&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @Query =&amp;nbsp;&amp;nbsp;&amp;nbsp; 'INSERT INTO #tblValues (Tab, Col, Sch, ColValue)' + &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ' SELECT ''' + @Tab + ''' AS Tab, ''' + @Col + ''' AS Col, ''' + @Sch + ''' AS Sch, [' + @Col + '] AS ColValue' +&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ' FROM [' + @Sch + '].[' + @Tab + ']' +&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ' WHERE [' + @Col + '] LIKE ''%' + @SearchValue + '%'''&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EXEC (@Query)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DELETE TOP(1) FROM @tblTables&lt;br&gt;END&lt;br&gt;&lt;br&gt;SELECT * FROM #tblValues&lt;br&gt;&lt;br&gt;DROP TABLE #tblValues&lt;br&gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;

</description><category>Queries</category><comments>http://mysqlserverblog.com/2009/01/21/searching-all-fields-in-a-database-for-a-text-string.aspx#Comments</comments><guid isPermaLink="false">1a0c8b80-d08c-417d-9e92-d000b8abbb6c</guid><pubDate>Thu, 22 Jan 2009 06:00:00 GMT</pubDate></item><item><title>RAISERROR Percent % Sign usage</title><link>http://mysqlserverblog.com/2008/01/28/raiserror-percent--sign-usage.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>Have you ever wondered how to build a string with values for an error message?&amp;nbsp; One would think that RASIERROR could simply take a string that was concatenated together with variables.&amp;nbsp; &lt;br&gt;&lt;br&gt;Something like RAISERROR ('My Error' + @myErrorString, 16,1)&lt;br&gt;&lt;br&gt;Unfortunately, RAISERROR is not as intuitive as this.&amp;nbsp; &lt;br&gt;&lt;br&gt;The syntax for RAISERROR is:&lt;br&gt;&lt;br&gt;RAISERROR &lt;b&gt;(&lt;/b&gt;{&lt;i&gt;msg_id&lt;/i&gt; | &lt;i&gt;msg_str&lt;/i&gt;}{&lt;b&gt;,&lt;/b&gt; &lt;i&gt;severity&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;i&gt;state&lt;/i&gt;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;b&gt;,&lt;/b&gt; &lt;i&gt;argument&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/i&gt;[&lt;b&gt;,&lt;/b&gt;...&lt;i&gt;n&lt;/i&gt;]] &lt;b&gt;)&lt;/b&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[WITH &lt;i&gt;option&lt;/i&gt;[&lt;b&gt;,&lt;/b&gt;...&lt;i&gt;n&lt;/i&gt;]]&lt;br&gt;&lt;br&gt;Maybe you have seen the arguments passed into the error message string with percent sign. &lt;br&gt;&lt;br&gt;RAISERROR ('My Error %s', 16,1, @myErrorString)&lt;br&gt;&lt;br&gt;The % sign indicates the use of a parameter.&amp;nbsp; &lt;br&gt;&lt;table cellspacing="0" cols="2" width="420"&gt;&lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td width="28%"&gt;d or i&lt;/td&gt;
&lt;td width="72%"&gt;Signed integer&lt;/td&gt;
&lt;/tr&gt;

&lt;tr valign="top"&gt;
&lt;td width="28%"&gt;o&lt;/td&gt;
&lt;td width="72%"&gt;Unsigned octal&lt;/td&gt;
&lt;/tr&gt;

&lt;tr valign="top"&gt;
&lt;td width="28%"&gt;p&lt;/td&gt;
&lt;td width="72%"&gt;Pointer&lt;/td&gt;
&lt;/tr&gt;

&lt;tr valign="top"&gt;
&lt;td width="28%"&gt;s&lt;/td&gt;
&lt;td width="72%"&gt;String&lt;/td&gt;
&lt;/tr&gt;

&lt;tr valign="top"&gt;
&lt;td width="28%"&gt;u&lt;/td&gt;
&lt;td width="72%"&gt;Unsigned integer&lt;/td&gt;
&lt;/tr&gt;

&lt;tr valign="top"&gt;
&lt;td width="28%"&gt;x or X&lt;/td&gt;
&lt;td width="72%"&gt;Unsigned hexadecimal&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt;To pad some space a number must be placed infront of the type. &lt;br&gt;&lt;br&gt;RAISERROR ('My Error %10s', 16,1, @myErrorString,@myErrorString2)&lt;br&gt;
&lt;br&gt;To justify simply use the + or - sign after the % sign.&amp;nbsp; To pad with a space, use `` (next to the 1 key)&lt;br&gt;&lt;br&gt;If you pass more than one argument then you must use the percent signs in order.&amp;nbsp; &lt;br&gt;&lt;br&gt;RAISERROR ('My Error %10s is not cool %10s', 16,1, @myErrorString,@myErrorString2)&lt;br&gt;</description><category>Queries</category><comments>http://mysqlserverblog.com/2008/01/28/raiserror-percent--sign-usage.aspx#Comments</comments><guid isPermaLink="false">f2dfeecf-9646-4b16-b369-c19ca281cf5d</guid><pubDate>Tue, 29 Jan 2008 05:40:00 GMT</pubDate></item><item><title>Changing Export Options for Reporting Services</title><link>http://mysqlserverblog.com/2008/01/03/changing-export-options-for-reporting-services.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>Have you ever wanted to change the export options for Reporting Services?&amp;nbsp; Have you seen issues with report page headers being exported to Excel as non headers? Other times displaying all export options on the web is not the best idea.&amp;nbsp; An end user trying to figure out what a TIF is can be a more user support time then is desired.&amp;nbsp; In other cases the export might need to be renamed, instead of TIF call it Image.&amp;nbsp; &lt;br&gt;&lt;br&gt;To make these changes, you will have to open up the RSReportServer.config file.&amp;nbsp; It is located in the report directory of SQL server (normally something like C:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer).&amp;nbsp; This is a an XML file that can be opened in Notepad.&amp;nbsp; In the XML file, about half way through it you will see a tag called &amp;lt;RENDER&amp;gt;.&amp;nbsp; To remove options from the drop down export, delete each extension tag that you do not want.&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;lt;Render&amp;gt;&lt;br&gt;... &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;br&gt;&lt;div id="1epl" class="ArwC7c ckChnd"&gt;&lt;wbr&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Extension Name="EXCEL"&amp;nbsp;&amp;nbsp;  Type="Microsoft.ReportingServices.Rendering.ExcelRenderer.ExcelRenderer,Microsoft.ReportingServices.ExcelRendering"&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;OverrideNames&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Name Language="en-US"&amp;gt;EXCEL AMR&amp;lt;/Name&amp;gt;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/OverrideNames&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Configuration&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DeviceInfo&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;RemoveSpace&amp;gt;0.25in&amp;lt;/RemoveSpace&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SimplePageHeaders&amp;gt;true&amp;lt;&lt;wbr&gt;/SimplePageHeaders&amp;gt;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DeviceInfo&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Configuration&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Extension&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Render&amp;gt;&lt;br&gt;&lt;br&gt;To rename the options, add the tag &amp;lt;OverrideNames&amp;gt;&amp;nbsp; then the sub element tag &amp;lt;Name Language="lang"&amp;gt;(New Name)&amp;lt;/Name&amp;gt;&amp;lt;/OverrideNames&amp;gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://images.quickblogcast.com/90812-79275/ssrsmenu.jpg" width="280" border="0"&gt;&lt;br&gt;&lt;br&gt;Other changes can also be configured.&amp;nbsp; In the case above I am removing any blank columns and rows that are 1/4 of an inch or less.&amp;nbsp; I am also forcing simple page headers to ensure that when exporting to Excel the headers are in Excel headers not in the first few rows of the document with a freeze pane.&amp;nbsp; This is a common problem with exporting to Excel with page headers from Reporting Services.&lt;br&gt;&lt;br&gt;&lt;img alt=""&gt;
&lt;/div&gt;To find out more about what tags are available for each option, check out &lt;a href="http://technet.microsoft.com/en-us/library/ms156281%28SQL.100%29.aspx"&gt; MS's Technet page&lt;/a&gt;.&lt;br&gt;</description><category>SQL Server Reporting Services - SSRS</category><comments>http://mysqlserverblog.com/2008/01/03/changing-export-options-for-reporting-services.aspx#Comments</comments><guid isPermaLink="false">455b6360-9cb8-41c2-aa5a-162600afc0bb</guid><pubDate>Fri, 04 Jan 2008 05:36:00 GMT</pubDate></item><item><title>SSRS Fit to Table to Page</title><link>http://mysqlserverblog.com/2007/12/04/ssrs-fit-to-table-to-page.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;Have you ever noticed that if a Total or Sub-Total line floats until to the last page by itself?&amp;nbsp; Worse, table headers do not copy over when only a Sub-Total or Total is all by itself on the last page.&amp;nbsp; To remedy this situation there is a table option that can be set called &lt;span style="font-weight: bold;"&gt;Fit table ton one page if possible&lt;/span&gt;. &lt;br&gt;&lt;br&gt;&lt;img src="http://mysqlserverblog.com/images/90812-79275/fittopage.png" border="0" width="448"&gt;&lt;br&gt;</description><category>SQL Server Reporting Services - SSRS</category><comments>http://mysqlserverblog.com/2007/12/04/ssrs-fit-to-table-to-page.aspx#Comments</comments><guid isPermaLink="false">0993228f-a09c-450a-8435-03bcb6f1c07a</guid><pubDate>Wed, 05 Dec 2007 05:20:00 GMT</pubDate></item><item><title>TSQL ROW_NUMBER Function</title><link>http://mysqlserverblog.com/2007/12/03/tsql-row_number_function.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;A great new feature of SQL Server 2005 is the ROW_NUMBER function.&amp;nbsp; In previous versions of SQL to get a numbered row would pretty much require moving the data into a temp table with an identity column, placing an identity column on the original table, or looping through data with a cursor.&lt;br&gt;&lt;br&gt;SQL Server 2005 makes adding a row number to a query a very simple task with the ROW_NUMBER function.&amp;nbsp; To use this, simply write the query like normal, say Sales Orders by Customer.&amp;nbsp; As one of the columns include the ROW_NUMBER() function with th&lt;span style="font-family: Courier New;"&gt;e &lt;span style="font-family: Verdana;"&gt;OVER clause. &lt;/span&gt;&lt;br style="font-family: Verdana;"&gt;&lt;br&gt;SELECT C.AccountNumber, C.CustomerID, SO.OrderDate,&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROW_NUMBER() OVER (ORDER BY SO.OrderDate) AS OrderNumber&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FROM Sales.Customer C &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INNER JOIN Sales.SalesOrderHeader SO ON C.CustomerID = SO.CustomerID&lt;/span&gt;&lt;br&gt;&lt;br&gt;The ORDER BY clause sorts the data, in this case by the OrderDate. The results will now return a sequential number based on the OrderDate along with the CustomerID, OrderDate, and AccountNumber.&amp;nbsp; &lt;br&gt;&lt;br&gt;Another question that might come up is if we wanted to number each row by customer and then start over at the next customer.&amp;nbsp; To do this, the partition attribute must be used as well.&lt;br&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;SELECT C.AccountNumber, C.CustomerID, SO.OrderDate,&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROW_NUMBER() OVER (PARTITION BY SO.CustomerID ORDER BY SO.OrderDate) AS OrderNumber&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FROM Sales.Customer C &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INNER JOIN Sales.SalesOrderHeader SO ON C.CustomerID = SO.CustomerID&lt;/span&gt;&lt;br&gt;&lt;br&gt;Now the data contains a rownumber (OrderNumber) that resets for each customer.&lt;br&gt;&lt;br&gt;The results of the two queries are seen below:&lt;br&gt;&lt;br&gt;&amp;nbsp; &lt;img src="http://mysqlserverblog.com/images/90812-79275/row_number.gif" border="0" width="439"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;</description><category>Queries</category><comments>http://mysqlserverblog.com/2007/12/03/tsql-row_number_function.aspx#Comments</comments><guid isPermaLink="false">421ad7e6-6f3f-405e-b324-4a614be85b88</guid><pubDate>Tue, 04 Dec 2007 04:42:00 GMT</pubDate></item><item><title>Subreports within table/matrix cells are ignored</title><link>http://mysqlserverblog.com/2007/11/27/subreports-within-tablematrix-cells-are-ignored.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;Unfortunately, subreports within a table or matrix cannot be exported to Excel.&amp;nbsp; I am not sure why MS did not allow this with Reporting Services.&amp;nbsp; This came into play recently when I wanted to make a report that displayed detail data next to the header data.&amp;nbsp; This would be like displaying customer information and then orders and dollars next to the customer's information.&amp;nbsp; I wanted to display the data side by side with a running list of customer information on the left and a listing of orders on the right.&amp;nbsp; Unfortunately, lack of a vertical cell merge forced me into a subreport within a matrix.&amp;nbsp; This is not very efficient but worked.&lt;br&gt;&lt;br&gt;The work around was to change out the table and go with a table of orders inside a list of customers.&amp;nbsp; Unfortunately, the table is easier when modifying 30 rows of data.&amp;nbsp; In a list, each field is a text box not a row and column.&amp;nbsp; Now imagine moving and resizing all of them at once, can someone say Crystal Reports :O(&amp;nbsp; Placing the table next to these text boxes also created interesting issues.&amp;nbsp; When there was multiple orders, the text boxes would slide down on the print preview leaving a gap in the customer information.&amp;nbsp; To remedy this, I had to place the table in a box.&amp;nbsp; I expanded the box to the bottom of the page.&amp;nbsp; &lt;br&gt;&lt;br&gt;The last weird issue I had was how the table is treated in a list box.&amp;nbsp; I wanted to filter the table to only display that customer's orders.&amp;nbsp; Instead of calling my customer dataset for the list and order dataset for the table and filter orders based on customer; I had to make one dataset to return both customer and order information. I grouped the list by customer data, then I had to filter the table that was the same dataset by the customer number.&amp;nbsp; &lt;br&gt;&lt;br&gt;In all, this was a very time consuming and annoying process just to display the data.&amp;nbsp; I am not sure why a table in a table does not work, why there is no vertical cell merge, and why subreports don't export to excel; but I encourage MS to fix these issues.&lt;br&gt;</description><category>SQL Server Reporting Services - SSRS</category><comments>http://mysqlserverblog.com/2007/11/27/subreports-within-tablematrix-cells-are-ignored.aspx#Comments</comments><guid isPermaLink="false">94315eb8-40e9-41f4-aeb1-5e2368f070d1</guid><pubDate>Wed, 28 Nov 2007 02:25:00 GMT</pubDate></item><item><title>SSRS Query Data in Header or Footer Not Exporting to Excel</title><link>http://mysqlserverblog.com/2007/11/16/ssrs-query-data-in-header-or-footer-not-exporting-to-excel.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;One issue that I have noticed with SSRS is that headers and footers do not contain query data that is derived from a hidden text field.&amp;nbsp; &lt;br&gt;&lt;br&gt;The work around is to assign the data to a global parameter that is hidden.&amp;nbsp; Then reference the global parameter in the footer or header.&amp;nbsp; The data will now be available in Excel headers and footers.&amp;nbsp; &lt;br&gt;&lt;br&gt;If you are not seeing a header or footer this is because by default Excel hides the headers and footers.&amp;nbsp; In Excel 2007, click the Insert menu then the Headers &amp;amp; Footers button.&amp;nbsp; In Excel 2003, click the View menu, then Headers &amp;amp; Footers.&amp;nbsp; &lt;br&gt;</description><category>SQL Server Reporting Services - SSRS</category><comments>http://mysqlserverblog.com/2007/11/16/ssrs-query-data-in-header-or-footer-not-exporting-to-excel.aspx#Comments</comments><guid isPermaLink="false">bb4db632-2579-44fe-bd91-610e1f716910</guid><pubDate>Sat, 17 Nov 2007 03:47:00 GMT</pubDate></item><item><title>DELETE Top TSQL Statement</title><link>http://mysqlserverblog.com/2007/11/04/delete-top-tsql-statement.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;A new addition to the DELETE command in SQL Server 2005 is the TOP statement.&amp;nbsp; The DELETE TOP does the same thing as a SELECT TOP WHERE only the TOP number of rows are deleted.&amp;nbsp; &lt;br&gt;&lt;br&gt;This can be very helpful when there are duplicate rows of data present.&amp;nbsp; &lt;br&gt;&lt;br&gt;DELETE TOP (1) &lt;br&gt;FROM Sales.Customer&lt;br&gt;WHERE CustomerID = 1&lt;br&gt;&lt;br&gt;This would delete one of the duplicate rows for Customer number 1&lt;br&gt;&lt;br&gt;Suppose somehow the whole customer table got duplicated.&amp;nbsp; I duplicated the Sales.Customer table into a tmpCustomer table.&lt;br&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;SELECT Top 1 CustomerID, COUNT(CustomerID) AS Cnt&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FROM tmpCustomer &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;GROUP BY CustomerID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;HAVING COUNT(CustomerID) &amp;gt; 1&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;WHILE @@RowCount &amp;gt; 0&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;BEGIN&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DELETE Top (1)&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM tmpCustomer&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE CustomerID = (SELECT Top (1) CustomerID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM tmpCustomer &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; GROUP BY CustomerID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; HAVING COUNT(CustomerID) &amp;gt; 1)&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;END &lt;/span&gt;&lt;br&gt;&lt;br&gt;While this worked just fine, it ran about 4 minutes for 38K rows.&amp;nbsp; Let's try the dreaded CURSOR.&amp;nbsp;&amp;nbsp; Notice I can stick a variable in where the TOP () statement is.&amp;nbsp; I subtracted -1 because we don't want to delete every row.&lt;br&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;DECLARE @cnt int, @custID as int&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;DECLARE dupCursor CURSOR FAST_FORWARD&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FOR SELECT CustomerID, COUNT(CustomerID) AS Cnt&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM tmpCustomer &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GROUP BY CustomerID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HAVING COUNT(CustomerID) &amp;gt; 1&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;OPEN dupCursor &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FETCH NEXT FROM dupCursor &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;INTO @custID, @cnt&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;WHILE @@FETCH_STATUS = 0&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;BEGIN&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DELETE Top (@cnt-1)&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM tmpCustomer&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE CustomerID = @custID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FETCH NEXT FROM dupCursor &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INTO @custID, @cnt&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;END&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;CLOSE dupCursor&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;DEALLOCATE dupCursor&lt;/span&gt;&lt;br&gt;&lt;br&gt;This ran much better at 18 seconds.&lt;br&gt;</description><category>Queries</category><comments>http://mysqlserverblog.com/2007/11/04/delete-top-tsql-statement.aspx#Comments</comments><guid isPermaLink="false">32de0d9c-ad2b-433f-a826-f0433f9186d6</guid><pubDate>Sun, 04 Nov 2007 17:32:00 GMT</pubDate></item><item><title>Writing JOINs vs Nested Select Queries</title><link>http://mysqlserverblog.com/2007/11/01/writing-joins-vs-nested-queries.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;I have seen a lot of is queries written without using the JOIN syntax.&amp;nbsp; Instead the developer chose to write the query using an IN clause in the WHERE clause with a SELECT statement; a Nested Query. While many people blame nested queries on developers that don't understand joins, they can actually be beneficial.&amp;nbsp; Let's take a query out of the AdventureWorks DB.&lt;br&gt;&lt;br&gt;An example would be:&lt;br&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;SELECT Distinct C.AccountNumber&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FROM Sales.Customer C&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INNER JOIN Sales.SalesOrderHeader O ON O.CustomerID = C.CustomerID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INNER JOIN Sales.SalesPerson SP ON SP.SalesPersonID = O.SalesPersonID&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;WHERE SP.CommissionPct &amp;gt;= .015&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br&gt;this can also written as&lt;br&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;SELECT AccountNumber &lt;br&gt;FROM Sales.Customer &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;WHERE CustomerID IN (SELECT CustomerID &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM Sales.SalesOrderHeader &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE SalesPersonID IN (SELECT SalesPersonID &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM Sales.SalesPerson &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE CommissionPct &amp;gt;= .015))&lt;/span&gt;&lt;br&gt;&lt;br&gt;The second query is very messy to read and I personally hate looking at queries like this, but it is faster.&amp;nbsp; To note I have an index on the SalesOrderHeader table with columns SalesPersonID, CustomerID. A distinct has to be used because multiple orders exist for a SalesPerson and Multiple Orders belong to multiple customers.&lt;br&gt;&lt;br&gt;The following are the two execution plans.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;img style="width: 788px; height: 259px;" src="http://mysqlserverblog.com/images/90812-79275/JoinQuery.gif" border="0"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://mysqlserverblog.com/images/90812-79275/nestedQuery.gif" border="0" width="700"&gt;&lt;br&gt;&lt;br&gt;Basically, the point is to not throw out a query because it looks messy.&amp;nbsp; Every query must be analyzed for performance and different approaches should be looked at.&lt;br&gt;</description><category>Queries</category><comments>http://mysqlserverblog.com/2007/11/01/writing-joins-vs-nested-queries.aspx#Comments</comments><guid isPermaLink="false">f08b3358-c8fb-4a42-bf7e-4681ae6ca2c8</guid><pubDate>Fri, 02 Nov 2007 03:51:00 GMT</pubDate></item><item><title>Reseed an Identity Column</title><link>http://mysqlserverblog.com/2007/10/26/reseed-an-identity-column.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;div&gt;&lt;/div&gt;Sometimes identity columns must be reseeded.&amp;nbsp; A good example is when merging data from a couple of different&amp;nbsp; data sources.&amp;nbsp; There is a DBCC command that makes this task easy.&lt;br&gt;&lt;br&gt;&lt;a name="syntaxToggle"&gt;&lt;span style="font-family: Courier New;"&gt;DBCC CHECKIDENT (&amp;lt;table name&amp;gt;, RESEED, &amp;lt;new value&amp;gt&lt;img src="http://mysqlserverblog.com/emoticons/wink.png" border="0" /&gt;&lt;/span&gt;&lt;br&gt;&lt;/a&gt;&lt;br&gt;To find what existing identity column values are, a simple query can be written off the sys.identity_columns system view.&lt;br&gt;&lt;pre style="font-family: Courier New;" class="code" id="ctl00_LibFrame_ctl08other" space="preserve"&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color: black;"&gt;&lt;/span&gt;&lt;/code&gt;SELECT   OBJECT_NAME(object_id) AS [Table],&lt;br&gt;         [name] AS [column],&lt;br&gt;         seed_value,&lt;br&gt;         last_value&lt;br&gt;FROM     sys.identity_columns&lt;br&gt;ORDER BY 1&lt;br&gt;&lt;/pre&gt;&lt;a style="font-family: Courier New;" name="syntaxToggle"&gt;&lt;/a&gt;&lt;br&gt;&lt;a name="syntaxToggle"&gt;&lt;span style="font-family: Verdana;"&gt;&lt;/span&gt;&lt;/a&gt;</description><category>SQL Administration</category><comments>http://mysqlserverblog.com/2007/10/26/reseed-an-identity-column.aspx#Comments</comments><guid isPermaLink="false">63f36b45-75a7-4f9c-8c5c-c2fa8f81ea74</guid><pubDate>Sat, 27 Oct 2007 03:12:00 GMT</pubDate></item><item><title>Selecting a Comma Delimited List with TSQL</title><link>http://mysqlserverblog.com/2007/09/25/selecting-a-comma-delimited-list-with-tsql.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>Sometimes instead of bringing back a table set of information, a query needs to return a comma delimited list.&amp;nbsp; I have seen some crazy stuff to do this like UDFs and Cursors.&amp;nbsp; There is a really simple way to do this in a select statement though. &lt;br&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;--declare a variable first&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;DECLARE @Orders varchar(MAX)&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;--varchar max is nice because there won't be overflow if the table is large&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;SET @Orders = '' --we can't concatenate NULLs so make empty string&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;SELECT @Orders = @Orders + Convert(varchar(10),Orders) + ','&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;FROM dbo.Orders&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;PRINT Left(@Orders,Len(@Orders)-1) --remove last comma&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;/div&gt;</description><category>Queries</category><comments>http://mysqlserverblog.com/2007/09/25/selecting-a-comma-delimited-list-with-tsql.aspx#Comments</comments><guid isPermaLink="false">aa52af8a-6e39-4158-98b7-71f233a81e4b</guid><pubDate>Wed, 26 Sep 2007 01:09:00 GMT</pubDate></item><item><title>Snapshot Transaction</title><link>http://mysqlserverblog.com/2007/09/20/snapshot-transaction.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>A new transaction level included in SQL Server 2005 is the snapshot transaction level.&amp;nbsp; Snapshot transactions allow for data consistency without blocking.&amp;nbsp; A Snapshot transaction fits between a dirty read, Read Uncommitted, and the Read Committed level.&lt;br&gt;&lt;br&gt;Read Committed will only read data that is committed to the database.&amp;nbsp; If a process is in the middle of changing data, then the Read Committed transaction will wait for that update to be complete causing some blocking.&amp;nbsp; A Snapshot transaction will read previously committed data.&amp;nbsp; Therefore it reads a version of the data that was consistent when it was started, but does not cause blocking because it does not wait for data to be updated.&amp;nbsp; &lt;br&gt;&lt;br&gt;Snapshot transactions must be enabled in the database.&amp;nbsp; &lt;a name="sectionToggle0"&gt;The ALLOW_SNAPSHOT_ISOLATION database option must be set to ON for Snapshot transactions to work.&amp;nbsp; Also, if a transaction was started with another level then it cannot be changed to snapshot.&amp;nbsp;&amp;nbsp; You can move from Snapshot to another form though.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/a&gt;&lt;div&gt;&lt;/div&gt;</description><category>Queries</category><comments>http://mysqlserverblog.com/2007/09/20/snapshot-transaction.aspx#Comments</comments><guid isPermaLink="false">cca95d78-7411-462d-9f4c-f29b34a24163</guid><pubDate>Fri, 21 Sep 2007 05:54:00 GMT</pubDate></item><item><title>Formatting SubTotal Columns in an SSRS Matrix View</title><link>http://mysqlserverblog.com/2007/09/15/formatting-subtotal-columns-in-an-ssrs-matrix-view.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>Developers that are new to SSRS might be frustrated with formatting Matrix subtotal columns. Once the data in the Matrix is setup the developer might choose a sub-total for one of the column groups.&amp;nbsp; This makes a gray empty box on the row level which cannot be formatted.&amp;nbsp; Logically, this would be where the formatting would take place.&lt;br&gt;&lt;br&gt;&lt;img src="http://mysqlserverblog.com/images/90812-79275/matrixviewcellformacellst.jpg" border="0" width="253"&gt;&lt;br&gt;&lt;br&gt;One of my first projects with a Matrix report involved adding a double line border above the total
field of a Matrix report.&amp;nbsp; I struggled with this for a bit, then I
realized the green triangle in the corner is for formatting the group. Right clicking this green corner will display its properties in the properties dialog.&amp;nbsp; Clicking on the cell will only bring up the properties for the row group cell (Total in this example).&lt;br&gt;
&lt;div&gt;&lt;/div&gt;</description><category>SQL Server Reporting Services - SSRS</category><comments>http://mysqlserverblog.com/2007/09/15/formatting-subtotal-columns-in-an-ssrs-matrix-view.aspx#Comments</comments><guid isPermaLink="false">ca0b9693-a358-4eff-8918-0990b0c049e2</guid><pubDate>Sat, 15 Sep 2007 18:16:00 GMT</pubDate></item><item><title>SQL Server Dynamic Management Views</title><link>http://mysqlserverblog.com/2007/08/28/sql-server-dynamic-management-views.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>One of the greatest features, and in my opinion the one that makes SQL Server a top tier enterprise database, is dynamic management views.&amp;nbsp; Before SQL Server 2005, lots of time was wasted trying to analyze and solve problems using Profiler, Query Analyzer, PerfMon and other tools.&amp;nbsp; With the introduction of Dynamic Management Views (DMVs) and Dynamic Management Functions (DMFs) , administrators have a place to query recorded data to analyze issues.&amp;nbsp; DMVs provide vital information, such as index usage stats.&amp;nbsp; Since the information is already recorded by the DBMS lot's of time is saved. Also, performance tuning and other management activities can be done proactive.&lt;br&gt;&lt;br&gt;I want to briefly discuss a couple of these views.&lt;br&gt;&lt;br&gt;The&amp;nbsp; sys.dm_exec_requests view is quite useful to show processes running on the database.&amp;nbsp; &lt;br&gt;&lt;br&gt;The
sys.dm_exec_sessions will tell the sessions that are logged in.&amp;nbsp; More
information is contained here than using sp_who2.&amp;nbsp;&amp;nbsp; Join this view with
the sys.dm_exec_requests view and a lot of information will be returned
allowing a DBA to find out who is running what on the server. &lt;br&gt;&lt;br&gt;sys.dm_db_index_usage_stats&amp;nbsp; view will explain how much an index is used.&amp;nbsp; It makes a great place for finding indexes that aren't needed.&amp;nbsp; &lt;br&gt;&lt;br&gt;The missing index views (sys.dm_db_missing_index_details, sys.dm_db_missing_index_group_stats, sys.dm_db_missing_index_groups), can help to identify indexes that are needed on tables.&amp;nbsp;&amp;nbsp; The DBMS logs entries into these views when a table is scanned and an index could have been used. index_group_stats is helpful because it identifies how many times the index could have been used. &lt;br&gt;&lt;br&gt;To find out information relating to cached query plans, look in the sys.dm_exec_cached_plans view.&amp;nbsp;&amp;nbsp; While this won't tell you a lot of meaningful information, the plan handle can be gotten and used with the sys.dm_exec_sql_text and sys.dm_exec_query_plans functions to get the XML showplan and text of the query.&lt;br&gt;&lt;br&gt;If you are using a service broker application the following views are of interest:&lt;br&gt;sys.dm_broker_activated_tasks, sys.dm_broker_connections, sys.dm_broker_activated_tasks, sys.dm_broker_forwarded_messages, sys.dm_broker_queue_monitors.&amp;nbsp; These views can help monitor message volume.&lt;br&gt;&lt;br&gt;What about hardware information relating to the database?&amp;nbsp; The sys.dm_os_wait_stats view will explain the length of time processes had to wait for resources.&amp;nbsp; &lt;br&gt;&lt;br&gt;Another important hardware view is sys.dm_os_performance_counters.&amp;nbsp; I like this view.&amp;nbsp; It is basically all the counters that are pulled in PerfMon for the SQL Server category.&amp;nbsp; While it is better to pull this information in PerfMon, it is easier to manipulate by querying it here.&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;/div&gt;</description><category>Performance</category><category>SQL Administration</category><comments>http://mysqlserverblog.com/2007/08/28/sql-server-dynamic-management-views.aspx#Comments</comments><guid isPermaLink="false">a88a99d8-07aa-4f3a-baa9-323cb3aa0540</guid><pubDate>Wed, 29 Aug 2007 01:43:00 GMT</pubDate></item><item><title>Correlating PerfMon with Profiler</title><link>http://mysqlserverblog.com/2007/08/26/correlating-perfmon-with-profiler.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>System monitor or PerfMon is a tool that most DBAs need to become
familiar with.&amp;nbsp; Many times Profiler will give information regarding to
what is running on the database but can't pinpoint the problem.&amp;nbsp; A new feature of SQL Server 2005 is the ability to correlate Profiler data with PerfMon (System Monitor).&amp;nbsp; &lt;br&gt;&lt;br&gt;To correlate the two logs:&lt;br&gt;&lt;ul&gt;&lt;li&gt;Create a trace log in SQL Server Profiler.&lt;/li&gt;&lt;li&gt;At the same time create a PerfMon log.&amp;nbsp; &lt;br&gt;&lt;/li&gt;&lt;li&gt;Once the Profiler trace is done, stop it. &lt;br&gt;&lt;/li&gt;&lt;li&gt;In Profiler Select File -&amp;gt; Import Performance Data&lt;/li&gt;&lt;li&gt;Select the counters to correlate.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;What is great about this is that performance problems become more apparent.&amp;nbsp; For instance, maybe the average disk queue spikes when a certain query is run.&amp;nbsp; There might be a table scan going on and the solution might be to separate the tables unto different disk arrays.&lt;br&gt;&lt;div&gt;&lt;/div&gt;</description><category>Performance</category><comments>http://mysqlserverblog.com/2007/08/26/correlating-perfmon-with-profiler.aspx#Comments</comments><guid isPermaLink="false">5a9504c6-ed83-4dcf-9291-dc592c21d75b</guid><pubDate>Mon, 27 Aug 2007 04:03:00 GMT</pubDate></item><item><title>Partitioning Tables part 2</title><link>http://mysqlserverblog.com/2007/08/22/partitioning-tables-part-2.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>A few days ago, I explained how to partition a table in SQL Server 2005.&amp;nbsp; I also mentioned how moving data is very fast when using partitions.&amp;nbsp; This is because you can swap partitions to other tables without having to move data.&amp;nbsp; All that happens is a pointer to the data is changed.&amp;nbsp; This makes a file partition move great for archiving data.&lt;br&gt;&lt;br&gt;For instance, say that we have two invoice tables, one that should contain the last two years of current invoices and an archival invoice data table.&amp;nbsp; Each year is partitioned into its own filegroup.&amp;nbsp; Suppose that our production table has the year 2005 in it. This has to be moved over to our archive table.&amp;nbsp; On the archival data table we have to make a partition to contain 2005.&amp;nbsp; &lt;br&gt;&lt;br&gt;First, we need to add a filegroup for the data to be put into.&lt;br&gt;&lt;br&gt;ALTER PARTITION SCHEME myscheme&lt;br&gt;NEXT USED [filearch2005]&lt;br&gt;&lt;br&gt;To add a partition, we must split them.&amp;nbsp; Therefore, let's use the following function:&lt;br&gt;&lt;br&gt;ALTER PARTITION FUNCTION mypartfunc ()&lt;br&gt;SPLIT ('1/1/2005')&lt;br&gt;&lt;br&gt;Now everything after 2005 is in its own partition and we just need to SWITCH from our Invoice table to our InvoiceArch table.&lt;br&gt;&lt;br&gt;ALTER TABLE dbo.Invoice&lt;br&gt;SWITCH PARTITION 1 TO dbo.InvoiceArch PARTITION 5&lt;br&gt;&lt;br&gt;After the PARTITION word we need to specify the number of the partition.&amp;nbsp; Now we have moved all the 2005 data from Invoice table to the InvoiceArch table in no time without locks. &lt;br&gt;&lt;div&gt;&lt;/div&gt;</description><category>Performance</category><comments>http://mysqlserverblog.com/2007/08/22/partitioning-tables-part-2.aspx#Comments</comments><guid isPermaLink="false">a34de6a8-c0ac-41f7-93d2-2ec5f455b2d1</guid><pubDate>Thu, 23 Aug 2007 01:55:00 GMT</pubDate></item><item><title>Partitioning Tables</title><link>http://mysqlserverblog.com/2007/08/20/partitioning-tables.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>SQL Server 2005 introduced a new feature to improve performance for accessing tables.&amp;nbsp; This feature is the ability to partition a table across many disk arrays.&amp;nbsp; In SQL Server 2000 a table can be placed into a file group, but there is not a way to divide up a table.&amp;nbsp; A DBA could make an indexed view that combines multiple tables via a UNION.&amp;nbsp; Each of those tables could then be put in a file group.&amp;nbsp; This takes a lot of work maintaining the code and tables.&amp;nbsp; Partitioning the data also allows for data to be moved from table to table with minimal overhead.&lt;br&gt;&lt;br&gt;To partition a table a Partition Function must be created first.&amp;nbsp; To create this use the following command.&amp;nbsp; &lt;br&gt;&lt;font face="Courier New"&gt;&lt;br&gt;CREATE PARTITION FUNCTION mypartfunc (datetime) AS&lt;br&gt;RANGE RIGHT FOR VALUES ('1/1/2005','1/1/2006','1/1/2007')&lt;/font&gt;&lt;br&gt;&lt;br&gt;Mypartfunc is the name of the function where datetime is of course the data type to divide on.&amp;nbsp; The last piece is range or the values that the data is split on.&amp;nbsp; Everything before 1/1/2005 is in the first file partition, 1/1/2005 - 12/31/2006 is the second, 1/1/2006 - 12/31/2006 is in a third file group and everything 1/1/2007 and greater is in the last file group. RANGE RIGHT means that the boundary point is included in the file group to the right.&lt;br&gt;&lt;br&gt;Once a function is created, a scheme must then be created.&amp;nbsp;&amp;nbsp; A function could be used for many different schemes; therefore, a function is really the business logic.&amp;nbsp; The scheme will tie the function to actual file groups.&amp;nbsp; These file groups can be place on separate disk arrays.&lt;br&gt;&lt;br&gt;&lt;font face="Courier New"&gt;CREATE PARTITION SCHEME myscheme AS &lt;br&gt;PARTITION mypartfunc TO&lt;br&gt;(filegroup1, filegroup2, filegroup3, filegroup4)&lt;br&gt;&lt;/font&gt;&lt;br&gt;Myscheme is the name of the scheme and the file groups are defined. &lt;br&gt;&lt;br&gt;So there is a function and a scheme.&amp;nbsp; The last piece of the puzzle is to tie these to a table or index.&amp;nbsp; You can easily do this with a CREATE TABLE or INDEX statement.&lt;br&gt;&lt;font face="Courier New"&gt;&lt;br&gt;CREATE TABLE myTable (mydate datetime, othervalue varchar(10))&lt;br&gt;ON myscheme(mydate)&lt;/font&gt;&lt;br&gt;&lt;br&gt;Myscheme is the scheme that was defined, where there the value of the scheme is the column in the table to partition on.&lt;br&gt;&lt;br&gt;In my next blog, I will discuss how using partitions can really increase performance in copying tables.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;/div&gt;</description><category>Performance</category><comments>http://mysqlserverblog.com/2007/08/20/partitioning-tables.aspx#Comments</comments><guid isPermaLink="false">6be1ccdd-04ee-4188-9a8a-c3a8047e1ef9</guid><pubDate>Tue, 21 Aug 2007 02:18:00 GMT</pubDate></item><item><title>Technorati</title><link>http://mysqlserverblog.com/2007/08/14/technorati.aspx?ref=rss</link><dc:creator>Adam Rink</dc:creator><description>&lt;a href="http://technorati.com/claim/cskrranshs" rel="me"&gt;Technorati Profile&lt;/a&gt;</description><category>Blogging Stuff</category><comments>http://mysqlserverblog.com/2007/08/14/technorati.aspx#Comments</comments><guid isPermaLink="false">361d9780-73cf-4d27-902b-c1e200806485</guid><pubDate>Wed, 15 Aug 2007 04:20:00 GMT</pubDate></item></channel></rss>