<?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>All Free Tech &#187; SQL Server</title>
	<atom:link href="http://www.allfreetech.com/tag/sql-server/feed" rel="self" type="application/rss+xml" />
	<link>http://www.allfreetech.com</link>
	<description>For developers</description>
	<lastBuildDate>Tue, 01 Feb 2011 13:45:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Working with the Report Builder in Microsoft SQL Server 2008: Part 2</title>
		<link>http://www.allfreetech.com/database/sql-server/working-with-the-report-builder-in-microsoft-sql-server-2008-part-2-32.html</link>
		<comments>http://www.allfreetech.com/database/sql-server/working-with-the-report-builder-in-microsoft-sql-server-2008-part-2-32.html#comments</comments>
		<pubDate>Sat, 23 Jan 2010 02:44:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[report builder]]></category>

		<guid isPermaLink="false">http://www.allfreetech.com/?p=32</guid>
		<description><![CDATA[In the previous part of the article, we had a look at the Report Builder overview and described the Report Builder 2.0 interface. In this part by Jayaram Krishnaswamy, we will discuss about Enabling and reviewing My Reports, and will see how to Modify a basic report. Enabling and reviewing My Reports As described in [...]]]></description>
			<content:encoded><![CDATA[<p>In the previous part of the article, we had a look at the <a href="http://www.packtpub.com/article/report-builder-in-microsoft-sql-server-2008-part1?utm_source=sl_sqlserver08_abr2_0409&amp;utm_medium=content&amp;utm_campaign=sanjiv" target="_blank">Report Builder overview and described the Report Builder 2.0 interface</a>. In this part by <b>Jayaram Krishnaswamy</b>, we will discuss about Enabling and reviewing My Reports, and will see how to Modify a basic report. <span id="more-32"></span></p>
<h2>Enabling and reviewing My Reports</h2>
<p>As described in Part 1 the My Reports folder needs to be enabled in order to use the folder or display it in the Open Report dialogue. The RC0 version had a documentation bug which has been rectified (<a href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=366413" target="_blank">https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=366413</a>)</p>
<h1>Getting ready</h1>
<p>In order to enable the My Reports folder you need to carry out a few tasks. This will require authentication and working with the SQL Server Management Studio. These tasks are listed here:</p>
<p>The <b>Server Properties</b> window is displayed with a navigation list on the left consisting of the following:</p>
<p>In the <b>General</b> page the <i>name, version, edition, authentication mode,</i> and <i>URL</i> of Reporting Service is displayed. Download of an <b>ActiveX Client Print</b> control is enabled by default. In order to work with Report Builder effectively and provide a <b>My Reports</b> folder for each user, you need to place a check mark for the check box <b>Enable a My Reports folder for each user</b>. The <b>My Reports</b> feature has been turned on as shown in the next screenshot.</p>
<p>In the <b>Execution</b> page there is choice for report timeout execution, with the default set such that the report execution expires after 1800 seconds.</p>
<p>In the <b>History</b> page there is choice between keeping an unlimited number of snapshots in the report history (default) or to limit the copies allowing you to specify how many to be kept.</p>
<p>In the <b>Logging</b> page, report execution logging is enabled and the log entries older than 60 days are removed by default. This can be changed if desired.</p>
<p>In the <b>Security</b> page, both Windows integrated security for report data sources and ad hoc report executions are enabled by default.</p>
<p>The <b>Advanced</b> page shows several more items including the ones described thus far as shown in the next figure.</p>
<p>The <b>Advanced</b> page is displayed as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image1.png" /></p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image2.png" /></p>
<p>The description of everything that a user with the assignment <b>My Reports</b> role can do is as follows:</p>
<p><i>May publish reports and linked reports, manage folders, reports, and resources in a users My Reports folder.</i></p>
<p>Report Builder 2.0 is displayed.</p>
<p>The <b>Open Report</b> dialogue appears as shown. When the report Server is offline, the default location is <b>My Documents</b>, like Microsoft products Excel and MS Access.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image3.png" /></p>
<p>The Report server that is active should get displayed here as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image4.png" /></p>
<p>All the folders and files on the server become accessible as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image5.png" /></p>
<p>Verify that a <b>My Reports</b> folder is created for the user (current user).</p>
<ol>
<li>Make sure the Report Server has started.</li>
<li>Make sure you have adequate permissions to access the Servers.</li>
<li>Open the <b>Microsoft SQL Server Management Studio</b> as described previously.</li>
<li>Connect to the Reporting Services after making sure you have started the Reporting Services.</li>
<li>Right-click the <b>Report Server</b> node.
<ul>
<li><b>General</b></li>
<li><b>Execution</b></li>
<li><b>History</b></li>
<li><b>Logging</b></li>
<li><b>Security</b></li>
<li><b>Advanced</b></li>
</ul>
</li>
<li>In the <b>General</b> page enable the <b>My Reports</b> feature by placing a check mark.</li>
<li>Click on the <b>Advanced</b> list item in the left.</li>
<li>Now expand the <b>Security</b> node of <b>Reporting Services</b> and you will see that the <b>My Reports</b> role is present in the list of roles as shown. This is also added to the ReportServer database.</li>
<li>Now bring up Report Builder 2.0 by clicking <b>Start | All Programs | Microsoft SQL Server 2008 Report Builder | Report Builder 2.0</b>.</li>
<li>Click on <b>Office Button | Open</b>.</li>
<li>Choose the <b>Recent sites and Servers</b>.</li>
<li>Highlight the Server URL and click <b>Open</b>.</li>
<li>Open the Report Manager by providing its URL address.</li>
</ol>
<p style="margin-left: 40px; margin-right: 40px;"><em>There could be slight differences in the look of the interface depending on whether you are using the RTM or the final version of SQL Server 2008 Enterprise edition.</em></p>
<hr color="#ff9933" noshade="noshade" size="1" />
<p>&nbsp;</p>
<div class="header">Learning SQL Server 2008 Reporting Services</div>
<div style="line-height: 0.4em;">&nbsp;</div>
<table cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td valign="top" width="99"><a href="http://www.packtpub.com/learning-sql-server-2008-reporting-services/book/sl/sqlserver08-abr2/0409?utm_source=sl_sqlserver08_abr2_0409&amp;utm_medium=content&amp;utm_campaign=sanjiv"><img alt="Learning SQL Server 2008 Reporting Services" border="0" class="left" height="123" src="http://images.packtpub.com/images/100x123/1847196187.png" title="Learning SQL Server 2008 Reporting Services" width="99" /></a></td>
<td valign="top">A step-by-step guide to getting the most of Microsoft SQL Server Reporting Services 2008 &nbsp;</p>
<ul>
<li>Everything you need to create and deliver data-rich reports with SQL Server 2008 Reporting Services as quickly as possible</li>
<li>Packed with hands-on-examples to learn and improve your skills</li>
<li>Connect and report from databases, spreadsheets, XML Data, and more</li>
<li>No experience of SQL Server Reporting Services required</li>
</ul>
<p>				<a href="http://www.packtpub.com/learning-sql-server-2008-reporting-services/book/sl/sqlserver08-abr2/0409?utm_source=sl_sqlserver08_abr2_0409&amp;utm_medium=content&amp;utm_campaign=sanjiv">http://www.packtpub.com/learning-sql-server-2008-reporting-services/book</a></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<hr color="#ff9933" noshade="noshade" size="1" />
<p>
	&nbsp;</p>
<h2>Modifying a basic report</h2>
<p>In this exercise, the report created will be modified to illustrate the formatting, layout, and other capabilities built into the Report Builder.</p>
<h1>Getting ready</h1>
<p>This hands-on will be using a MS Access report that was imported using Visual Studio and hosted on the Report Server. The MS Access report will be modified to use the new Report Items in Report Builder 2.0.</p>
<h1>Follow the steps</h1>
<p>You will be carrying out the following steps:</p>
<ol>
<li>Open Report Builder and open the <b>ByOrders.rdl</b> report.</li>
<li>Review the imported MS Access report.</li>
<li>Modify the properties.</li>
</ol>
<h3>Open Report Builder and open the ByOrders.rdl report</h3>
<p>You will be accessing the ByOrders.rdl file from the Report Builder in order to modify it in the Report Builder. The steps are listed here:</p>
<p>The <b>ByOrders</b> report gets displayed in the Report Builder as shown:</p>
<ol>
<li>Start Report Builder from its shortcut.</li>
<li>Click the <b>Office</b> button and in the drop-down window click on <b>Open</b>. The <b>Open</b> dialogue is displayed.</li>
<li>Click on <b>Recent Sites and Servers</b> in the left navigation area. The Report Servers&#39; URL is displayed.</li>
<li>Highlight the Report Server URL and click on the <b>Open</b> button.</li>
<li>Click on the MS Access folder and click on the <b>Open</b> button.</li>
<li>Highlight the report <b>ByOrders</b> and click on the <b>Open</b> button.</li>
</ol>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image6.png" /></p>
<h3>Review the imported MS Access report</h3>
<p>The dataset for the report is <b>DataSet1</b> on the left and the report body is in the design area. The various report items and their data binding will be examined for one such control, the <b>CompanyName</b>. It will be instructive to study the others as well. In order to review the report we will follow these steps:</p>
<p>The properties of <b>CompanyName</b> are displayed as shown. <b>CompanyName</b> is inside a container textbox inside the Tablix and it is a place holder. You should also notice the large square bracket on the left ranging three rows. This is the grouping symbol.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image7.png" /></p>
<p>This opens the <b>Placeholder&#39;s Properties</b> page as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image8.png" /></p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image9.png" /></p>
<p>You have added the HTML tags <em>&lt;u&gt;</em> and <em>&lt;/u&gt;</em> on either side of the original <b>CompanyName</b> data that came from the dataset. Now it is slightly more than the data and in the design view (CompanyName) it is replaced by this expression. A placeholder is the holding place of an expression. You can make a textbox into a placeholder by designating the textbox to hold an expression. For example there are two place holders for the time <i>Now ()</i> and the <i>expression =&quot;Page&quot; &amp; Globals.PageNumber &amp; &quot; of &quot;&amp; Globals.TotalPages</i>.</p>
<p>The report gets processed and you may need to provide the login for this report. The username is <b>Admin</b> and there is no <b>password</b>.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image10.png" /></p>
<p>The report is displayed in the Report Builder as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image11.png" /></p>
<p>The <b>Address</b> field is highlighted in the report as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image12.png" /></p>
<p>You can see that this represents the detail (the data that comes in each of the rows). It is also a placeholder and its value is that of &quot;Address&quot;. You can apply Rich Text formatting by using HTML tags for textboxes as well as place-holder values.</p>
<p>Note that only certain HTML tags and CSS attributes are supported. For the supported HTML tags refer to <a href="http://msdn.microsoft.com/en-us/library/dd207048.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/dd207048.aspx</a>. For an example of CSS rendering, refer to <a href="http://hodentek.blogspot.com/2009/01/can-you-use-css-style-attributes-in.html" target="_blank">http://hodentek.blogspot.com/2009/01/can-you-use-css-style-attributes-in.html</a>.</p>
<p>Both vertical and horizontal movements of objects can be very smooth and can be changed in <b>Points</b> as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image13.png" /></p>
<ol>
<li>Highlight <b>CompanyName</b> and right&ndash;click on it.</li>
<li>Click on <b>Placeholder Properties&hellip;</b>.</li>
<li>Change the <b>Markup</b> type to <b>HTML &ndash; Interpret HTML tags as styles</b>.</li>
<li>Click on the <b><i>fx</i></b> symbol (which opens an <b>Expression</b> window) along&nbsp; the <b>Value</b>.</li>
<li>In the <b>Expression</b> window that is displayed, modify the expression as shown in the following screenshot:</li>
<li>Click on the <b>OK</b> button on the <b>Expression</b> window as well as the <b>Placeholder Properties&#39;</b> window.</li>
<li>Click on the <b>Run</b> button in the <b>Home</b> menu.</li>
<li>Click on the <b>View Report</b> button.</li>
<li>Click on the <b>Address</b> field in the report design.</li>
<li>Change Report title <b>ByOrders</b> to <b>Orders</b> by editing the textbox.</li>
<li>Extend the length of the &lt;&lt;Expr&gt;&gt; directly below the report title to accommodate a longer string.</li>
<li>Make the <b>EmployeeID</b> feld left aligned as well as formatted. Set the font weight <b>Bold</b>.</li>
<li>Click on the table that has the <b>Address, City</b>, and so on. Extend it to the right by dragging the table handles so that the <b>Required Date</b> can be fully displayed.</li>
<li>Rearrange the positions of objects and the size of textboxes to fully display the data.</li>
</ol>
<p>Highlighted objects can be expanded and moved using the <i>Ctrl</i> or <i>Shift</i> keys together with the arrow keys.</p>
<p>The modified report design is shown in the following screenshot:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article2-image14.png" /></p>
<p>
	&nbsp;</p>
<h2>Summary</h2>
<p>The Report Builder 2.0 tool is described in full, starting from the top to the bottom of this interface. Creating reports with this tool is described using an existing report and modifying it as well as creating a new report from data. Embedding charts and gauges are also described. Some of the interactive and rich text features are&nbsp; also discussed.</p>
<p>Report Builder 1.0 is briefly mentioned but its utility for reports models created using VS 2008 or BIDS did not warrant an example due to current limitations. It may be possible to use this tool with Report Models created with an earlier version of SQL Server. One of the main features of Report Builder 2.0 is its ability to create Ad Hoc reports. The reader may notice slight differences in the look of the interfaces slightly at variance depending on the version of the SQL Server 2008 and Report Builder 2.0 used.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.allfreetech.com/database/sql-server/working-with-the-report-builder-in-microsoft-sql-server-2008-part-2-32.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Working with the Report Builder in Microsoft SQL Server 2008: Part 1</title>
		<link>http://www.allfreetech.com/database/sql-server/working-with-the-report-builder-in-microsoft-sql-server-2008-part-1-30.html</link>
		<comments>http://www.allfreetech.com/database/sql-server/working-with-the-report-builder-in-microsoft-sql-server-2008-part-1-30.html#comments</comments>
		<pubDate>Sat, 23 Jan 2010 02:43:25 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[report builder]]></category>

		<guid isPermaLink="false">http://www.allfreetech.com/?p=30</guid>
		<description><![CDATA[Report Builder 2.0 is feature-rich reporting tool with the latest Microsoft Office look and feel. In this two part article by Jayaram Krishnaswamy, we will see how the Report Builder 2.0 provides an extremely flexible GUI with user friendly wizards for creating the Tablix data regions, a versatile construct that includes tables, matrix, and charts [...]]]></description>
			<content:encoded><![CDATA[<p>Report Builder 2.0 is feature-rich reporting tool with the latest Microsoft Office look and feel. In this two part article by <strong>Jayaram Krishnaswamy</strong>, we will see how the Report Builder 2.0 provides an extremely flexible GUI with user friendly wizards for creating the Tablix data regions, a versatile construct that includes tables, matrix, and charts and gauges. Report Builder 2.0 supports server resources such as shared Data Sources, works with SQL Server Data Sources and many third party products, and can directly open and edit server hosted reports. Report Builder together with Report Manager provides powerful support for building and managing a bewildering array of report types.<span id="more-30"></span></p>
<p>The Microsoft SQL Server 2008 Reporting Services Report Builder 2.0 tool can be installed from a standalone installer available at this Microsoft site, <a href="http://download.microsoft.com/download/a/f/6/af64f194-8b7e-4118-b040-4c515a7dbc46/ReportBuilder.msi" target="_blank">http://download.microsoft.com/download/a/f/6/af64f194-8b7e-4118-b040-4c515a7dbc46/ReportBuilder.msi</a>. The same file is also available from a collection of download files when you access the Microsoft SQL Server 2008 Feature Pack, October 2008 at <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=228DE03F-3B5A-428A-923F-58A033D316E1&amp;displaylang=en" target="_blank">http://www.microsoft.com/downloads/details.aspx?FamilyId=228DE03F-3B5A-428A-923F-58A033D316E1&amp;displaylang=en</a>.</p>
<h2>Report Builder overview</h2>
<p>In the present version of SQL Server 2008 [Enterprise Evaluation edition] there&nbsp; are two Report Builders available. Report Builder 1.0, which has remained as a program that can be launched from the Report Manager, and the new Report Builder 2.0, which is a stand alone report authoring tool that needs to be independently launched.</p>
<p>Although Report Builder 1.0 can access Report Models built with Visual Studio 2008 and the Report Manager, it cannot be used to create reports using those models. It also does not work with Reports generated by Visual Studio 2008/BIDS/Report Builder 2.0. The errors can be summarized as follows:</p>
<p><i>Specifying credentials in a URL is not supported</i></p>
<p><i>System.IO.StreamReader: The Report element was not found</i></p>
<p><i>MemoryStream length must be non-negative and less than 2^31-1-origin. Parameter name: offset; Remote GDI stream version: ?. Expected version: 11.0.1</i></p>
<ul>
<li>When you try to access the Report Server 2008 from the link provided on the Report Builder 1.0 interface you get the following error message:</li>
<li>When you try to open a report created using VS2008/BIDS/ReportBuilder2.0 using the <b>Open Report&hellip;</b> and <b>Open File&hellip;</b> navigational items in Report Builder 1.0 you get the following error message:</li>
<li>Report Builder 1.0 allows you to access Report Models created with VS2008/BIDS/Report Manager and even allows you create a report in design view but this report cannot be processed on the Report Server. If you try to do so, you get the following error message:</li>
</ul>
<p>In this article the Report Builder 2.0 interface will be described along with the new features that are incorporated into this version. Report Builder 2.0 is admirably suited to address all items in the Report Definition Language of 2008.</p>
<p>One of the important features of Report Builder 2.0 is the empowerment it provides business users to create ad hoc reports using the Report Models built on the databases they use.</p>
<p>In this article you will be learning mostly about the Report Builder 2.0&nbsp; interface details and working with it to create reports or modify them. It may be noted that Report Builder generates 2008 compliant RDL files as described in <a href="http://download.microsoft.com/download/6/5/7/6575f1c8-4607-48d2-941d-c69622e11c32/RDL_spec_08.pdf" target="_blank">http://download.microsoft.com/download/6/5/7/6575f1c8-4607-48d2-941d-c69622e11c32/RDL_spec_08.pdf</a> and therefore, cannot work with reports generated using 2005 technology.</p>
<h2>Report Builder 2.0 user interface description</h2>
<p>Report Builder is a report authoring tool and the basic procedure for authoring a report consists of the following steps:</p>
<ul>
<li>Report planning</li>
<li>Connecting to a source of data</li>
<li>Extracting a dataset from source</li>
<li>Designing the report and data binding</li>
<li>Previewing the report</li>
</ul>
<p>Although deploying the report is not included in the above, Report Builder can deploy the report as well. It is not always necessary to deploy a completed report, as any part of a report definition file can be deployed. This makes modifying a report on the server very flexible.</p>
<p>In the following sections, the various parts of the Report Builder interface will be described starting at the very top and going to the bottom of the interface</p>
<h1>The menu for file operations</h1>
<p>Report Builder 2.0 can be accessed from <b>Start | All Programs | Microsoft SQL Server 2008 Report Builder | Report Builder 2.0</b>.</p>
<p>This brings up the Report Builder Interface 2.0 as shown with the design area containing two icons: <b>Table</b> or <b>Matrix</b> and <b>Chart</b>. Each of these will launch a&nbsp; related wizard which will step you through the various tasks. The Report Builder 2.0 interface is very similar to Office 2007. More than one instance of Report Builder can be launched.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image1.png" /></p>
<p>At the very top of the following screen shown you have the <i>undo</i> and <i>redo</i> controls as well as a <i>save</i> icon.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image2.png" /></p>
<p>When you click on the save icon the <b>Save as Report</b> window gets displayed as shown. Here you provide a name for the report. The default save extension is&nbsp; <i>*.rdl</i> and it will be saved to the report server. It may also be persisted to a folder on your machine.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image3.png" /></p>
<p>Clicking on the <b>Office Button</b> (top left) opens a drop-down window shown in the following screenshot:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image4.png" /></p>
<p>In this window, you can carry out a number of tasks such as creating a new report, opening an existing report, saving a report, and saving a report with a different name.</p>
<p>The <b>Save</b> button saves it to the default location seen earlier and <b>Save as</b> invokes the same window to save the report with a different name as seen earlier displying the report server instance as the <b>Save to</b> location.</p>
<p>The <b>Recent Documents</b> pane shows the more recent reports created with this tool. <b>New</b> allows you to create a new report. When you click on <b>Open</b>, the following <b>Open Report</b> window gets displayed with the default location <i>http://Hodentek2:8080/ReportServer_SANGAM/My Reports</i>. You will also notice the message: This folder is not available because the My Reports feature is not enabled on the computer. Also the <b>Open Reports</b> window allows you look for reports with the extension <i>.rdl</i>.</p>
<p>Therefore, unless the <b>My Reports</b> feature is enabled, this window is unusable. This is supposed to be possible from Report Manager but there are no controls in Report Manager that would do this. An alternative was suggested by one of the MSDN forum moderators (see <a href="http://social.msdn.microsoft.com/forums/en-US/sqlreportingservices/thread/6c695160-29e8-4185-be6d-5fe027a6975c/" target="_blank">http://social.msdn.microsoft.com/forums/en-US/sqlreportingservices/thread/6c695160-29e8-4185-be6d-5fe027a6975c/</a>). <i>Hands-on exercise</i> (Part 2) will describe how you may enable My Reports. The idea of My Reports is similar to <b>My Documents</b> where each user can keep his reports.</p>
<p>When the <b>Options</b> button (in the previous screenshot) is clicked it opens the window <b>Report Builder Options</b> window with two tabbed pages <b>Settings</b> and <b>Resource</b> shown as follows:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image5.png" /></p>
<p>Here you can view, as well as modify, Report Builder settings. The defaults are more than adequate to work with the examples in this book.</p>
<p>Clicking on the <b>Resources</b> button brings up this interesting window which enables you to interact with Microsoft regarding SSRS activities, concerns, community, and so on. If you are serious about Reporting Services, these are very valuable links. The <b>About</b> button when clicked can provide you with Report Builder version information.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image6.png" /></p>
<h1>The ribbon</h1>
<p>The main menu consists of <b>Home, Insert,</b> and <b>View</b> menu items which are part of the &quot;ribbon&quot;. The ribbon introduced by Microsoft in Office 2007 is actually a container for other toolbar items. The ribbon is the replacement for the classic menus, toolbars, and is supposed to be more efficient and discoverable by the user. In fact you see a lot more on the &quot;ribbon&quot; than in the classic menu.</p>
<h3>Home</h3>
<p>The next figure shows the <b>Home</b> menu with its toolbar arranged from left to right and divided into sections. The <b>Run</b> toolbar item with the title <b>Views</b> when clicked would run the report open in the design view (in fact, even without a report open in the design view, the report can be run. The result would be the current date and time getting displayed in the center of the screen of an untitled report which has just ExecutionTime as the only item in the report).</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image7.png" /></p>
<p>The <b>Font, Paragraph, Border,</b> and <b>Number</b> toolbar sections become enabled if parts of a report need editing. The formatting of textboxes in the report, the formatting of numbers in the report, and the alignment of components in the layout can all be independently managed using these toolbar items.</p>
<h3>Insert</h3>
<p>When you click on the <b>Insert</b> menu item on the &quot;ribbon&quot;, the tabbed page for this item is displayed as shown in the following screenshot:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image8.png" /></p>
<p>It has four sections: <b>Data Regions, Report Items, Subreports,</b> and <b>Header &amp; Footer</b>. These are all the normal items that are used either individually or together to make up a report. There can be more than one data region in a report.</p>
<hr color="#ff9933" noshade="noshade" size="1" />
<p>&nbsp;</p>
<div class="header">Learning SQL Server 2008 Reporting Services</div>
<div style="line-height: 0.4em;">&nbsp;</div>
<table cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td valign="top" width="99"><a href="http://www.packtpub.com/learning-sql-server-2008-reporting-services/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"><img alt="Learning SQL Server 2008 Reporting Services" border="0" class="left" height="123" src="http://images.packtpub.com/images/100x123/1847196187.png" title="Learning SQL Server 2008 Reporting Services" width="99" /></a></td>
<td valign="top">A step-by-step guide to getting the most of Microsoft SQL Server Reporting Services 2008 &nbsp;</p>
<ul>
<li>Everything you need to create and deliver data-rich reports with SQL Server 2008 Reporting Services as quickly as possible</li>
<li>Packed with hands-on-examples to learn and improve your skills</li>
<li>Connect and report from databases, spreadsheets, XML Data, and more</li>
<li>No experience of SQL Server Reporting Services required</li>
</ul>
<p>				<a href="http://www.packtpub.com/learning-sql-server-2008-reporting-services/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv">http://www.packtpub.com/learning-sql-server-2008-reporting-services/book</a></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<hr color="#ff9933" noshade="noshade" size="1" />
<h3>Data Regions</h3>
<p>In the Data Regions section you have both the Tablix (<b>Table, Matrix,</b> and <b>List</b>) and the graphic controls that can be bound to data&mdash;the <b>Chart</b> and the <b>Gauge</b>. <b>Gauge</b> is new in SQL Server Reporting Services 2008. Chart and gauge implementations are the off shoot of collaboration with Dundas (<a href="http://www.dundas.com/" target="_blank">http://www.dundas.com/</a>). Report Builder is built in such a way that the dataset must be defined before any of the data regions are added to the report body. For the purpose of describing the various data regions in this section, it is assumed (in order to get the screen shots shown here) that a dataset has been defined and the default wizards on the design surface have been removed.</p>
<h4>Table</h4>
<p>The Table is meant for displaying data retrieved from a database either all data detailed in groups or a combination (some grouped and some detailed) of both. It has a fixed number of columns which can be adjusted at design time. The table length expands to accommodate the rows.</p>
<p>Data can be grouped by a single field or by multiple fields. Expression designer can be used in grouping as well. The grouping is carried out by creating row groups. Static rows can be added for row headings (labels) and totals. Aggregates for groups can be added. Both detailed data as well as grouped data can be hidden initially and the user can interactively reveal the data needed by drill downs.</p>
<p>When you click on <b>Insert | Table | Insert Table</b> and then click on the design surface you can add a table to the design area. The table appears as shown with handles to adjust its dimensions. The table can be dragged to any other location on the design surface (the body of the report) as well.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image9.png" /></p>
<p>After placing the table, which by default has three columns and two rows, when you click on any other part of the design area you will see the table as shown. When you hover over the cell marked <b>Data</b> on the table you will see a little icon. This icon is a minimized version of the dataset fields. The grayed out feature that surrounds the table indicate the position of the rows and columns of the table. It also shows such other features as whether it is a detail, or whether it is a group. In the case of group, within a group the feature would indicate the nesting schematically as well. When you want to increase the size of a column or a row you can drag the double headed arrow that gets displayed when your cursor is placed between two columns or between two cells as shown.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image10.png" /></p>
<p>When you click on the dataset icon in the cell <b>Data</b> you get a drop-down list containing the fields in the dataset as shown. You can choose any of the fields to occupy the cell you clicked and the corresponding header will be added to the table. In this particular dataset there are nine fields and you can choose any of them to occupy the cell.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image11.png" /></p>
<p>When you right-click on a cell, a drop-down menu will be available. It can be used for the following:</p>
<ul>
<li>Work with the highlighted textbox (each cell of the table is a textbox) including to copy, cut, delete, and paste contents.</li>
<li>Work with the properties of the Textbox.</li>
<li>Populate the textbox with an expression using the expression builder. The expression builder gets displayed when <b><i>fx</i> Expression</b> is clicked.</li>
<li>Use <b>Select</b> to select the body or the Tablix.</li>
<li>Insert a new column or a new row. Columns can be added to the right or the left of the clicked cell and rows can be added above or below the clicked cell.</li>
<li>Delete columns and rows.</li>
<li>Add a group. Both row and column groups can be added.</li>
</ul>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image12.png" /></p>
<p>When you click on the properties of the textbox, the <b>Text Box Properties</b> window is displayed. The textbox has several properties which are arranged on the left as a list with each item having its own page as shown. The <b>Help</b> button on any of the pages will take you directly to the definition of the properties and is extremely useful.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image13.png" /></p>
<p>In the <b>General</b> page, you can make changes to the elements in the <b>Name, Value,</b> and <b>Sizing options</b> page as shown. The <b>Value</b> is one which you choose among the column values (from the drop-down) from the dataset. You may also add a text for the <b>ToolTip</b>, which will display this text when the report is generated and this cell is accessed by hovering over it in the report. Alternatively you can set the <b>Value</b> and <b>Tooltip</b> using <b><i>fx</i></b>&mdash;the button that brings up the <b>Expression</b> window.</p>
<p>In the <b>Number</b> page you can set the number and date data type formatting options for the cell that contains a number or a date. This is what you normally would find in most Microsoft products such as Excel and Access.</p>
<p>In the <b>Alignment</b> page you can choose the vertical and horizontal alignments as well as the padding of the textbox content from the edges of the cell.</p>
<p>Similarly the <b>Font</b> and <b>Border</b> properties are the same ones you find in most Microsoft products.</p>
<p>The <b>Fill</b> property lets you add or change background color to the report as well as add a graphic element. The graphic element can be <b>embedded, external,</b> or originate from a <b>database</b> (being one of the fields accessed). Expressions can be developed to set a desired color for the <b>Fill</b>.</p>
<p>The <b>Visibility</b> of the textbox can be any of <b>Show, Hide, Show or Hide based on an expression</b>. In each of these cases the visibility can be toggled when another table cell is clicked (which can be chosen). This page also gives access to the <b>Expression</b> window which is similar to the MS Access expression builder.</p>
<p>The <b>Interactive Sorting</b> page allows you to define interactive sorting options on&nbsp; the textbox.</p>
<h4>Matrix</h4>
<p>Matrix provides a similar functionality (roughly speaking rows against columns) to cross-tab reports in MS Access (<a href="http://aspalliance.com/1041_Creating_a_Crosstab_Report_in_Visual_Studio_2005_Using_Crystal_Reports.all" target="_blank">http://aspalliance.com/1041_Creating_a_Crosstab_Report_in_Visual_Studio_2005_Using_Crystal_Reports.all</a>) and Pivot Table dynamic views (<a href="http://www.aspfree.com/c/a/MS-SQL-Server/On-Accessing-Data-From-An-OLAP-Server-Using-MS-Excel/3/" target="_blank">http://www.aspfree.com/c/a/MS-SQL-Server/On-Accessing-Data-From-An-OLAP-Server-Using-MS-Excel/3/</a>). The matrix should have at least one row group and one column group. The matrix can expand both ways to accommodate the data, horizontally for column groups and vertically for row groups. The matrix cells (intersection of rows and columns) display summary information (aggregates).</p>
<p>When you click on <b>Insert Matrix</b> in the <b>Insert</b> menu and drop it on the design area of Report Builder 2.0, it gets displayed as shown in the following figure:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image14.png" /></p>
<p>Now if you click inside the boundary of the (2&#215;2) empty matrix you will see more features of the matrix as shown in the following screenshot. The basic elements are the <b>ColumnGroup</b> (Column Groups), the <b>RowGroup</b> (Row Groups), and the <b>Data</b>. The group information is also displayed as shown by overlaid lines pointing to them. There needs to be a minimum of one group and one column for the matrix and there could be a hierarchy of column and row groups.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image15.png" /></p>
<p>The row and column group cells have their own properties which can be displayed when you right-click on them as shown in the next screenshot for the row group. When you right-click on the cell marked <b>Rows</b>, the following drop-down menu&nbsp; pops up.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image16.png" /></p>
<p>In addition to the properties that you can set for the textbox in that cell, you have additional submenu items that work with the grouping and totaling. These are part of representing data in a matrix.</p>
<p>Each of the Tablix for the <b>Rows</b> and <b>Columns</b> has the additional submenu items which are shown here for the <b>Rows</b>. Similar ones apply for the <b>Columns</b> as well. These are useful when you want to create nested groups. With the Matrix design interface in SQL Server 2005 this would not have been possible.</p>
<p>Add Group</p>
<ul>
<li>Row Group
<ul>
<li>Parent Group&#8230;</li>
<li>Child Group&#8230;</li>
<li>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</li>
<li>Adjacent Above</li>
<li>Adjacent Below</li>
</ul>
</li>
</ul>
<p>Row Group</p>
<ul>
<li>Delete Group</li>
<li>Group Properties</li>
</ul>
<p>Add Total</p>
<ul>
<li>Before</li>
<li>After</li>
</ul>
<p>In addition to the above, each of the items <b>Rows</b> and <b>Columns</b> cells has the following items as well. These specify how new columns and rows are inserted with reference to the current cell as shown. The differences are due to the geometrical positions that are allowed for the new columns or rows as shown.</p>
<p>For the &quot;Columns&quot; cell:</p>
<p>Insert Column</p>
<ul>
<li>Inside Group-Left</li>
<li>Inside Group-Right</li>
<li>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</li>
<li>Outside Group-Left</li>
<li>Outside Group-Right</li>
</ul>
<p>Insert Row</p>
<ul>
<li>Inside Group-Above</li>
<li>Inside Group-Below</li>
<li>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</li>
<li>Outside Group_Above</li>
</ul>
<p>For the &quot;Rows&quot; cell:</p>
<p>Insert Column</p>
<ul>
<li>Inside Group-Left</li>
<li>Inside Group-Right</li>
<li>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</li>
<li>Outside Group-Left</li>
</ul>
<p>Insert Row</p>
<ul>
<li>Inside Group-Above</li>
<li>Inside Group-Below</li>
<li>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</li>
<li>Outside Group_Above</li>
<li>Outside Group_Below</li>
</ul>
<p>Besides using a cell as a starting point, one could also use the rows as a whole or column as a whole to add further structure as shown in the next figure. Of course you need to use the proper submenu option to arrive at a particular matrix structure. Clicking at the indicated points would let you choose the structure you want for your matrix. If you click at the location shown for the Tablix you could choose to the delete the whole matrix. The Tablix graphical arrangement gives you the maximum flexibility in extending the matrix in 2-dimensions.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image17.png" /></p>
<h4>List</h4>
<p>The list data region repeats for each row of data. List element provides a single container for the data which can be used to generate what are called <i>Free Form Reports</i>. In this kind of report there is no rigid structure such as a table for the data. You can also place a list inside another list or even a chart inside a list. You can drag a column from a dataset and drop it into the list. You can work with the list using the properties of the <b>Rectangle</b> it contains as well as its Tablix properties.</p>
<p>As described earlier, the design interface is very flexible and you can leverage all features provided by the Tablix structure like displaying details and adding groups either independent, or nested. The properties pages described earlier allow you to sort and filter grouped data.</p>
<p>When you drop a <b>List</b> on the design surface you will see just a single cell as shown. You can change its dimensions to suit your needs.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image18.png" /></p>
<p>When you click on the List you can access its handles as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image19.png" /></p>
<p>When you add a List, there is one column and one row (just one cell). This can be extended in both directions by choosing the appropriate submenu items. These can be displayed by right-clicking on the handles as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image20.png" /></p>
<p>
	&nbsp;</p>
<hr color="#ff9933" noshade="noshade" size="1" />
<div class="header">Books from Packt</div>
<table border="0" bordercolor="#cc6600" cellpadding="3" id="table42" style="border-collapse: collapse;" width="588">
<tbody>
<tr>
<td valign="top" width="68">
<p align="center"><font face="Verdana" size="1">&nbsp; <a href="http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="C#<br />
2008 and 2005 Threaded Programming: Beginner's Guide" class="style7" height="62" src="http://images.packtpub.com/images/50x61/1847197108.png" style="border: 1px solid rgb(0, 0, 0);" title="C# 2008 and 2005 Threaded Programming: Beginner's Guide" width="50" /></a><br />
					<span lang="en-us"><span class="style1"> <a href="http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <font color="#ff0000">C# 2008 and 2005 Threaded Programming: Beginner&#39;s Guide</font></a></span></span></font></p>
</td>
<td valign="top" width="68">
<p align="center"><a href="http://www.packtpub.com/sql-server-integration-services-visual-studio-2005/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="Beginners Guide to SQL Server Integration Services<br />
Using Visual Studio 2005" border="0" height="61" src="http://images.packtpub.com/images/50x61/1847193315.png" style="border: 1px solid rgb(0, 0, 0);" title="Beginners Guide to SQL Server Integration Services Using Visual<br />
Studio 2005" width="49" /></a><br />
					<a href="http://www.packtpub.com/sql-server-integration-services-visual-studio-2005/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <font color="#ff0000" face="Verdana" size="1">Beginners Guide to SQL Server Integration Services Using Visual Studio 2005</font></a></p>
</td>
<td valign="top" width="68">
<p align="center"><font face="Verdana" size="1"><a href="http://www.packtpub.com/implementing-microsoft-dynamics-nav-2009/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="Implementing Microsoft Dynamics NAV 2009" height="61" src="http://images.packtpub.com/images/50x61/1847195822.png" style="border: 1px solid rgb(0, 0, 0);" title="Implementing Microsoft Dynamics NAV 2009" width="49" /></a><font face="Verdana" size="1"><br />
					<span lang="en-us"> <span class="style1"><font color="#ff0000"> <a href="http://www.packtpub.com/implementing-microsoft-dynamics-nav-2009/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <font color="#ff0000">Implementing Microsoft Dynamics NAV 2009</font></a></font></span></span></font></font></p>
</td>
<td valign="top" width="68">
<p align="center"><font face="Verdana" size="1"><a href="http://www.packtpub.com/asp-net-data-presentation-controls/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="ASP.NET Data<br />
Presentation Controls Essentials" border="0" height="61" src="http://images.packtpub.com/images/50x61/184719530X.png" style="border: 1px solid rgb(0, 0, 0);" title="ASP.NET Data Presentation Controls Essentials" width="50" /></a><br />
					</font> <a href="http://www.packtpub.com/asp-net-data-presentation-controls/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <font color="#ff0000" face="Verdana" size="1">ASP.NET Data Presentation Controls Essentials</font></a></p>
</td>
<td valign="top" width="68">
<p align="center"><a href="http://www.packtpub.com/software-testing-with-visual-studio-team-system-2008/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="Software Testing with Visual Studio Team System 2008" class="style7" height="61" src="http://images.packtpub.com/images/50x61/184719558X.png" style="border: 1px solid rgb(0, 0, 0);" title="Software Testing with Visual Studio Team System 2008" width="49" /></a><br />
					<font color="#ff0000" face="Verdana"> <span class="style9" lang="en-us"> <a href="http://www.packtpub.com/software-testing-with-visual-studio-team-system-2008/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <span class="style1"><font color="#ff0000" size="1">Software Testing with Visual Studio Team System 2008</font></span></a></span></font></p>
</td>
<td valign="top" width="68">
<p align="center"><font face="Verdana" size="1"><a href="http://www.packtpub.com/vsto-3-for-office-2007-programming/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="VSTO 3.0 for Office<br />
2007 Programming " class="style7" height="62" src="http://images.packtpub.com/images/50x61/1847197523.png" style="border: 1px solid rgb(0, 0, 0);" title="VSTO 3.0 for Office 2007 Programming " width="50" /></a><br />
					<span lang="en-us"><span class="style8"> <a href="http://www.packtpub.com/vsto-3-for-office-2007-programming/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <span class="style1"><font color="#ff0000">VSTO 3.0 for Office 2007 Programming </font></span></a></span></span></font></p>
</td>
<td valign="top" width="68">
<p align="center"><a href="http://www.packtpub.com/linq-quick-starter/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="LINQ Quickly" class="style7" height="62" src="http://images.packtpub.com/images/50x61/1847192548.png" style="border: 1px solid rgb(0, 0, 0);" title="LINQ Quickly" width="50" /></a><br />
					<font color="#ff0000" face="Verdana"> <span class="style9" lang="en-us"> <a href="http://www.packtpub.com/linq-quick-starter/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <span class="style1"><font color="#ff0000" size="1">LINQ Quickly</font></span></a></span></font></p>
</td>
<td valign="top" width="68">
<p align="center"><a href="http://www.packtpub.com/soa-patterns-with-biztalk-server-2009/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <img alt="SOA Patterns with<br />
BizTalk Server 2009" height="62" src="http://images.packtpub.com/images/50x61/1847195008.png" style="border: 1px solid rgb(0, 0, 0);" title="SOA Patterns with BizTalk Server 2009" width="50" /></a><br />
					<font color="#ff0000" face="Verdana"> <span class="style9" lang="en-us"> <a href="http://www.packtpub.com/soa-patterns-with-biztalk-server-2009/book/sl/sqlserver08-abr1/0309?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv"> <span class="style1"><font color="#ff0000" size="1">SOA Patterns with BizTalk Server 2009</font></span></a></span></font></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<hr color="#ff9933" noshade="noshade" size="1" />
<h4>Chart</h4>
<p>A picture tells lot more than a bunch of numbers, and charts (graphs) aggregate the whole range of data that is highly informative and aesthetically pleasing. Charts have a myriad of properties, both with regard to how they are linked to data as well as their visual properties that it is hard to justify describing them in an abbreviated fashion.</p>
<p>Charts are basically used while creating a graph from the data to summarize important and relevant information. There are two ways you can work with chart in Report Builder 2.0. The easiest is to use the <b>Chart Wizard</b>. The other way is to start with a chart template and then associate it with a dataset.</p>
<p>There are many chart types such as bar charts, column charts, line charts, pie charts, area charts, polar charts, range charts, scatter charts and so on. The following screenshot schematically shows the various supported chart types. The chart type would depend on the data that it represents. Generally a chart should help visualize the data. A chart has its data region as well, its Tablix properties.</p>
<p>You can insert a chart on the report body by clicking <b>Insert | Chart |Insert Chart</b> and clicking again on the body of the report. This brings up the <b>Select Chart Type</b> window as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image21.png" /></p>
<p>Here you have number of options as shown. For each of these choices you have a number of other options as shown on the right-hand side when you choose the <b>Column</b> type.</p>
<p>Assuming you choose the default (the one highlighted in the above figure) and click on the <b>OK</b> button, the type of chart you chose gets added to the design area of the report as shown. You can increase the size of the chart both ways by dragging the handles.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image22.png" /></p>
<p>When you double-click inside the chart, you see the drop-zones on its three sides as shown. These are the areas into which you can drag-and-drop columns from the Dataset or use the minimized dataset icon that gets displayed when you hover over this area.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image23.png" /></p>
<p>When you right-click on any of these areas, you can access the various ways you can work with the charts as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image24.png" /></p>
<p>The important chart related items are category fields, series fields, and data fields. You can work with all properties of the chart from this drop-down menu and even change the type of chart you want to develop.</p>
<h4>Gauge</h4>
<p>This is new in Reporting Services 2008. Like chart, gauge is also a data region. Gauge has only a single data region unlike a chart. It has the look of any industrial meters (measuring instrument) with a range of values and the indicator showing the present value or some configurable value. They can be used together with both table and matrix elements.</p>
<p>When you add a gauge to a report, it comes up positioned within a gauge panel. The properties of this can be accessed when you click outside the boundary of the gauge. When you want the gauge to display data, you should associate its data property with the dataset. Gauge, like chart also has a myriad of properties which can be accessed from its <b>Properties</b> window.</p>
<p>In <i>Hands-on exercise</i>, (Part 2) you will be adding a radial gauge to display the data and a <b>linear</b> gauge to display an average.</p>
<h3>Report Items</h3>
<p>Textbox, image, line, and rectangle are the items you find in the <b>Report Items</b> section of <b>Insert</b>. You will be using textbox and image both of which may be bound to related as well as unrelated database variables. In the case of textbox, you have an option to use a static text, a field from the built-in fields, or connected to one of the fields from the dataset. A table added to a report has textboxes in its cells, but you can add a textbox outside the table and bind it to an aggregate value related to&nbsp; the dataset.</p>
<p>Similar to the textbox, an image added to the report can be embedded, originate from an external source; or being one of the dataset fields. An image can be added to the current report by right-clicking the <b>Images</b> folder in <b>Report Builder</b> and picking an image from your hard drive which can then be simply embedded in the report using the <b>Image</b> report item. This way you can add a logo to your report.</p>
<p>A line cannot be bound to the dataset. Its purpose is purely to provide support as a graphic separator element. The rectangle is also used to improve the visible appeal. However, it can contain other items, even data regions. You can control the rendering behaviour of items placed inside a rectangle (parent control) for the controls placed inside the rectangle. The rectangle will be an anchor for the items placed within it and move when the rectangle is moved in the report design.</p>
<p>When the line or the rectangle is used inside data regions you may use their <b>RepeatWith</b> property to allow them to be rendered when the report gets displayed.</p>
<h3>Subreports</h3>
<p>A subreport is a child of a main report. The main report is a container for the subreport(s). The <b>Subreport</b> section in the <b>Insert</b> menu item of the &quot;ribbon&quot; allows you to add a subreport. The parent report and the subreport are stored usually in the same folder on the report server. The main report can be designed to pass parameters to the subreport. The parameter then filters the subreport for it to be displayed in a data region of the main report.</p>
<p>Subreports can be separated from main data region of the main report or they can be placed within the data region of the main report. A report can contain more than one subreport.</p>
<p>As described above, the subreport may be placed inside the main report several ways as shown in the following screenshot:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image25.PNG" /></p>
<h3>Header and footer</h3>
<p>A report page can contain a header and footer. In Report Builder 2.0 there is page footer by default which contains the built-in parameter <i>ExecutionTime</i>.</p>
<p>Some of the common features of page headers and footers are the following:</p>
<ul>
<li>Headers go at the top of the page and footers go to the bottom and they repeat on each page of the report.</li>
<li>They both can contain static text, images, lines and rectangles, borders, expressions (lookup the properties of these in Report Builder 2.0).The expressions can include field references for reports from the dataset.</li>
<li>You can easily add headers and footers from the <b>Insert</b> menu item in the &quot;ribbon&quot;. You can just, as easily, remove them by right-clicking the item and choose to remove the item.</li>
<li>The most common use of headers and footers is to display page numbers, report titles, and so on. There are number of built-in fields such as <b>Page Number, Execution Time, Report Name, Total Pages</b> and so on, which can be dragged-and-dropped on to headers and footers.</li>
<li>To display variable data from a dataset in headers and footers you place a textbox and set the value for the textbox using an expression. Choose the appropriate field from the dataset. In a similar manner you can display aggregate values from the expression builder. For data from multiple datasets you cannot reference the fields, rather you should reference the objects in the report.</li>
<li>You can suppress these on the first and last pages of a report using the <i>PrintOnFirstPage, PrintOnLastPage</i> properties which can be accessed from their properties.</li>
<li>Report headers and footer are not the same as the page headers and footers.</li>
<li>Reports that you see with a browser are rendered by the HTML renderer, but the report can be delivered in different formats. Each of them has their own renderer and you should optimize the report for the format you want to deliver.</li>
</ul>
<h3>View</h3>
<p>The <b>View</b> menu has very few items as shown:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image26.png" /></p>
<p><b>Report Data</b> and <b>Grouping</b> are checked by default. If you want to review or make changes to the properties of objects you place on the report, you should frst place a checkmark for the <b>Properties</b>. Otherwise you will see only the <b>Properties</b> pop-up window that comes up when you right-click an object to look at its properties.</p>
<p>Place checkmark for the <b>Rulers</b> if you want to design measured placement of objects on the report. The rulers become visible when you move around or adjust object sizes.</p>
<h1>Report Data, the Report Designer, and the properties</h1>
<p>These are the items that you will find just below the &quot;ribbon&quot; assuming you have not disabled <b>Report Data</b> and <b>Properties</b> (these are enabled by default) as shown in the following screenshot. The properties will be that of the object highlighted in the report body.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image27.png" /></p>
<h3>Report Data</h3>
<p>As seen in the previous figure, you can create <b>New</b> report data; <b>Edit</b> an existing report data (the figure above has an existing report data in the <b>C_Main</b>. It also has three main folders. The built-in fields we saw earlier. The parameters will contain parameters associated with the report. The images folder contains images that can be imported into this folder, which you can embed in a report from your hard drive.</p>
<p>The <b>Report Data</b> is an excellent starting point to create a report from scratch without using wizards displayed in default. When you click on the drop-down handle <b>New</b> the following menu will be displayed.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image28.png" /></p>
<p>All you need to do is to go and configure each of the items from top to bottom as follows:</p>
<ul>
<li>The <b>Data Source&hellip;</b> will bring up a window where you establish the connection to the datasource.</li>
<li>After this, you click on <b>Dataset&hellip;</b> to create a query to extract a set from the database which you want to display in your report. When you click on <b>Dataset&hellip;</b> you will display the properties of <b>Dataset</b> which you can use to design a query visually (only for SQL Server databases), an SQL Statement or import a saved SQL query or RDL file.</li>
<li>You can then define parameter(s) by clicking on <b>Parameters&hellip;</b> to create a parameter from its <b>Properties</b> window. You add a parameter if you want to filter your query further to produce a smaller and more manageable set of pertinent information.</li>
<li>Click on <b>Images&hellip;</b> to choose images from your machine if you need to embed them in the report.</li>
</ul>
<p>On the other hand, if you already have these you can edit them or delete them.</p>
<h3>Report Designer pane</h3>
<p>The various parts of this pane are shown in the following screenshot. This has been described earlier. The choices you make in the <b>View</b> pane will show or hide the <b>Groupings</b> at the bottom as well as in the <b>Ruler</b>. When you want to create a report from scratch and do not want to use the wizards, you can delete everything on the report and start from scratch.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image29.png" /></p>
<p>For displaying groups of data, the underlying data must support this structure and it is necessary that there exists hierarchical relationships within the data. An example is shown in the following screenshot from the <i>TestNorthwind</i> database used in the exercises.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image30.png" /></p>
<p>In Report Builder 2.0, groupings show both row groupings as well as column groupings. If you are starting from the wizard, you will be setting up the row groups as well as column groups as seen in the <b>Arrange Fields</b> page of the wizard. The available fields were moved into column groups and row groups. One of the shortcomings of this wizard is that once you move a field from the available to any of the other three, you cannot move it back. However you can only move between the three. If you go <b>back</b> and return, you have the same arrangement. If you <b>Cancel</b>, you need to start the wizard again. Another problem with this wizard step is that you must add a field to the <b>Value</b> field. What if one wants to show only a few columns of data in a table? However, it is well suited for matrix design. The above shortcomings in the earlier SQL Server 2008 RC0 version have been rectified in the latest version of Report Builder 2.0 bundled with the Feature Pack (<a href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=371356" target="_blank">https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=371356</a>).</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image31.png" /></p>
<p>The above arrangement would lead to a report&#39;s grouping as shown here:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image32.png" /></p>
<p>Each of the groups shown above has its own properties which can be accessed&nbsp; by right-clicking the group. For example, the row group <b>[ProductName]</b> in the above. You can then review its <b>Group Properties</b> window as shown in the two following screenshots:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image33.png" /></p>
<p>When you click on the drop-down item, <b>Group Properties&hellip;</b>, the <b>Group Properties</b> window shows up.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image34.png" /></p>
<p>Clicking on the <b>Next</b> button in the <b>New Table</b> or <b>Matrix</b> wizard&#39;s <b>Arrange&nbsp; Fields</b> page takes you to the window where you can arrange to show the group aggregates. You can show them in several ways depending on the choice you make as shown in the following screenshot:</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image35.png" /></p>
<h3>Properties</h3>
<p>This window appears, by default, at the right of the report designer pane. It shows all configurable properties of the objects on the report body. You only need to click on the object. Most of the properties become effective as soon as you complete the property and leave that property or move to the next property in the <b>Properties</b> window. If you add custom assemblies, these are also shown in this window.</p>
<h1>Server status and tools</h1>
<p>At the very bottom of the Report Builder you will get an indication as to the Report Server you are connected to (present case there is only one running) and its status as shown in the following screenshot. You can also change from design to run (preview) by clicking on the respective icons in this figure. You can also enlarge or reduce the size of the report both in design and in preview using the zoom slide.</p>
<p style="text-align: center;"><img src="http://www.packtpub.com/files/images/sqlserver08-article1-image36.png" /></p>
<p>
	&nbsp;</p>
<h2>Summary</h2>
<p>In this part of the article, we had a look at the Report Builder overview. We described the Report Builder 2.0 interface along with the new features that are incorporated into this version. In the next part, we will discuss about <a href="http://www.packtpub.com/article/report-builder-in-microsoft-sql-server-2008-part2?utm_source=sl_sqlserver08_abr1_0309&amp;utm_medium=content&amp;utm_campaign=sanjiv" target="_blank">Enabling and reviewing My Reports, and will see how to Modify a basic report</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.allfreetech.com/database/sql-server/working-with-the-report-builder-in-microsoft-sql-server-2008-part-1-30.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3 Quick And Painless Ways To Fine Tune SQL Server Query Performance</title>
		<link>http://www.allfreetech.com/database/sql-server/3-quick-and-painless-ways-to-fine-tune-sql-server-query-performance-19.html</link>
		<comments>http://www.allfreetech.com/database/sql-server/3-quick-and-painless-ways-to-fine-tune-sql-server-query-performance-19.html#comments</comments>
		<pubDate>Sat, 23 Jan 2010 02:29:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Database]]></category>

		<guid isPermaLink="false">http://www.allfreetech.com/?p=19</guid>
		<description><![CDATA[Effective database design is an aspect often overlooked in application design phases. A flawed data model will lead to flawed transactions that could compromise your data as well as produce poor response times. There are many factors which affect the performance of your database ranging from hardware to good design. This article focuses on tips [...]]]></description>
			<content:encoded><![CDATA[<p>Effective database design is an aspect often overlooked in application design phases. A flawed data model will lead to flawed transactions that could compromise your data as well as produce poor response times. There are many factors which affect the performance of your database ranging from hardware to good design. This article focuses on tips and tricks to improve your data structure design that can increase SQL-Server query performance: index design, stored procedures and triggers. <span id="more-19"></span></p>
<h2>Indexes</h2>
<p>Index design is a large concern when designing your data structure. SQL Server indexes are similar to the indexes you would find in the library or the tabs in a dictionary.</p>
<p>There are four main types of indexes:</p>
<ul></ul>
<ul></ul>
<ul>
<li>Primary Keys (Creates a unique index to enforce a primary key)</li>
<li>Unique (Creates a unique index but not a primary key) &#8211; Clustered (Which are indexes based on the actual table data)</li>
<li>Non-Clustered (Not based on the table data)</li>
</ul>
<p>I&#39;m going to touch on how setting your indexes can affect performance. To retrieve data from a table, a SQL statement is passed and the table is searched in a linear mode until the data that is needed is come across. Indexes eliminate whole table scans by allowing queries to access data by using the index directly. This allows queries to perform lookups much more efficiently.</p>
<p>Indexes help with table SELECTS, UPDATES, and DELETES, but with INSERTS, indexes will slow the performance down. The reason for this is simple if you think about it. Inserting a record in a table with a lot of indexes requires the insert to traverse all the indexes in the table. This is where the design aspect comes into play. If the majority of work running against a table is lookups then you will want to use indexes, if the majority of work done against a table is inserting then you probably do not want to use indexes. Another consideration you might need to consider is table size. If a table is small then it may be more efficient to do a table scan rather than using indexes.</p>
<p>To summarize, when thinking about indexes and performance you must considers the following:</p>
<ol></ol>
<ol></ol>
<ol>
<li>What type of actions will this table be primarily used for? If you will be using the table for things other than INSERTS then indexes are a good idea.</li>
<li>Can an index be created that will represent the majority of data you will be pulling? If so then the queries need to look no further than the index itself for the data. This eliminates the queries from having to hit the actual data tables.</li>
<li>Is the table large enough to require an index? Indexing small tables can slow down your performance.</li>
</ol>
<h2>Stored Procedures</h2>
<p>Another &quot;surefire&quot; way to improve your response times and performance is to use stored procedures whenever possible. Stored procedures are prebuilt, precompiled SQL statements that are stored within the database itself. Stored procedures can accept parameters as input and return values as output. Stored procedures are efficient for many reasons. First off, stored procedures exist as part of the database itself. Because of this, they are precompiled and prechecked for errors. SQL statements that are going to be used frequently such as table inserts, retrievals, deletions, and updates should be built as a stored procedure. Data validation can be built into stored procedures to ensure that business rules are followed and data integrity is maintained. When executing a stored procedure it is only necessary to pass an execute command. For example, to call a stored procedure called sp_AddCustomer, you would send</p>
<pre>     EXEC sp_AddCustomer, ParameterList</pre>
<p>to the database along with any parameters needed. This is much more efficient than sending entire SQL statements over the network, especially if there are many users performing the same actions.</p>
<p>Let&#39;s say we have a table called orders. We may want to add orders frequently (we would hope!). We could build a stored procedure that will INSERT a row into the orders table based on a list of parameters. For example:</p>
<pre>     CREATE PROCEDURE sp_AddOrder @customername char,
     @Customeraddress char, @ItemNum Int, @OrderDate Date
     As
     Declare @InsertString NVARCHAR(500)

     Set @InsertString =&#39;INSERT INTO ORDERS
     (customername,customeraddress,itemnum,orderdate) values
     (@customername, @Customeraddress, @ItemNum, NOW)&#39;
     GO
</pre>
<p>Then to execute:</p>
<pre>     EXEC sp_AddOrder InsertString,customername,
     Customeraddress, ItemNum</pre>
<p>Stored Procedure make database design quick , scalable and maintainable. When deciding to use stored procedures you can follow the rules below.</p>
<ol></ol>
<ol></ol>
<ol>
<li>Stored procedures execute by simply passing an execute command to the database. This relieves the network from having to pass an entire SQL statement over thus saving bandwidth and response time.</li>
<li>Stored procedures are precompiled. Thus all error checking is done at the time it is built. This ensures solid SQL Statements and fast execution time.</li>
<li>Stored procedures are fantastic for maintaining data integrity. Good data integrity always translates into good response times.</li>
</ol>
<h2>Triggers</h2>
<p>Triggers are very similar to stored procedures in that they also reside in the database itself. They too are precompiled and have a very similar structure.</p>
<p>So what are the differences? Triggers execute automatically based on a particular action to a table. INSERT, DELETE, UPDATE are all common catalyst to a trigger.</p>
<p>Why would you want an additional statement to run against the database if you are already passing one? The answer &#8211; triggers can be used for anything from audit trails to data validation. A trigger on a table is considered to be part of any statement run against that table. Because of this, a ROLLBACK in a trigger will cause the entire SQL statement to be rolled back. It becomes almost impossible for someone to corrupt your data. As we said before, good data means good response times.</p>
<p>If you need to maintain data integrity, you can move all validation into triggers and take that burden off the client machine. In a large-scale environment this can save valuable resources. If you need to maintain an audit trail of sensitive data, you no longer need to put that processing on a client application or on the burden of the person maintaining the database. Every time you update data on an orders table for example, you could move the old data into a table called audit_orders.</p>
<p>All this work which would normally bee done on the client side or by the DBA, is now handled automatically by a TRIGGER. This not only takes the burden away from others, but also assures that there can be no mistakes in tracking the history of the data. The general structure for designing a trigger is below.</p>
<pre>     If exists (select * from sysobjects where type = &#39;TR&#39;
     name=&#39;ti_orders&#39;)
     Drop trigger ti_orders
     Go
     Create trigger ti_orders on orders for UPDATE
     As
     Insert into audit_orders (parm1,parm2,parm3,parm4,etc,)</pre>
<p>The above example will move a copy of the data into the audit_orders column before it is modified. This will give you a snapshot of how the data existed through time. And because this is prebuilt, you only need to write it once and not worry again about maintaining the audit table.</p>
<h2>Summary</h2>
<p>In an enterprise situation it is often difficult to say what vehicles are going to be used to access or modify your data. There may be more than one group of people, more that one application, or more than one DBA.</p>
<p>Because of this, strong validation on the database side in the form of Stored Procedures,Triggers and Indexes will ensure your database remains scaleable, your data remains safe, and response times remain high.</p>
<p>Poorly designed data models can only frustrate your users and yourself. If you follow the steps above when designing your database, you will find you end up with a very scalable and responsive structure you can build upon.</p>
<p><strong>Phillip Elbert</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.allfreetech.com/database/sql-server/3-quick-and-painless-ways-to-fine-tune-sql-server-query-performance-19.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The SQL Server High Performance Series</title>
		<link>http://www.allfreetech.com/database/sql-server/the-sql-server-high-performance-series-21.html</link>
		<comments>http://www.allfreetech.com/database/sql-server/the-sql-server-high-performance-series-21.html#comments</comments>
		<pubDate>Fri, 23 Mar 2007 02:34:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Database]]></category>

		<guid isPermaLink="false">http://www.allfreetech.com/?p=21</guid>
		<description><![CDATA[Inefficiency is a gluttonous thief. It burglarizes your server rooms at all hours of the day and night, demanding virtually limitless hardware sacrifices to satiate its endless thirst for clock cycles and disk rotations. In return it punishes your users with reduced performance and reduced satisfaction, and devastates your solution&#39;s scalability. This inefficiency, materialized in [...]]]></description>
			<content:encoded><![CDATA[<p>Inefficiency is a gluttonous thief. It burglarizes your server rooms at all hours of the day and night, demanding virtually limitless hardware sacrifices to satiate its endless thirst for clock cycles and disk rotations. In return it punishes your users with reduced performance and reduced satisfaction, and devastates your solution&#39;s scalability.<span id="more-21"></span></p>
<p><b>This inefficiency, materialized in the form of slow performance, is one of the primary causes of system abandonment</b>. This is particularly troublesome in the SQL Server world where many systems servicing large user bases often run on low cost server boxes that leave little margin for performance waste. Many organizations have tossed out their SQL Server solution running on a $3000 PC because the performance wasn&rsquo;t satisfactory (not achieving so-called &ldquo;Enterprise&rdquo; performance), to replace it with a multi-million dollar mainframe solution, overcoming embarrassing inefficiency with brute force.</p>
<h3>Reward</h3>
<p>Several years back, in a moment of nerdish bravado, I made a foolish blanket statement that I could reduce the runtime of virtually any element of a non-trivial SQL Server database solution by 95% (thus improving the performance by about 20x), doing so through some rudimentary changes requiring nothing more than some analysis, minor code changes (changing the underlying code, but not the functionality), indexing, and file group changes. To my surprise, and even greater dismay, this number actually proved to be remarkably accurate: From giant multi-hour organization wide reports, to simple security procedures run hundreds of times a minute, the obvious low hanging fruit alone often improved performance by 10x or more. With a little bit of elbow grease it has proven extraordinarily common to improve performance by 20x or more, significantly improving responsiveness and load handling of the respective systems at minimal cost.</p>
<p>The remarkable thing is that these weren&rsquo;t systems implemented by bad developers &ndash; many of them were extraordinary developers who implemented a lot of tricks and techniques that I&rsquo;ve co-opted and added to my own bag of techniques. Instead there seems to be a dearth of real information on developing for performance in SQL Server, leaving many to guess about the best approach, not to mention that there isn&rsquo;t enough attention paid to performance efficiency in enterprise solutions. Many seem to be under the false impression that gross inefficiency requiring massive clusters to perform trivial tasks merits a capital-E Enterprise designation.</p>
<h3>Motivation</h3>
<p>In software development there&rsquo;s an oft-referenced vice known as &ldquo;<b>premature optimization</b>&rdquo;. This is the tendency to prematurely focus on code performance while code is still young and awkwardly growing, before the critical performance weaknesses have been identified and measured. The end result of this misguided effort is often convoluted code that is difficult to understand and maintain (for instance code including inline assembly or using specialized system hacks in seldom called edge functions). This is often a mistake of inexperienced programmers that haven&rsquo;t had the perfectionist engineering streak beaten out of them.</p>
<p>Consider also that performance truly isn&#39;t a concern for the vast majority of code in most client-side applications &ndash; it likely doesn&#39;t matter if the code that validates an input box in a Windows Forms application takes 3ms or 70ms to complete. As the processing is decentralized and isn&rsquo;t impacting other users who might be running the application elsewhere on the planet, it is basically making use of &ldquo;free&rdquo; clock cycles available on the client PC, and generally is imperceptible to the user. If one thousand different users were running the application simultaneously, they&rsquo;re running it on a thousand powerful PCs, effectively throwing a massive &ldquo;cluster&rdquo; at the problem. In other words, you can overcome application inefficiency on the client side through massive computational excess and a endless ability to scale-out. Even in cases where there is worthwhile performance issues identified, for example an image processing algorithms that takes several seconds to perform an operation, it&#39;s often best to wait until the project nears a release and the code has settled, at which point you can send a commando performance team to profile and then selectively improve the slowest sections of code that will have the most beneficial impact, focusing on the lowest hanging fruit, yielding a bounty of quick wins. (Taking one for the team because there&#39;s no I in team, and no clich&eacute; unworthy)</p>
<p>Enterprise databases, or any centralized system for that matter, are entirely different beasts &ndash; performance is one of the critical elements of these systems, and performance problems are one of the primary reasons why solutions are abandoned or re-architected. Consider that every clock cycle wasted on a shared resource, such as a database server, impacts the performance of the overall system and every other user. In most environments there is a massive asymmetry between the computational capability of client machines, and the computational capability of a shared system, such as a database server. There are usually some fixed financial and technological limits to the amount of hardware that a system can scale to, so your database server running on a lowly Dell two-way server is desperately trying to keep up with the demands of 500 user workstations pounding away at it. Even though Google is clustered on purportedly thousands of machines, they still have to develop efficiently to be able to economically service millions of users in a timely manner.</p>
<p>Thus, while it might seem irrelevant when taken alone that your stored procedure saturates the resource, taking 200ms to return a simple list of values to populate a drop list for Joe User, imagine 100 users all opening that form at the same time putting a shared demand on the database system. The performance impact starts to become significant and adversely affects the usability (and credibility) of the system. This is exacerbated by the fact that simultaneous performance demands aren&rsquo;t merely additive on shared resources, but rather contention and task sharing often means that these issues snowball into much more than the sum of the parts.</p>
<h3>Wisdom</h3>
<p>You should consider the performance of your database from day one with every table you add, every index you create, every trigger you concoct, and every relationship you define. While the misguided will argue that this amounts to premature optimization (as Ralph Waldo Emerson observed, a foolish consistency is the hobgolbin of little minds, and the belief that any performance concerns are premature is just such a foolish consistency), the reality is that the performance of a database system is largely defined by the fundamental design of the system, and as the system grows it becomes much more difficult and costly to solve fundamental performance problems. Furthermore, once an enterprise system reaches production even the simplest performance change, such as adding an index, requires complex analysis to determine how it impacts other parts of the system, or that it satisfies what could be hundreds of procedures accessing the object.</p>
<p>The cynical will wonder how one can predict the future when designing a database system, but the reality is that the access patterns are usually obvious by the time you&#39;re starting designing tables &#8211; you know how the tables relate, what data will be searched, how often you&#39;ll be selecting the records versus modifying them, and how big the fields and records should be. Use this information effectively when developing the tables to choose the appropriate clustered and secondary indexes, to minimize the size of each record, and to write efficient SQL. Don&#39;t leave it for a maintenance programmer to reverse engineer the system and apply best guesses in a moment of crisis in the future.</p>
<h3>The Basics? We&rsquo;re All Professionals Here!</h3>
<p>Much of the material covered in this outing will be old hat for a lot of developers, but is nonetheless worth a recap &ndash; Even among the pros there remains misunderstandings and conflicting information about the fundamentals of databases, and the true magnitude of impact they have on systems. I&rsquo;ve intentionally authored this series conversationally, as opposed to a &ldquo;high impact hit list!&rdquo;, however if you&rsquo;d just like a brief summary list you can find one at the end.</p>
<h3>Data Size</h3>
<p>This needs to be addressed as there is a growing camp of &ldquo;data wasters&rdquo; that erroneously believe that the larger the amount of waste, the more Enterprise Ready a solution is (capitalization used derisively). I step into this quagmire knowing full well that this section will yield me some &ldquo;you&rsquo;re a dummy!&rdquo; responses from some newly earned adversaries, however that&rsquo;s a price I&rsquo;m willing to pay if I can save but one byte tree.</p>
<p>Minimize the size of your data. Don&rsquo;t use GUIDs where they aren&#39;t necessary (e.g. where you don&rsquo;t really need global uniqueness/replication), and don&rsquo;t use a bigint where an int or a smallint will suffice. Don&rsquo;t use a smallint where a tinyint will suffice or an nvarchar where a varchar would be fine. Use the smallest type that is reasonable for the field. Don&rsquo;t invent vague packing technicalities or native type size issues in an attempt to justify oversized data.</p>
<p>Of course you <i>should</i> plan for realistic growth, and I&rsquo;m not advocating that you use a tinyint to store your CustomerID field, but keep the rational, real world in mind when designing your applications &ndash; are you really going to exceed 2 billion users? Is there going to be more than 32767 languages in your application? Is it likely that we&rsquo;re going to a new calendaring system that might have 2 billion months?</p>
<p>Evaluate if it might be an acceptable compromise to simply use these large types in your fa&ccedil;ade while actually storing smaller types in the actual database. This would give you improved performance, and would allow you to easily upsize your data types in the future in the unlikely event that it becomes necessary.</p>
<p>Clearly there are cases where large data types are legimately warranted, however too many database architects abscond themselves of any responsibility for efficiency by making everything a GUID or a bigint &ldquo;just in case&rdquo; (GUIDs have a substantial creation cost as well, in addition to the obvious storage and I/O costs. While GUIDs once used the available network card MAC address as the foundation and generally sequentially increased in value on each new GUID, in current Windows variants GUIDs are basically random numbers &#8212; used as a clustered primary key they can lead to endless data reordering).</p>
<p>Why does it matter? In real enterprise apps before you know it there are tens or hundreds of millions of rows throughout your database, and these rows need to be read from, and written to, the glacially slow storage subsystem constantly &ndash; given this finite resource, doesn&rsquo;t it seem logical that 1MB of I/O carrying 20,000 records is better than 1MB of I/O carrying only 5,000 records? Of course it is. Isn&rsquo;t it better that 10% of your database can fit in the memory cache rather than just 5%? Of course.</p>
<p>&nbsp;</p>
<p>Don&rsquo;t be lulled into a false justification of large data types by running ridiculously small benchmarks, where all of the data exists in the memory cache and the I/O is dwarfed by the computational element of the query, yielding &quot;only&quot; a performance hit of 10% or so with larger types &ndash; when your database gets to real enterprise size, <b>size really does matter</b>. That cluster indexed GUID primary key not only makes the row bigger, it makes every non-clustered index bigger (and thus slower) as well, and when the weakest link SAN is running at 100%, you&#39;ll regret every wasteful byte.</p>
<h3>Indexes</h3>
<p>Many SQL Server performance problems are rooted in missing or inappropriate indexes, or alternately unused indexes. This is often true for databases thrown together by front-end experts unhappily tasked with supplying the back-end database, just as it&rsquo;s often the case for those carefully crafted by highly-focused database professionals.</p>
<p>An understanding of indexes, and a focus on their application, is paramount for high performance databases. Not only is it critical to create the right indexes, it&rsquo;s important to craft your access to properly utilize the indexes that are there.</p>
<h3>A Bookshelf Full of Examples</h3>
<h3>Non-Clustered Indexes</h3>
<p>Indexes in reference books serve the same purpose (and share many of the same traits) as those in the database world &ndash; by referencing the index you can follow a shortcut to a particular piece of information, seeking directly to that specific page, versus going from page to page scanning the contents. In the SQL Server world these sorts of indexes are called <b>non-clustered indexes</b> (or secondary indexes) &ndash; they are a subset of the data ordered for a specific purpose, containing a pointer to where the real data row can be found.</p>
<p>In the Northwind database an example of a non-clustered index is ShipPostalCode on the Orders table. This index sorts by the ShipPostalCode, and may be used for a query such as the following.</p>
<p><code>SELECT * FROM Orders WHERE ShipPostalCode = &#39;05022&#39;</code></p>
<p>If you take a look at the execution plan (Ctrl-K or choose the option &ldquo;Show Execution Plan&rdquo; under the Query drop-down in Query Analyzer. When you execute a query with this option enabled a new tab, Execution Plan, will appear beside the results tab), you can see that an index seek took place, and then a bookmark lookup to find the actual data row. If we run SET STATISTICS IO ON on the connection before running the above query, we&rsquo;ll get some statistics on the IO used to satisfy the query, which will be as follows.</p>
<p><code>Table &#39;Orders&#39;. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0.</code></p>
<p>Compare this to the following query, which simulates having no index.</p>
<p><code>SELECT * FROM Orders WITH(INDEX(0)) WHERE ShipPostalCode = &#39;05022&#39;</code></p>
<p>In this case the execution shows a full table scan, and our IO statistics reports the following.</p>
<p><code>Table &#39;Orders&#39;. Scan count 1, logical reads 21, physical reads 0, read-ahead reads 0.</code></p>
<p>Without the index there was significantly more I/O, and the differential would be <b>vastly</b> worse if this were a large enterprise-sized table instead of a small sample table. To make matters much, much worse such a table scan will block on every single exclusive page or row lock on the table, waiting for the data to be unlocked just to be able to verify if the wanted information is contained within, while the index seek knows that the locked data isn&#39;t the data that it&#39;s looking for and is unaffected. Try running the above two queries in two separate query analyzer windows while the following script is running in yet another (increase the WAITFOR delay if you can&#39;t jump between them all within 30 seconds).</p>
<p><code>BEGIN TRAN</p>
<p>	UPDATE Orders SET OrderDate = &#39;1997-08-27&#39;<br />
	WHERE OrderID = 10647</p>
<p>	WAITFOR DELAY &#39;00:00:30&#39;</p>
<p>	ROLLBACK TRAN</code></p>
<p>The first query, using the index, instantly returns the result regardless of the row lock, which is logical given that the row being locked is not what the query is looking for, while the second query, not using the index (which can happen because no index exists, or the index isn&rsquo;t deemed the best choice) blocks until the other connection&rsquo;s lock is released. Not using an index is not only vastly less efficient, it can significantly worsen blocking problems as a database scales (or rather tries to scale).</p>
<h3>Clustered Indexes</h3>
<p>Returning to our analogy, many books take it a step further and order the content, making the data itself an index of sorts. A cookbook might sort by main category and then dish name, while a phone book famously sorts by [city, last name, first name] (in that order). Thus if you want to search based upon the sorted data, it&rsquo;s extremely efficient &ndash; in the example of the phone book you can very quickly seek to the desired city and last name, scanning a small number of records for the desired person. In the SQL Server world this sort of index is called a <b>clustered index</b> (the sorting of the data itself), and for obvious reasons you can only have one clustered index in a book, or on a table. The primary benefit of a clustered index is that all of the table data is immediately available for every index match &ndash; no dereferencing is necessary.</p>
<p>In the Northwind database consider the following query.</p>
<p><code>SELECT * FROM Orders JOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID WHERE Orders.ShipPostalCode = &#39;05022&#39;</code></p>
<p>If you look at the execution plan, the Order Details data is grabbed via a very efficient clustered index seek.</p>
<p>Clustered indexes aren&rsquo;t all milk and honey, though. For instance imagine that you&rsquo;re the hard working typesetter maintaining the layout of the phone book, and you&rsquo;ve carefully arranged all of the entries on the respective pages. Every time a new entry comes in and doesn&rsquo;t coincidentally fit right at the end of the sort order, or someone changes the information on an existing row in a way that alters the sort order (&ldquo;Smith&rdquo; changes his name to &ldquo;Jones&rdquo;), you need to reorganize some pages to make space. This same data-churn problem occurs with both non-clustered and clustered indexes, but clustered indexes exacerbate the problem given that it contains the entirety of the row data.</p>
<p>Of course you could plan for this by keeping a bit of blank space on each of your pages to facilitate at least a couple of changes, which is what the <b>fillfactor</b> is used for in SQL Server (a lower fillfactor leaves more empty space but reduces the true data density &#8211; insert performance is improved, but read performance is diminished. A high fill factor increases the real data density and thus read performance, but increases the likelihood of inserts requiring page splits. Note that fillfactor only applies on index creation, and whenever you defragment/rebuild your indexes), however this can be a serious performance issue for out-of-order inserted data, or frequently changing cluster indexed fields. It&rsquo;s for this reason that many developers use the monotonically increasing identity field as their cluster index. Historically there was a worry that having multiple inserts all going to the same &quot;place&quot; in the index, at the end, would lead to scalability killing contention at this hot spot. SQL Server has logic to deal with identity fields and effectively eliminates this hot spot issue.</p>
<p>Another problem with clustered indexes is their girth (they contain the entire row data). This is largely irrelevant if you&rsquo;re seeking to specific records, or where you actually plan on using all of the data after a lookup, however if you are querying a range of data (for instance the first name of all of the people with the last name &ldquo;Forbes&rdquo; in the city of &ldquo;Oakville&rdquo;) the query engine will read in the entire row contents for each matching record using a range scan, extracting only the requested data. In our example phone book there is so little extra data that it&rsquo;s a minor overhead, however in many large real-world tables this can have a serious performance impact.</p>
<p>Consider if instead we had a secondary index that was sorted by City, Last Name, First Name, the query engine could very efficiently scan past only the small index entries.</p>
<h3>Covering Indexes</h3>
<p>This brings up a very important point &ndash; Some indexes contain enough information that you don&rsquo;t even need to go to the content, your query being satisfied by the index itself. Consider an index in a tour book that sorts famous attractions by their name, and the country and city that they were located in, pointing to the page where further information regarding it could be found. If you just want to know what city the Accademia dell&#39; Arte del Disegno in Italy is found in, a quick seek through the index will tell you that it&rsquo;s in Florence. In this instance the index was a &ldquo;covering index&rdquo;, in that it fully covered our request and we didn&rsquo;t need to dereference to the complete topical information. This is often the most efficient query mechanism of all.</p>
<p>Consider the following variation of a query we ran earlier.</p>
<p><code>SELECT OrderID FROM Orders WHERE ShipPostalCode = &#39;05022&#39;</code></p>
<p>This will efficiently use the ShipPostalCode index to find the specific record, and because the query is fully satisfied by the index itself, the costly bookmark lookup is avoided, and IO is minimal.</p>
<p><code>Table &#39;Orders&#39;. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0.</code></p>
<p>The observant will note that OrderID isn&rsquo;t actually in the index ShipPostalCode, or at least it doesn&rsquo;t appear to be. The trick is that all of the fields that are the sort fields for the clustered index, if one is defined, are automatically added as data fields to every other index on the table. This can be blessing in cases where you want one of the clustered fields and suddenly the non-clustered index is a covering index, but it also needs to be weighed against the fact that it makes every other index larger, and thus less &ldquo;data dense&rdquo;.</p>
<p>Small covering index seeks are the most efficient method of pulling data, and it&rsquo;s a good reason to ensure that you are only pulling the specific fields that you actually need from any given table, preferably with a covering index. Range scans are also highly efficient in many situations, and are usually used when the wanted entries in an index are consecutive, such as when you search BETWEEN two dates against a date index, though because of the previously mentioned bookmark lookup costs range scans are generally only seen if the index is fully covering, or against the clustered index.</p>
<p>Even in the case where a full scan is necessary, indexes might still be fully covering. Consider if the following index were added to the Customer table.</p>
<p><code>CREATE INDEX CountryCity ON Customers(Country,City,Address)</code></p>
<p>This index of course contains Country, City, Address, but as mentioned above it also contains CustomerID because it&rsquo;s in the clustered index. Of course if we query on Country, or Country and City, or Country, City, and Address, an efficient seek or range scan might be used to pull the matching records.</p>
<p><code>SELECT CustomerID FROM Customers WHERE Country = &#39;Canada&#39;</code></p>
<p>What if instead we wanted to search only on the address? In that case the index can&rsquo;t be searched in order because it sorts by country and then city and address, and thus a particular address could exist anywhere in the index.</p>
<p><code>SELECT CustomerID FROM Customers WHERE Address = &#39;43 rue St. Laurent&#39;</code></p>
<p>You might be surprised to see that it still used the index, albeit this time it&rsquo;s an inefficient scan rather than a seek. The index was used because it covered the query (all predicates and returned columns), and because the index is only a subset of the data it requires less I/O to scan the entire index than it does to scan the entire table data.</p>
<h3>Statistics and Bookmarks</h3>
<p>In a prior example we ran a query that required a bookmark lookup to satisfy the query (thus it did not have a covering index). The query was as follows.</p>
<p><code>SELECT * FROM Orders WHERE ShipPostalCode = &#39;05022&#39;</code></p>
<p>If you look at the execution plan for this query you can see that it seeks the &ldquo;lookups&rdquo; in the index, and then does a bookmark lookup against the clustered index (which is the actual table data). In this case there is only a single row to return, but even still the bookmark lookup cost is estimated to account for 50% of the cost of the query.</p>
<p>The cost of bookmark lookups, where an item is found in the index but it isn&rsquo;t a covering index, is the reason why many people are surprised to find that SQL Server has ignored what they believe are perfect indexes and instead table scanned (&ldquo;Why isn&rsquo;t it using my index! ARGHHH!!!&rdquo;). Consider the following query.</p>
<p><code>SELECT * FROM Orders WHERE ShipPostalCode = &#39;24100&#39;</code></p>
<p>Looking at the query plan you can see that it actually did a cluster index scan (which is a table scan on a table with a clustered index) instead of using our index, and the subtree cost is 0.0530.</p>
<p>This might seem perplexing because we seem to have a perfectly satisfactory index, however let&rsquo;s do the same query again, this time using a query hint to force it to use our index.</p>
<p><code>SELECT * FROM Orders WITH(INDEX(ShipPostalCode)) WHERE ShipPostalCode = &#39;24100&#39;</code></p>
<p>If you look at the query plan you can see that it used our index, as demanded, but this time the bookmark lookups account for 80% of the query time. Our subtree cost comes in at 0.0564 &ndash; more than it was doing a table scan!</p>
<p>In this case this was only 10 records of a total of 830 (1.2%) yet still it opted to do a full table scan rather than using our index. Many developers have been perplexed in this situation, wondering why SQL Server was avoiding their beautiful index, but it&rsquo;s doing it for a very valuable reason &#8211; it was cheaper than indirectly looking up each piece of data through bookmarks.</p>
<p>Of course we could have avoided bookmark lookups by using the index as a covering index if possible by using a query like the following, presuming this was all the data we needed to extract from the table.</p>
<p><code>SELECT OrderID FROM Orders WHERE ShipPostalCode = &#39;24100&#39;</code></p>
<p>Now it uses our index, is super efficient, and has a subtree cost of only 0.0064. In larger databases the difference can be the tremendous by avoiding both the bookmark lookup and the table scan.</p>
<p>So how did the query engine guess how many rows would match a criteria to choose which method (whether by index and bookmark lookup, or table scan) to use to most efficiently satisfy the query? That&rsquo;s where something called distribution statistics comes into play. Statistics are a representative set of the data that are used by the query engine to make a best-guess plan for how to most efficiently serve the data. You can view the statistics for a given index, in the following case for the index ShipPostalCode, via the DBCC SHOW_STATISTICS command.</p>
<p><code>DBCC SHOW_STATISTICS(&#39;Orders&#39;,&#39;ShipPostalCode&#39;)</code></p>
<p>Due to the limited number of discrete ShipPostalCode values in the table, the statistics are entirely accurate in this case. In a more realistic database, with thousands or millions of rows, statistics start to become much more of an estimation (with an ever increasing margin of error). These estimations can lead to entirely wrong assumptions by the query engine in some edge cases, such as where it thinks a given set of predicates will yield thousands of rows when really it might yield only a couple.</p>
<p>Statistics can also fail for multi-field indexes. In this case the selectivity of the first field is used, so in the case of the index we created earlier (Country, City, Address), due to the fact that the country has a low selectivity (there are lots of entries for each country), the index will often be ignored, even though the city and address combination is highly unique. For this reason it is generally recommended that the most selective field comes first in your index, so in the case of that index the fields would be Address, City, and then Country. This is debateable because it also makes the index more single purpose &ndash; it no longer serves an efficient purpose for less-granular searches like just Country, or Country/City. This needs to be evaluated on a case by case basis, and truly wouldn&rsquo;t be an issue for fully-normalized tables.</p>
<p>It should also be noted that ensuring that your statistics are as accurate as possible is critical. SQL Server includes automatic statistic updates, on by default, where it will attempt to do data sampling and update statistics when it feels they are out of date. Nonetheless it is a best practice to schedule full statistic updating at regular intervals (at a minimum weekly), preferably using the WITH FULLSCAN option so it is as accurate as possible. The standard database maintenance plan includes a step for statistic updating, and allows you to choose the amount of data to sample.</p>
<p>Regardless of all of the above, there will be cases where you may find that your statistics are up to date, your indexes are optimal, yet SQL Server is still incorrectly choosing not to use your index. In this case it may be an unfortunate reality that an index hint needs to be added to the query to politely (or rather sternly) request that it reconsider. Obviously this should be a last resort.</p>
<h3>Actually Using Indexes</h3>
<p>So you&rsquo;ve created beautiful indexes, and you&rsquo;ve ensured that your query only pulls the necessary data from each table, using covering indexes where possible to avoid costly bookmark lookups. You pull up the execution plan to find&hellip;that the query engine is entirely ignoring your index. There are several reasons why this could happen.</p>
<p>Consider the following query.</p>
<p><code>SELECT OrderID FROM Orders WHERE LEFT(ShipPostalCode,4) = &#39;0502&#39;</code></p>
<p>Fairly simple query, and from the looks of it one might think it&rsquo;d be an efficient covered index seek. Upon execution you&rsquo;ll discover that actually it was an inefficient scan. Consider the following instead.</p>
<p><code>SELECT OrderID FROM Orders WHERE ShipPostalCode LIKE &#39;0502%&#39;</code></p>
<p>In this case the query is executed as a highly efficient index seek. I have had cases where this tiny difference reduced an enterprise report from running for literally hours to a matter of seconds.</p>
<p>The reason is that in the former the indexed field was hidden within a function. The query engine can&rsquo;t predict what the result of the function will be, so it&rsquo;s forced to evaluate it for every row to see what pops out. LIKE is a first class comparison, it knows how it behaves, so the query engine can actually optimize against it. There are countless cases where people hide criteria fields in functions unnecessarily, and the result is massive, unexpected inefficiency.</p>
<p>The most common example of this mistake is using DATEADD/DATEDIFF to pull rows within a certain period of time &ndash; instead of pre-calculated a fixed demarcation (i.e. precalculating GetDate() &ndash; 3 years) and then doing a direct comparison with the row data, developers are forcing whole table scans with wasteful date computations on every single row. For instance consider a query to report news items that have occurred within the past 12 hours from a hypothetical news table .</p>
<p><code>DECLARE @CurrentTime </p>
<p>	SET @CurrentTime = GetDate() </p>
<p>	SELECT * FROM NewsStories WHERE DATEDIFF(hh,NewsDate,@CurrentTime)&lt;12</code></p>
<p>Guaranteed to be terribly inefficient, yet it&#39;s overwhelmingly common. The query engine can much more effectively optimize the following variant.</p>
<p><code>DECLARE @StartTime </p>
<p>	SET @StartTime = DATEADD(hh,-12,GetDate()) </p>
<p>	SELECT * FROM NewsStories WHERE NewsDate &gt; @StartTime</code></p>
<h3>Database Cheat Sheet</h3>
<h3>Indexed Computed Columns</h3>
<p>At the outset I advocated that you minimize space usage (increasing real data density). The goal wasn&rsquo;t to try to fit that database on a floppy disk, but rather to minimize the amount of I/O necessary to satisfy a given query, as I/O is the weakest link of most enterprise systems. There are design choices, such as adding additional indexes, that actually increase the size of your database on disk yet reduce the I/O necessary for certain queries, and these are usually very worthwhile trade-offs.</p>
<p>Another powerful technique you can use to trade disk space for improved database performance is indexed calculated columns. There are countless variations, but I&rsquo;ll cover one scenario that is fairly commonly used &ndash; report counts by month for a given year. In the case of the Orders table this could be achieved via the following query.</p>
<p><code>SELECT YEAR(OrderDate) AS [Year], MONTH(OrderDate) AS [Month], COUNT(*) AS [Monthly Orders] <br />
	FROM Orders <br />
	WHERE YEAR(OrderDate)=1997 <br />
	GROUP BY YEAR(OrderDate), MONTH(OrderDate)</code></p>
<p>Instead of adhoc decomposing the date into month and year constituents, consider adding them as computed columns.</p>
<p><code>ALTER TABLE dbo.Orders ADD <br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OrderDateYear&nbsp; AS CONVERT(smallint,YEAR(OrderDate)), <br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OrderDateMonth&nbsp; AS CONVERT(tinyint,MONTH(OrderDate)) <br />
	</code></p>
<p>Now we can change our query to the following.</p>
<p><code>SELECT OrderDateYear AS [Year], OrderDateMonth AS [Month], COUNT(*) AS [Monthly Orders] <br />
	FROM Orders <br />
	WHERE OrderDateYear=1997 <br />
	GROUP BY OrderDateYear, OrderDateMonth</code></p>
<p>By itself we&rsquo;ve done nothing for the query efficiency (in fact it is actually less efficient as it&rsquo;s applying the where predicate after building the set), though we&rsquo;ve achieved a bit of &ldquo;code re-use&rdquo;. However we now have the foundations for some powerful indexed computed columns.</p>
<p><code>CREATE NONCLUSTERED INDEX IX_OrderDateDecomposed ON dbo.Orders<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OrderDateYear,<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OrderDateMonth<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) ON [PRIMARY]<br />
	GO<br />
	</code></p>
<p>Now the query referencing these computed columns is dramatically more efficient. Even better, these indexed computed columns haven&rsquo;t decreased the real data density of the table because they&rsquo;re only materialized in the index. NOTE: Ensure that queries that don&rsquo;t need these computed fields don&rsquo;t pull them explicitly or implicitly via the wasteful * column selector, as it&rsquo;ll unnecessarily calculate each of the computed fields for each row.</p>
<h3>Indexed Views</h3>
<h4>[This functionality only exists in the Enterprise and Developer edition of SQL Server 2000]</h4>
<p>An indexed view, sometimes referred to as a materialized view, is a sort of indexed computed columns on steroids, taking the idea of storing computed results to the next level. In a previous example we improved the performance of some data aggregation logic by grouping on some indexed computed columns. We can take a variant of that and create a view out of it.</p>
<p><code>CREATE VIEW dbo.OrdersByMonth<br />
	WITH SCHEMABINDING<br />
	AS<br />
	SELECT OrderDateYear AS [Year], OrderDateMonth AS [Month], COUNT_BIG(*) AS [Monthly Orders]<br />
	FROM dbo.Orders<br />
	GROUP BY OrderDateYear, OrderDateMonth</code></p>
<p>As it is the view is acting as nothing more than a template for queries against the underlying table, and is only of benefit for code reuse (which itself is a very worthwhile goal). We can take that a step further by materializing this view so the actual results are stored, and changes to the underlying table is automatically reflected in the aggregates. The following command creates the indexed view.</p>
<p><code>CREATE UNIQUE CLUSTERED INDEX IX_OrdersByMonth ON OrdersByMonth(Year,Month)</code></p>
<p>Now the following query will be satisfied by the indexed view, using the pre-computed values, rather than recalculating for every query.</p>
<p><code>SELECT [Year],[Month],[Monthly Orders] FROM OrdersByMonth WHERE Year=1997</code></p>
<p>In the end the resource usage for our monthly order count query has dropped by about 90% over the original query, and this is for a tiny sample database. In the real-world the differential can be extraordinary.</p>
<p>Indexed views do have some downsides, such as the automatic maintenance that occurs whenever the underlying data changes, however they can be an extraordinarily powerful tool in your arsenal and deserve further research if your platform supports it.</p>
<h3>Summary</h3>
<ul>
<li>Keep your rows as small as possible to maximize real data density.</li>
<li>All tables should have a clustered index except in rare exception situations. Normally this will be a single field primary key.</li>
<li>Small clustered indexes keep non-clustered indexes small, increasing real data density.</li>
<li>Clustered indexes help make other indexes covering indexes.</li>
<li>Queries serviced by covering indexes are extremely efficient.</li>
<li>Avoid hiding criteria fields in functions &ndash; indexes will not be used for them.</li>
<li>Consider indexed computed columns where appropriate</li>
<li>If you shelled out the cash for Enterprise Edition, seriously evaluate how indexed views fit in your solutions</li>
<li>Index, index, index! Only in extremely rare cases are the additional update and insertion costs associated with maintaining indexes heavier than the benefits.</li>
<li>Understand execution plans. Evaluate them regularly.</li>
</ul>
<h5>Examples given in this series will reference the sample database &ldquo;Northwind&rdquo;. It can be installed via the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en">script</a> found on the Microsoft website</h5>
<h4 class="clsPageLink">Dennis W. Forbes</h4>
]]></content:encoded>
			<wfw:commentRss>http://www.allfreetech.com/database/sql-server/the-sql-server-high-performance-series-21.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bulk Loading XML into SQL Server 2005 using .NET</title>
		<link>http://www.allfreetech.com/database/sql-server/bulk-loading-xml-into-sql-server-2005-using-net-25.html</link>
		<comments>http://www.allfreetech.com/database/sql-server/bulk-loading-xml-into-sql-server-2005-using-net-25.html#comments</comments>
		<pubDate>Mon, 12 Feb 2007 02:38:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.allfreetech.com/?p=25</guid>
		<description><![CDATA[With a number of clients, I have been provided a sample format for a transactions along with instructions to develop a process to load it into a database as quickly and painlessly as possible.&#160; This usually comes with the requirements that the XML data file can have any number of records from 1 to n.&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>With a number of clients, I have been provided a sample format for a transactions along with instructions to develop a process to load it into a database as quickly and painlessly as possible.&nbsp; This usually comes with the requirements that the XML data file can have any number of records from 1 to n.&nbsp; This example demonstrates the most efficient and scalable way that I have found to solve this. Not to mention that it can be maintained without rebuilding the solutions each time the data format changes.</p>
<div class="wlWriterSmartContent" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:324560c5-5085-435a-8913-b198c6215d26" style="padding: 0px; display: inline; margin: 0px;">
<p><a href="http://www.wijix.com/file.axd?file=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SqlXmlDemo.zip" target="_blank">Source Code for This Article</a></p>
</div>
<p><a href="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SQLXML%20Diagram_2.png"><img alt="SQLXML Diagram" border="0" height="504" src="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SQLXML%20Diagram_thumb.png" style="border-width: 0px;" width="578" /></a></p>
<p><span style="text-decoration: underline;"><strong>XML into SQL Server 2005 Example</strong></span></p>
<p>To load data from an XML into SQL Server, can be done in 3 easy steps.</p>
<p>1. Setup SQLXML.</p>
<p>2. Application to perform loading.</p>
<p>3. Develop Mapping File.</p>
<p><span style="text-decoration: underline;"><strong>1. Setup Instructions (SQLXML)</strong></span></p>
<p><em>[Install]</em></p>
<blockquote>
<p>1. Download SQLXML 3.0 <br />
		&nbsp;&nbsp;&nbsp; <strong><em>Note: if using SQL Server 2005, then SQLXML4.0 comes with it.</em></strong></p>
</blockquote>
<p><em>[Convert to .NET Compatible]</em></p>
<blockquote>
<p>2. To use this library, it must be convert to a type library that is .NET compliant. To do this.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; a. Using a Command Prompt browse to <strong>C:\Program Files\Common Files\System\Ole DB</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp; </strong>b. Verify that <strong>xblkld3.dll </strong>or <strong>xblkld4.dll</strong> exists.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; c. Assuming you have some version of Visual Studio .NET installed, run</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong><em>[Drive]:\[Path of Visual Studio]\Bin\tlbimp.exe [xblkld3.dll</em></strong> or <strong><em>xblkld4.dll]</em></strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This will create a new library called <strong>SQLXMLBULKLOADLib.dll.</strong></p>
</blockquote>
<blockquote>
<p>3. In Visual Studio, select &quot;Add Reference&quot; in the Solution Explorer</p>
</blockquote>
<blockquote>
<p>4. Browse to Location mentioned in 2.a</p>
</blockquote>
<p><em>[Add to Component Service (COM)]</em></p>
<blockquote>
<p>5. Goto Start &gt; Control Panel &gt; Administrative Tools &gt; Component Services</p>
</blockquote>
<blockquote>
<p>6. Under Components, Add new Application called &quot;Sql Xml&quot;</p>
</blockquote>
<blockquote>
<p>7. Open newly created application, and drag-n-drop, the <strong>xblkld3.dll </strong>or <strong>xblkld4.dll</strong> into application</p>
<p><a href="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/ComponentServices9_2.jpg"><img alt="ComponentServices9" border="0" height="406" src="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/ComponentServices9_thumb.jpg" style="border-width: 0px;" width="582" /></a></p>
</blockquote>
<p><em>[Reference in .NET Solution]</em></p>
<blockquote>
<p>8. Add a reference to <strong>SQLXMLBULKLOADLib.dll </strong>to your project.</p>
</blockquote>
<p><strong><span style="text-decoration: underline;">2. Loader Application</span></strong></p>
<p>The loader application takes 3 things to execute properly &#8211; connectionstring, mapping file location, and data file location.&nbsp; The example that I have provided allows for the user to provide 2 and assumes the connection string is fixed.&nbsp; Since SqlXml requires a connection string, it is assumed that a database exists and that you have rights to the database based on NTLM credentials of SQL user credentials provided in the connection string.&nbsp; For this example we have created an empty database named &quot;SqlXmlDemo&quot;, and set SqlXml Component to do the following</p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);">objBL.CheckConstraints = True  <span style="color: rgb(0, 128, 0);">// Check for Database Constraints and throw appropriate errors</span>
objBL.SGDropTables = True      <span style="color: rgb(0, 128, 0);">// Drop Tables referenced in Schema prior to loading</span>
objBL.SchemaGen = True         <span style="color: rgb(0, 128, 0);">// Create the Database Schema, if it does not exist      </span></pre>
</div>
<p><strong>C#: Loader Application</strong></p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">using</span> System;
<span style="color: rgb(0, 0, 255);">using</span> System.IO;
<span style="color: rgb(0, 0, 255);">using</span> System.Collections;
<span style="color: rgb(0, 0, 255);">using</span> SQLXMLBULKLOADLib;
<span style="color: rgb(0, 0, 255);">using</span> System.Data.OleDb;
<span style="color: rgb(0, 0, 255);">using</span> System.Diagnostics;

<span style="color: rgb(0, 0, 255);">namespace</span> SQLXmlExample
{
    <span style="color: rgb(0, 0, 255);">class</span> Program
    {
        [STAThread]
        <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">void</span> Main(<span style="color: rgb(0, 0, 255);">string</span>[] args)
        {
            <span style="color: rgb(0, 0, 255);">string</span> schema = <span style="color: rgb(0, 0, 255);">string</span>.Empty;
            <span style="color: rgb(0, 0, 255);">string</span> datafile = <span style="color: rgb(0, 0, 255);">string</span>.Empty;
            <span style="color: rgb(0, 0, 255);">string</span> connectionString = <span style="color: rgb(0, 96, 128);">@&quot;provider=SQLOLEDB;data source=localhost;database=SqlXmlDemo;Integrated Security=SSPI;&quot;</span>;

            <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">int</span> i = 0; i &lt; args.Length; i++)
            {
                <span style="color: rgb(0, 0, 255);">switch</span> (args[i].ToLower())
                {
                    <span style="color: rgb(0, 0, 255);">case</span> <span style="color: rgb(0, 96, 128);">&quot;-schema&quot;</span>:
                            schema = args[i + 1];
                            <span style="color: rgb(0, 0, 255);">break</span>;
                    <span style="color: rgb(0, 0, 255);">case</span> <span style="color: rgb(0, 96, 128);">&quot;-datafile&quot;</span>:
                            datafile = args[i + 1];
                            <span style="color: rgb(0, 0, 255);">break</span>;
                }
            }
            <span style="color: rgb(0, 0, 255);">if</span> (schema == <span style="color: rgb(0, 0, 255);">string</span>.Empty || datafile == <span style="color: rgb(0, 0, 255);">string</span>.Empty)
            {
                Console.WriteLine(<span style="color: rgb(0, 96, 128);">&quot;Missing Schema or Data File.  Format: SqlXmlExample -datafile [filename] -schema [filename]&quot;</span>);
                <span style="color: rgb(0, 0, 255);">return</span>;
            }

            Load(datafile, schema, connectionString);
        }

        <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">void</span> Load(<span style="color: rgb(0, 0, 255);">string</span> XMLFilename, <span style="color: rgb(0, 0, 255);">string</span> XMLMappingFilename, <span style="color: rgb(0, 0, 255);">string</span> ConnectionString)
        {
            SQLXMLBULKLOADLib.SQLXMLBulkLoadClass loader = <span style="color: rgb(0, 0, 255);">new</span> SQLXMLBULKLOADLib.SQLXMLBulkLoadClass();
            loader.CheckConstraints = <span style="color: rgb(0, 0, 255);">true</span>;
            loader.XMLFragment = <span style="color: rgb(0, 0, 255);">true</span>;
            loader.SchemaGen = <span style="color: rgb(0, 0, 255);">true</span>;
            loader.SGDropTables = <span style="color: rgb(0, 0, 255);">false</span>;
            loader.Transaction = <span style="color: rgb(0, 0, 255);">false</span>;
            loader.ConnectionString = ConnectionString;
            loader.Execute(XMLMappingFilename, XMLFilename);
        }
    }
}</pre>
</div>
<p><strong>VBScript: Loader Application</strong></p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);">Dim objBL
Set objBL = CreateObject(<span style="color: rgb(0, 96, 128);">&quot;SQLXMLBulkLoad.SQLXMLBulkLoad.3.0&quot;</span>)
objBL.ConnectionString = <span style="color: rgb(0, 96, 128);">&quot;provider=SQLOLEDB;data source=localhost;database=SqlXmlDemo;Integrated Security=SSPI;&quot;</span>
objBL.ErrorLogFile = <span style="color: rgb(0, 96, 128);">&quot;C:\ImportSample\error.log&quot;</span>

objBL.CheckConstraints = True
objBL.XMLFragment = True
objBL.SchemaGen = True
objBL.SGDropTables = True

objBL.Execute <span style="color: rgb(0, 96, 128);">&quot;C:\ImportSample\MappingFile.xml&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;C:\ImportSample\DataFile.xml&quot;</span>
Set objBL = Nothing</pre>
</div>
<p><strong><span style="text-decoration: underline;">3. Develop Mapping File.</span></strong></p>
<p>The maintenance aspect of this process is 95% related to the mapping file.&nbsp; The mapping file tells the application how the XML data elements map to the SQL Database Table.&nbsp; The sample data file below is contains information about 3 people.&nbsp; The mapping file show below the data file. outlines how this data is mapping to the database.&nbsp; Since the application has been instructed to drop tables and recreate them, the mapping file is in controll of hte structure of the tables in which the data will be loaded.</p>
<p><strong><em>XML Data File</em></strong></p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);">&lt;?xml version=<span style="color: rgb(0, 96, 128);">&quot;1.0&quot;</span> encoding=<span style="color: rgb(0, 96, 128);">&quot;UTF-8&quot;</span> ?&gt;
&lt;Data&gt;
    &lt;Record&gt;
        &lt;TABLE_NM&gt;CLIENTS&lt;/TABLE_NM&gt;
        &lt;ERR&gt;0&lt;/ERR&gt;
        &lt;FIRST_NAME&gt;John&lt;/FIRST_NAME&gt;
        &lt;LAST_NAME&gt;Smith&lt;/LAST_NAME&gt;
        &lt;CITY&gt;Houston&lt;/CITY&gt;
        &lt;STATE&gt;TX&lt;/STATE&gt;
        &lt;ZIP&gt;77082&lt;/ZIP&gt;
        &lt;DOB&gt;1973-07-13&lt;/DOB&gt;
    &lt;/Record&gt;
  &lt;Record&gt;
        &lt;TABLE_NM&gt;PROSPECTS&lt;/TABLE_NM&gt;
        &lt;ERR&gt;-1&lt;/ERR&gt;
        &lt;FIRST_NAME&gt;James&lt;/FIRST_NAME&gt;
        &lt;LAST_NAME&gt;Walton&lt;/LAST_NAME&gt;
        &lt;CITY&gt;Dallas&lt;/CITY&gt;
        &lt;STATE&gt;TX&lt;/STATE&gt;
        &lt;ZIP&gt;77563&lt;/ZIP&gt;
        &lt;DOB&gt;1965-01-15&lt;/DOB&gt;
    &lt;/Record&gt;
  &lt;Record&gt;
    &lt;TABLE_NM&gt;CLIENTS&lt;/TABLE_NM&gt;
    &lt;ERR&gt;0&lt;/ERR&gt;
    &lt;FIRST_NAME&gt;Jane&lt;/FIRST_NAME&gt;
    &lt;LAST_NAME&gt;Doe&lt;/LAST_NAME&gt;
    &lt;CITY&gt;Austin&lt;/CITY&gt;
    &lt;STATE&gt;TX&lt;/STATE&gt;
    &lt;ZIP&gt;77342&lt;/ZIP&gt;
    &lt;DOB&gt;1961-12-31&lt;/DOB&gt;
  &lt;/Record&gt;
&lt;/Data&gt;</pre>
</div>
<p><strong><em>XML Mapping File</em></strong></p>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);">&lt;?xml version=<span style="color: rgb(0, 96, 128);">&quot;1.0&quot;</span> ?&gt;
&lt;Schema xmlns=<span style="color: rgb(0, 96, 128);">&quot;urn:schemas-microsoft-com:xml-data&quot;</span>
        xmlns:dt=<span style="color: rgb(0, 96, 128);">&quot;urn:schemas-microsoft-com:xml:datatypes&quot;</span>
        xmlns:sql=<span style="color: rgb(0, 96, 128);">&quot;urn:schemas-microsoft-com:xml-sql&quot;</span> &gt;

   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;TABLE_NM&quot;</span>        dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;ERR&quot;</span>            dt:type=<span style="color: rgb(0, 96, 128);">&quot;int&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;FIRST_NAME&quot;</span>    dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;LAST_NAME&quot;</span>    dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;ADDRESS&quot;</span>        dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;CITY&quot;</span>            dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;STATE&quot;</span>        dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> sql:datatype=<span style="color: rgb(0, 96, 128);">&quot;nvarchar(2)&quot;</span>/&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;ZIP&quot;</span>            dt:type=<span style="color: rgb(0, 96, 128);">&quot;string&quot;</span> /&gt;
   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;DOB&quot;</span>            dt:type=<span style="color: rgb(0, 96, 128);">&quot;date&quot;</span> /&gt;

   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;ROOT&quot;</span>            sql:<span style="color: rgb(0, 0, 255);">is</span>-constant=<span style="color: rgb(0, 96, 128);">&quot;1&quot;</span>&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;Record&quot;</span> /&gt;
   &lt;/ElementType&gt;

   &lt;ElementType name=<span style="color: rgb(0, 96, 128);">&quot;Record&quot;</span>       sql:relation=<span style="color: rgb(0, 96, 128);">&quot;PERSON&quot;</span>&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;TABLE_NM&quot;</span>        sql:field=<span style="color: rgb(0, 96, 128);">&quot;TABLE_NM&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;ERR&quot;</span>            sql:field=<span style="color: rgb(0, 96, 128);">&quot;ERROR_ID&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;FIRST_NAME&quot;</span>    sql:field=<span style="color: rgb(0, 96, 128);">&quot;NAME_FIRST&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;LAST_NAME&quot;</span>        sql:field=<span style="color: rgb(0, 96, 128);">&quot;NAME_LAST&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;ADDRESS&quot;</span>        sql:field=<span style="color: rgb(0, 96, 128);">&quot;ADDRESS_LINE1&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;CITY&quot;</span>            sql:field=<span style="color: rgb(0, 96, 128);">&quot;CITY&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;STATE&quot;</span>            sql:field=<span style="color: rgb(0, 96, 128);">&quot;ST&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;ZIP&quot;</span>            sql:field=<span style="color: rgb(0, 96, 128);">&quot;ZIP&quot;</span> /&gt;
      &lt;element type=<span style="color: rgb(0, 96, 128);">&quot;DOB&quot;</span>            sql:field=<span style="color: rgb(0, 96, 128);">&quot;BIRTH_DT&quot;</span> /&gt;
   &lt;/ElementType&gt;

&lt;/Schema&gt;</pre>
</div>
<div>&nbsp;</div>
<p><strong>Result</strong></p>
<p>The result is a database with a newly created &quot;PERSON&quot; table and the data from the data file above.</p>
<p><strong><em>Database Summary from SQL Server 2005</em></strong></p>
<p><a href="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SQLServerDatabaseSummary2_2.jpg"><img alt="SQLServerDatabaseSummary2" border="0" height="111" src="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SQLServerDatabaseSummary2_thumb.jpg" style="border-width: 0px;" width="642" /></a></p>
<p><strong><em>PERSON Table after execution Loader Application</em></strong></p>
<p><a href="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SQLServerTableData3_2.jpg"><img alt="SQLServerTableData3" border="0" height="108" src="http://www.wijix.com/image.axd?picture=WindowsLiveWriter/BulkLoadingXMLintoSQLServer2005using.NET_BCA7/SQLServerTableData3_thumb.jpg" style="border-width: 0px;" width="644" /></a></p>
<p><strong>Brad Merrell</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.allfreetech.com/database/sql-server/bulk-loading-xml-into-sql-server-2005-using-net-25.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

