<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8567031383628107211</id><updated>2011-11-27T16:54:05.341-08:00</updated><category term='SQL Server 2005 SSIS Cubes Schemas Pivot tables'/><title type='text'>SQL Server 2005</title><subtitle type='html'>You see things; and you say 'Why?' But I dream things that never were; and I say 'Why not?'</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>48</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-3209767984737918307</id><published>2009-11-04T20:11:00.000-08:00</published><updated>2009-11-04T20:17:08.490-08:00</updated><title type='text'>Recovery Models and backup</title><content type='html'>&lt;h2&gt;Backups &lt;/h2&gt; &lt;p&gt;Microsoft, in SQL Server Books Online, defines backups as:&lt;/p&gt; &lt;p&gt;&lt;i&gt;A copy of data that is used to restore and recover data after a system failure&lt;/i&gt;&lt;/p&gt; &lt;p&gt;SQL Backups can be created a number of ways and can incorporate all or some of the data, as well as some part of the transaction log. While this article is focused on 2005 syntax, most of the concepts are applicable to 2000. This is a huge topic. At best, I'm going to scratch the surface and give you enough information so you won't start crying again. After reading this, you should be able to set up a reasonable set of backups for your system.&lt;/p&gt; &lt;h2&gt;Recovery Models &lt;/h2&gt; &lt;p&gt;In order to begin working on backups, the business needs define a database recovery model. In essence, a &lt;b&gt;recovery&lt;/b&gt; &lt;b&gt;model&lt;/b&gt; defines what you're going to do with the transaction log data. &lt;/p&gt; &lt;p&gt;There are three recovery models: &lt;b&gt;Ful&lt;/b&gt;l, &lt;b&gt;Simple&lt;/b&gt; and &lt;b&gt;Bulk Logged&lt;/b&gt;. These are pretty easy to define:&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;b&gt;Simple&lt;/b&gt; –&lt;b&gt; &lt;/b&gt;in simple recovery mode, the transaction log is not backed up so you can only recover to the most recent full or differential backup. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Full&lt;/b&gt; – in full recovery mode you backup the database and the transaction log so that you can recover the database to any point in time. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Bulk Logged &lt;/b&gt;– in bulk logged mode, most transactions are stored in the transaction log, but some bulk operations such as bulk loads or index creation are not logged.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The two most commonly used modes are &lt;b&gt;Simple&lt;/b&gt; and &lt;b&gt;Full&lt;/b&gt;. Don't necessarily assume that, of course, you always need to use Full recovery to protect your data. It is a business decision. The business is going to tell you if you need to recover to a point in time or if you simply need the last full backup. It's going to define if your data is recoverable by other means, such as manual entry, or if you have to protect as much as possible as it comes across the wire. You use Simple recovery if you can afford to lose the data stored since the last full or differential backup and/or you just don't need recovery to a point in time. In Simple mode, you must restore &lt;i&gt;all&lt;/i&gt; secondary read/write file groups when you restore the primary. You use Simple mostly on secondary databases that are not an absolute vital part of the enterprise or reporting systems, with read only access so there isn't a transaction log to worry about anyway. You use Full if every bit of the data is vital, you need to recover to a point in time or, usually in the case of very large databases (VLDB), you need to restore individual files and file groups independently of other files and file groups.&lt;/p&gt; &lt;p&gt;With both Simple and full recovery models, you can now run a &lt;b&gt;Copy-Only backup&lt;/b&gt; which allows you to copy the database to a backup file, but doesn't affect the log, differential backup schedules or impact recovery to a point in time. I'll try to drill down on as many of these topics as possible through the article, but not the files and filegroups.&lt;/p&gt; &lt;h2&gt;Working with Simple Recovery &lt;/h2&gt; &lt;p&gt;Enough talk. Let's get down to running backups. Let's assume that we're in Simple recovery on a small to mid-sized database. I'm going to use AdventureWorks for all the sample scripts. To set it to simple recovery:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;ALTER DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;SET &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;RECOVERY SIMPLE&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Your simplest backup strategy is to run, at regular intervals, the following SQL Server backup command, which will perform a full backup of the database:&lt;/p&gt;&lt;pre&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New';" lang="EN-US"&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;BACKUP DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\AdventureWorks.BAK'&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/span&gt;&lt;/pre&gt; &lt;p&gt;What's with all the typing you ask? Don't we have GUI tools to handle the work for us? Yes, most simple backups can be performed using SQL Server Management Studio. However, if you want to learn and understand what Management Studio is doing for you, or if you want some fine grained control over what is backed up, how and where, then you're going to have to break out the keyboard and put away the mouse.&lt;/p&gt; &lt;p&gt;The above command will precipitate a basic backup to disk. Most DBAs I know backup to file and then scrape the files onto a tape or some other media. This is because files on disk are simple and quick to recover, whereas media can sometimes be a bit of a pain. For example, we generally have two to three days worth of backups on our file systems for immediate recovery. We only go to the tape systems if we need to run restores for older backups.&lt;/p&gt; &lt;p&gt;What did that command do? It made a copy of all the committed data in the database. It also copied uncommitted log entries. These are used during recovery to either commit or rollback changes that occurred to the data during the backup process.&lt;/p&gt; &lt;h3&gt;Copy-only backups&lt;/h3&gt; &lt;p&gt;Normally, backing up a database affects other backup and restore processes. For example after running the previous command, any differential backups (a backup that only copies data changed since the last backup) would be using this as the starting point for data changes, not the backup you ran last night. As noted earlier, SQL 2005 introduces a new concept to backups, &lt;b&gt;COPY_ONLY&lt;/b&gt; backups, which allow us to keep from interrupting the cycle:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;BACKUP DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\AdventureWorks.bak'  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;COPY_ONLY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Already we've found one of those more granular moments when the Management Studio wouldn't help you. If you want a copy only backup, you have to use the command line.&lt;/p&gt; &lt;h3&gt;Differential backups&lt;/h3&gt; &lt;p&gt;Let's assume for a moment, that we're still in simple recovery, but we're dealing with a larger database, say something above 100 GB in size. Full backups can actually start to slow down the process a bit. Instead, after consultation with the business, we've decided to do a weekly full backup and daily differential backups. &lt;b&gt;Differential&lt;/b&gt; backups only backup the data pages that have changed since the last &lt;b&gt;full&lt;/b&gt; backup. Following is the SQL backup command to perform a differential backup:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;BACKUP DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\backups\AdventureWorks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;DIFFERENTIAL&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Now, if we had to restore this database, we'd first go to the last full backup, restore that, and then restore the differential backups in order (more on that later).&lt;/p&gt; &lt;p&gt;You might have noticed, if you're trying these commands out as you go along, that we have not been changing the backup file names each time. Yet we haven't run into any errors. When running backups as we've done, SQL Server treats the file like a backup device and simply keeps appending the backups to the file.&lt;/p&gt; &lt;p&gt; &lt;img title="Figure 1" src="http://www.simple-talk.com/iwritefor/articlefiles/322-image001.gif" border="0" /&gt;&lt;/p&gt; &lt;p&gt;If you want to simply overwrite the existing file you'll need to modify your backup statements:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;BACKUP DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\backups\AdventureWorks.bak'  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;INIT&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;There are a number of other backup options that I won't be detailing here. Read the books online to see details on &lt;b&gt;BLOCKSIZE&lt;/b&gt;, &lt;b&gt;EXPIREDATE&lt;/b&gt;, &lt;b&gt;RETAINDAYS&lt;/b&gt;, &lt;b&gt;PASSWORD&lt;/b&gt;, &lt;b&gt;NAME&lt;/b&gt;, &lt;b&gt;STATS&lt;/b&gt;, and so on.&lt;/p&gt; &lt;p&gt;You can also run a statement that will check the integrity of a database backup. It doesn't check the integrity of the data within a backup, but it does verify that the backup is formatted correctly and accessible.&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;VERIFYONLY  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\backups\Adventureworks.bak'&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;h2&gt;Full recovery and log backups &lt;/h2&gt; &lt;p&gt;We've primarily been working on a database that was in Simple recovery mode (this used to be called &lt;b&gt;Truncate Log on Checkpoint&lt;/b&gt;). In this mode, we do not backup the transaction logs for later recovery. Every backup under this mechanism is a database backup. Log backups are simply not possible.&lt;/p&gt; &lt;p&gt;However, you've only protected the data as of the last good backup, either full or differential. Let's change our assumptions. Now we're dealing with a large, mission critical application and database. We want to be able to recover this database up to the latest minute. This is a very important point. In theory, since the log entries are being stored and backed up, we're protected up to the point of any failure. However, some failures can cause corruption of the log, making recovery to a point in time impossible. So, we have to determine what the reasonable minimum time between log backups will be. In this case we can live with no more than 15 minutes worth of lost data.&lt;/p&gt; &lt;p&gt;So, let's start by putting our database in &lt;strong&gt;FULL&lt;/strong&gt; recovery mode:&lt;/p&gt;&lt;pre&gt;&lt;p class="Code" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;span style="color: blue;" lang="EN-US"&gt;ALTER DATABASE &lt;/span&gt;&lt;span style="color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;span style="color: blue;" lang="EN-US"&gt;SET &lt;/span&gt;&lt;span style="color: black;" lang="EN-US"&gt;RECOVERY &lt;/span&gt;&lt;span style="color: blue;" lang="EN-US"&gt;FULL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Then, on a scheduled basis, in this case every 15 minutes, we'll run the SQL backup command for the transaction log:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;BACKUP &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;LOG &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\backups\AdventureWorks_Log.bak'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;This script will backup committed transactions from the transaction log. It has markers in the file that show the start and stop time. It will truncate the log when it successfully completes, cleaning out from the transaction log the committed transactions that have been written to the backup file. If necessary, you can use the &lt;b&gt;WITH&lt;/b&gt; &lt;b&gt;NO_TRUNCATE&lt;/b&gt; statement to capture data from the transaction log regardless of the state of the database, assuming it's online and not in an &lt;b&gt;EMERGENCY&lt;/b&gt; status. This is for emergencies only.&lt;/p&gt; &lt;p&gt;Note that we are not using the &lt;b&gt;INIT&lt;/b&gt; statement in this case, but you can do so if you choose. When doing log backups, you've got options:&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;Run all the backups to a single file, where they'll stack and all you have to do, on restore (covered later), is cycle through them. &lt;/li&gt;&lt;li&gt;Name the backups uniquely, probably using date and time in the string.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;In that latter case, safety says, use &lt;b&gt;INIT &lt;/b&gt;because you're exercising maximum control over what gets backed up where, and you'll be able to know exactly what a backup is, when it was taken and from where based on the name. This is yet another place where operating backups from the command line gives you more control than the GUI. We've used both approaches in our systems for different reasons. You can decide what is best for your technology and business requirements.&lt;/p&gt; &lt;p&gt;Most of the options available to the database backup are included in Log backup, including &lt;b&gt;COPY_ONLY&lt;/b&gt;. This would allow you to capture a set of transaction data without affecting the log or the next scheduled log backup. This would be handy for taking production data to another system for troubleshooting etc.&lt;/p&gt; &lt;p&gt;If you have your database set to &lt;strong&gt;FULL&lt;/strong&gt; Recovery, you need to run log backups. Sometimes, people forget and the transaction log grows to the point that it fills up the disk drive. In this case, you can run:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;BACKUP &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;LOG &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NO_LOG&lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New';" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Attaching &lt;b&gt;NO_LOG&lt;/b&gt; to the log backup, and not specifying a location for the log, causes the inactive part of the log to be removed and it does this without a log entry itself, thus defeating the full disk drive. This is absolutely not recommended because it breaks the log chain, the series of log backups from which you would recover your database to a point in time. Microsoft recommends running a full backup immediately after using this statement. Further, they're warning that this statement may be deprecated in a future release.&lt;/p&gt; &lt;h2&gt;Restoring Databases &lt;/h2&gt; &lt;p&gt;As important as SQL Server backups are, and they are vital, they are useless without the ability to restore the database.&lt;/p&gt; &lt;h3&gt;Restoring a full database backup &lt;/h3&gt; &lt;p&gt;Restoring a full database backup is as simple as it was to create:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backup\AdventureWorks.bak'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;It's really that simple – unless, as we did originally, we are backing up everything to a file as if it were a backup device. In that case, you'll need to specify which file within the "device" you're accessing. If you don't know which file, you'll need to generate a list:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;HEADERONLY &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backup\Adventureworks.bak'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;This will give you the same list as I showed above from Management Studio. So now, if we wanted to restore the second file in the group, the &lt;b&gt;COPY_ONLY&lt;/b&gt; backup, you would issue the following command:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backup\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;2&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Unfortunately, if you're following along, you may find that you just generated this error:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New';" lang="EN-US"&gt;Msg 3159, Level 16, State 1, Line 1&lt;br /&gt;The tail of the log for the database "AdventureWorks" has not been backed up.&lt;br /&gt;Use BACKUP LOG WITH NORECOVERY to backup the log if it contains work you do&lt;br /&gt;not want to lose. Use the WITH REPLACE or WITH STOPAT clause of the RESTORE&lt;br /&gt;statement to just overwrite the contents of the log.&lt;br /&gt;Msg 3013, Level 16, State 1, Line 1&lt;br /&gt;RESTORE DATABASE is terminating abnormally.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;What this means is, that your database is in full recovery mode, but you haven't backed up the "tail of the log", meaning the transactions entered since the last time you ran a backup. You can override this requirement if you change the previous syntax to:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;2&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;REPLACE&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;That's the first time we've stacked the &lt;b&gt;WITH&lt;/b&gt; clauses (&lt;b&gt;WITH FILE=2&lt;/b&gt; and &lt;b&gt;WITH REPLACE&lt;/b&gt; is represented as &lt;b&gt;WITH FILE=2, REPLACE&lt;/b&gt;), but it won't be the last. Read through the books online. Most of the &lt;b&gt;WITH&lt;/b&gt; clause statements can be used in combination with the others.&lt;/p&gt; &lt;p&gt;What happens if we want to restore to a different database than the original? For example, we want to make a copy of our database from a separate backup. Maybe we want to move it down to a production support server where we are going to do some work on it, separate from the production copy of the database. If we take the simple approach, well, try this:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks_2 &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;2&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;In this case, you should see a whole series of errors relating to files not being overwritten. You really can create new databases from backups, but if you're doing it on a server with the existing database, you'll need to change the location of the physical files using the logical names. In order to know the logical names of the files for a given database, run this prior to attempting to move the files:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;FILELISTONLY &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;2&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;This can then be used to identify the appropriate logical names in order to generate this script:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks_2 &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;2&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;MOVE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'AdventureWorks_Data' &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\backups\aw2_data.mdf'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;MOVE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'AdventureWorks_Log' &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;TO &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\backups\aw2_log.ldf'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;h3&gt;Restoring a differential backup &lt;/h3&gt; &lt;p&gt;The last method is to apply the differential backup. This requires two steps. First, we'll restore the database, but with a twist and then we'll apply the differential backup:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;1&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NORECOVERY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;REPLACE&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;  &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\AdventureWorks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;3&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Most of this is probably self-explanatory based on what we've already covered. The one wrinkle is the inclusion of the &lt;b&gt;NORECOVERY&lt;/b&gt; keyword. Very simply, during a restore, transactions may have started during the backup process. Some of them complete and some don't. At the end of a restore, completed transactions are rolled forward into the database and incomplete transactions are rolled back. Setting &lt;b&gt;NORECOVERY&lt;/b&gt; keeps transactions open. This allows for the next set of transactions to be picked up from the next backup in order.&lt;/p&gt; &lt;p&gt;We're mainly dealing with simple backups and restores in this article, but a more advanced restore in 2005 allows secondary file groups to be restored while the database is online. Its primary file group must be online during the operation. This will be more helpful for very large database systems.&lt;/p&gt; &lt;h3&gt;Restoring SQL Server databases to a point in time &lt;/h3&gt; &lt;p&gt;Restoring logs is not much more difficult than the differential database restore that we just completed. There's just quite a bit more involved in restoring to a moment in time. Assuming you're backing up your logs to a single file or device:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;HEADERONLY &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks_log.bak'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Otherwise, you simply go and get the file names you need. First run the database restore, taking care to leave it in a non-recovered state. Follow this up with a series of log restores to a point in time.&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;1&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NORECOVERY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;REPLACE&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;STOPAT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'Oct 23, 2006 14:30:29.000'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;; &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;LOG &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks_log.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;1&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NORECOVERY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;STOPAT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'Oct 23, 2006 14:30:29.000'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;; &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;LOG &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks_log.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;2&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NORECOVERY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;STOPAT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'Oct 23, 2006 14:30:29.000'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;; &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;LOG &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks_log.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;3&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NORECOVERY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;STOPAT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'Oct 23, 2006 14:30:29.000'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;; &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: fuchsia;" lang="EN-US"&gt;LOG &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM DISK = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\Adventureworks_log.bak' &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: red; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH FILE = &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;4&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;, &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;code&gt;   &lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;STOPAT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'Oct 23, 2006 14:30:29.000'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Now what we have is a database that is up to the exact, last committed transaction at 14:30:29 on the 23&lt;sup&gt;rd&lt;/sup&gt; of October. Remember, during multi-step restores such as this, you have to leave the database in a recovering status. That means appending &lt;b&gt;NORECOVERY&lt;/b&gt; to each statement until you've completed the restore process. If for some reason you've added &lt;b&gt;NORECOVERY&lt;/b&gt; to all your statements, or you simply stop in the middle, and would like to bring the database back online, you can use this statement to complete the process:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;WITH &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;RECOVERY&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;h2&gt;Database snapshots &lt;/h2&gt; &lt;p&gt;SQL Server 2005 introduced the concept of a snapshot, or a read-only, static view of a database. Snapshots are primarily created in order to supply a read-only version of a database for reporting purposes. However, they do function in a similar way to backups. The one primary difference is that all uncommitted transactions are rolled back. There is no option for rolling forward, capturing logs, etc., that backups provide, nor are very many SQL Server resources used at all. Rather, disk technology is used to create a copy of the data. Because of this they are much faster than backups both to create and restore. &lt;/p&gt; &lt;p&gt;&lt;b&gt;NOTE&lt;/b&gt;:&lt;br /&gt;&lt;i&gt;For more details on SQL 2005 Snapshot, please refer to &lt;a href="http://www.simple-talk.com/sql/database-administration/sql-server-2005-snapshots/"&gt;http://www.simple-talk.com/sql/database-administration/sql-server-2005-snapshots/&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt; &lt;p&gt;A good use of snapshots, in addition to reporting, might be to create one prior to maintenance after you've already removed all the active users (and their transactions) from the system. While snapshots don't support the volatility of live backups, their speed and ease of recovery make a great tool for quick recovery from a botched rollout. Snapshots are stored on the server, so you must make sure you've got adequate storage.&lt;/p&gt; &lt;p&gt;The syntax is different because you're not backing up a database; you're creating a new one:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;CREATE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks_ss1430 &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;ON &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;(&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;NAME &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks_Data&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;,&lt;br /&gt;&lt;span style=""&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;FILENAME &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: red;" lang="EN-US"&gt;'C:\Backups\AdventureWorks_data_1430.ss'&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;) &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: gray; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;AS &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;SNAPSHOT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;OF &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;AdventureWorks&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Now it will be accessible for read-only access. Since we're primarily concerned with using this as a backup mechanism, let's include the method for reverting a database to a database snapshot.&lt;/p&gt; &lt;p&gt;First, identify the snapshot you wish to use. If there is more than one on any database that you're going to revert, you'll need to delete all except the one you are using:&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;DROP DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks_ss1440&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;Then you can revert the database by running a &lt;b&gt;RESTORE&lt;/b&gt; statement (mixed metaphors, not good):&lt;/p&gt;&lt;pre&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;RESTORE DATABASE &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks &lt;/span&gt;&lt;/code&gt;&lt;span style="font-size: 10pt; color: black; font-family: 'Courier New';" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;FROM &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;DATABASE_SNAPSHOT &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: blue;" lang="EN-US"&gt;= &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: black;" lang="EN-US"&gt;Adventureworks_ss1430&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt; color: gray;" lang="EN-US"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span style="color: rgb(51, 51, 51); font-family: Arial;" lang="EN-US"&gt;  &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt; &lt;p&gt;That's it. On my system, running the database snapshots of Adventureworks took 136 ms. The full backup took 5,670 ms. The restore of the snapshot took 905ms and the database restore took 13,382ms. Incorporating this into a production rollout process could result in significant benefits&lt;/p&gt; &lt;p&gt;Again, it's worth noting that there are some caveats to using the snapshot. You have to have enough disk space for a second copy of the database. You need to be careful dealing with snapshots since most of the syntax is similar to that used by databases themselves. Last, while there are snapshots attached to a database you can not run a restore from a database backup of that database.&lt;/p&gt; &lt;h2&gt;Best practices &lt;/h2&gt; &lt;p&gt;The manner in which you perform database backups should not be a technical decision. It should be dictated by the business. Small systems with low transaction rates and/or reporting systems that are loaded regularly will only ever need a full database backup. Medium sized systems and large systems become dependent on the type of data managed to determine what types of backup are required.&lt;/p&gt; &lt;p&gt;For a medium sized system, a daily backup with log backups during the day would probably answer most data requirements in a timely manner.&lt;/p&gt; &lt;p&gt;For a large database the best approach is to mix and match the backups to ensure maximum recoverability in minimum time. For example, run a weekly full backup. Twice a day during the week, run a differential backup. Every 10 minutes during the day, run a log backup. This gives you a large number of recovery mechanisms.&lt;/p&gt; &lt;p&gt;For very large databases, you'll need to get into running filegroup and file backups because doing a full backup or even a differential backup of the full database may not be possible. A number of additional functions are available to help out in this area, but I won't be going into them here. &lt;/p&gt; &lt;p&gt;You should take the time to develop some scripts for running your backups and restores. A naming convention so you know what database, from which server, from which date, in what specific backup and format will be very conducive to your sanity. A common location for backups, log, full or incremental, should be defined. Everyone responsible should be trained in both backup and recovery and troubleshooting the same. There are many ways of doing this, but you can find a few suggestions in &lt;a href="http://www.simple-talk.com/sql/backup-and-recovery/pop-rivetts-sql-server-faq-no2-pop-backs-up/"&gt;Pop backs up&lt;/a&gt; and &lt;a href="http://www.simple-talk.com/sql/backup-and-recovery/pop-rivetts-sql-server-faq-no.3-pop-restores/"&gt;Pop Restores&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The real test is to run your backup mechanisms and then run a restore. Then try a different type of restore, and another, and another. Be sure that, not only have you done due diligence in defining how to backup the system, but that you've done the extra step of ensuring that you can recover those backups. If you haven't practiced this and documented the practice and then tested the document, in effect, you're not ready for a disaster.&lt;br /&gt;&lt;/p&gt;&lt;script type="text/javascript"&gt;document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1395240&amp;zs=3330305f323530&amp;ifr='+AdBrite_Iframe+'&amp;ref='+AdBrite_Referrer+'" type="text/javascript"&gt;');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));&lt;/script&gt;&lt;br /&gt;&lt;div&gt;&lt;a target="_top" href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1395240&amp;amp;afsid=1" style="font-weight: bold; font-family: Arial; font-size: 13px;"&gt;Your Ad Here&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End: AdBrite --&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-3209767984737918307?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.simple-talk.com/sql/backup-and-recovery/sql-server-2005-backups/' title='Recovery Models and backup'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/3209767984737918307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=3209767984737918307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/3209767984737918307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/3209767984737918307'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/11/recovery-models-and-backup.html' title='Recovery Models and backup'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-4734590837107693600</id><published>2009-09-15T19:55:00.000-07:00</published><updated>2009-10-28T10:41:04.702-07:00</updated><title type='text'>SSIS Design Pattern - Custom Error Handling</title><content type='html'>&lt;span style=";font-family:verdana;color:navy;"  &gt;&lt;p&gt;Error logging is crucial to troubleshooting and auditing efforts. If an error occurs in your SSIS package while it is executing production loads, transformations, or transfers; you will want to know as much as possible about it.&lt;/p&gt; &lt;p&gt;To demonstrate, create a new SSIS project named ErrorTest:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest0.png" /&gt;&lt;/p&gt; &lt;p&gt;I encourage you to develop the practice of renaming packages as you create them. This will make your life simpler once you deploy:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest1.png" /&gt;&lt;/p&gt; &lt;p&gt;I rename Package.dtsx to ErrorTestPkg.dtsx (don't change the extension):&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest2.png" /&gt;&lt;/p&gt; &lt;p&gt;When you rename a package the following dialog will appear:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest3.png" /&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Always answer this dialog "Yes"&lt;/em&gt;.&lt;br /&gt;Drag an Execute SQL Task onto the Control Flow:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest4.png" /&gt;&lt;/p&gt; &lt;p&gt;Configure it (double-click or right-click and select Edit to open the editor) as shown below. Note any connection will suffice, so long as the SQL Server is running. Also note the SQL will generate an exception (intentionally):&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest5.png" /&gt;&lt;/p&gt; &lt;p&gt;Click OK to close the editor. Right-click the Task and select Execute Task to test:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest6.png" /&gt;&lt;/p&gt; &lt;p&gt;The task should fail (as planned):&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest7.png" /&gt;&lt;/p&gt; &lt;p&gt;Stop execution and click on the Event Handlers tab:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest8.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Check to be sure the Executable dropdown is set to the ErrorTestPkg (the package) and the Event handler dropdown is set to OnError. Click the link to create a new OnError Event Handler for the package. From the Toolbox, drag and drop a Data Flow Task onto the Event Handler:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest9.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Double-click the Data Flow Task to edit it. From the toolbox, drag a Script Component transformation onto the Data Flow:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest10.png" /&gt;&lt;/p&gt; &lt;p&gt;The Script Component can be configured as a Source, Transformation, or Destination. Select Source:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest11.png" /&gt;&lt;/p&gt; &lt;p&gt;Since a Source has only outputs (a destination has only inputs, and a transformation has both inputs and outputs), you will need to configure the Output. Rename the generic Output 0 to ErrorOutput:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest12.png" /&gt;&lt;/p&gt; &lt;p&gt;Click on Output Columns and click Add Column:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest13.png" /&gt;&lt;/p&gt; &lt;p&gt;Rename the Column ErrDescription:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest14.png" /&gt;&lt;/p&gt; &lt;p&gt;Edit the ErrDesription column's properties - change the datatype to String (DT_STR) and the length to 5000:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest15.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Add the ErrorDescription System variable to the ReadOnlyVariables property of the Script Component:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest16.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;There are other variables you will add to your error handling script component. Remember variable names are case-sensitive, comma-separated, with no spaces in the list.&lt;/em&gt;&lt;br /&gt;Click the Design Script button and add the following code snippet in the CreateNewOutputRows subroutine as shown below:&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:Courier New;color:black;"  &gt;&lt;br /&gt;       &lt;span style="color:blue;"&gt;With&lt;/span&gt; ErrorOutputBuffer&lt;br /&gt;           .AddRow()&lt;br /&gt;           .ErrDescription = &lt;span style="color:blue;"&gt;Me&lt;/span&gt;.Variables.ErrorDescription&lt;br /&gt;       &lt;span style="color:blue;"&gt;End With&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some explanation: The name of the ErrorOutputBuffer was determined by the name you gave the Script Component Output earlier. When you changed the Output name to ErrorOutput, the script component's output buffer was changed to ErrorOutputBuffer.&lt;br /&gt;&lt;br /&gt;To populate the buffer, you must add rows to it. Think of this as starting a new row in a table. If you're familiar with tables in Microsoft Word documents, you know when you start a new row it is empty until you populate it. The same is true here. You are creating a new, empty row in the output buffer to populate with data.&lt;br /&gt;&lt;br /&gt;The final step is to load the row. Again, in your production-ready error event handler you will populate more columns in the output buffer than this one - this is for demonstration purposes only:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest17.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Next, drag a flat file destination onto the Data Flow and connect it to the Script Component as shown:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest18.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Note: You will likely want to store error data in a database rather than a flat file.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;When you configure a flat file destination, you are prompted for which type of file. Delimited files are fairly simple to read - especially with few fields:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest19.png" /&gt;&lt;/p&gt; &lt;p&gt;Select a location and name for your flat file. I chose C:\ErrorOutput1.txt:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest20.png" /&gt;&lt;/p&gt; &lt;p&gt;Click Columns to view the columns the file will contain. &lt;em&gt;Note: the columns would be empty if you had not connected a data path from the Script Component prior to configuring the Flat File Destination&lt;/em&gt;:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest21.png" /&gt;&lt;/p&gt; &lt;p&gt;Click OK to proceed. Click the Mappings page to assign mappings between fields in the pipeline and fields in the destination: &lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest22.png" /&gt;&lt;/p&gt; &lt;p&gt;Since you built the destination from the metadata contained in the pipeline, auto-mapping should occur when you click Mappings:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest23.png" /&gt;&lt;/p&gt; &lt;p&gt;Click OK. Your Event Handler should appear as shown:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest24.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Start debugging the package by pressing F5 or clicking the Debug Run arow. Your ExecuteSQL task should fail as before: &lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest25.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Click on the Event Handlers tab to determine the run status of your Package OnError Event Handler. Double-click the Data Flow Task and note one row was written to your error file (ErrorOutput1.txt):&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest26.png" width="800" /&gt;&lt;/p&gt; &lt;p&gt;Open ErrorOutput1.txt file to view the error stored there:&lt;/p&gt; &lt;p&gt;&lt;img src="http://vsteamsystemcentral.com/images/ext/ErrorTest27.png" /&gt;&lt;/p&gt; &lt;p&gt;In this example, we built a package to demonstrate logging package errors to a data destination - albeit a flat file. This technique can be used to catch errors and store them for troubleshooting posterity.&lt;/p&gt; &lt;p&gt;&lt;a class="" title="Get this SSIS package!" href="http://www.vsteamsystemcentral.com/dnn/LinkClick.aspx?link=articles%2fErrorTest.zip&amp;amp;tabid=89&amp;amp;mid=388" target="_blank"&gt;Get the code&lt;/a&gt;!&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-4734590837107693600?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://vsteamsystemcentral.com/cs21/blogs/applied_business_intelligence/archive/2007/04/08/ssis-design-pattern-custom-error-handling.aspx' title='SSIS Design Pattern - Custom Error Handling'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/4734590837107693600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=4734590837107693600' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/4734590837107693600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/4734590837107693600'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/09/ssis-design-pattern-custom-error.html' title='SSIS Design Pattern - Custom Error Handling'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-3919458807744542909</id><published>2009-09-10T20:40:00.000-07:00</published><updated>2009-09-10T20:41:18.490-07:00</updated><title type='text'>DTS vs SSIS</title><content type='html'>&lt;p&gt;In today’s blog post, we will give a basic introduction of SSIS (SQL Server Integration Services) and provide a comparison of some of those features with DTS (Data Transformation Services), it’s predecessor.&lt;/p&gt; &lt;p&gt;SSIS is an ETL tool provided by Microsoft for extracting the data from various sources, transforming the data according to the business requirements and loading the data into the destination. The source and the destination could be anything that you can talk to using a connection. One important thing to understand is that SQL Server Integration Services (SSIS) is a component of Microsoft SQL Server 2005 and is not a separate install. Integration Services includes graphical tools and wizards for building and debugging packages, tasks for performing workflow functions such as FTP operations, for executing SQL statements, or for sending e-mail messages, data sources and destinations for extracting and loading data, transformations for cleaning, aggregating, merging, and copying data.&lt;/p&gt; &lt;p&gt;In SQL Server 2000, DTS packages are created in Enterprise Manager. The DTS packages are created in the DTS designer and you have the option of saving them in SQL Server or saving them to the filesystem (by specifying the location as “Structured Storage File”). In Integration Services, the packages are created using Business Intelligence Development Studio (BIDS). BIDS is nothing but another version of Microsoft Visual Studio. It is a modified version of Visual Studio.  When we create Integration Services packages using BIDS, they are saved on the client machine (local machine). We have to explicitly deploy the Integration Services Packages onto the destination server.&lt;/p&gt; &lt;p&gt;The following steps show how you can launch BIDS:&lt;/p&gt; &lt;p&gt;Go to: &lt;b&gt;&lt;i&gt;Start –&gt; All Programs –&gt; Microsoft Sql Server 2005 –&gt; Business Intelligence Development Studio&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_1.jpg" title="ssis_1.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_1.thumbnail.jpg" alt="ssis_1.jpg" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The basic organization concept in DTS as well as SSIS is the concept of a package. A package is essentially a collection of SSIS objects which includes:&lt;/p&gt; &lt;p&gt;a)    Connections to the data sources,&lt;br /&gt;b)    Data Flows,&lt;br /&gt;c)    Control Flows, and&lt;br /&gt;d)    Event Handlers&lt;/p&gt; &lt;p&gt;We will discuss these shortly.  Let’s first look at the DTS Package Designer and BIDS to get an idea of the IDE layout.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Package Design Pane&lt;/b&gt;:&lt;/p&gt; &lt;p&gt;The following images show the DTS and SSIS design panes respectively.&lt;br /&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_2.jpg" title="ssis_2.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_2.thumbnail.jpg" alt="ssis_2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_3.jpg" title="ssis_3.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_3.thumbnail.jpg" alt="ssis_3.jpg" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The striking difference when one sees both the designers is the way the designer is designed.&lt;/p&gt; &lt;p&gt;In DTS, the designer consists of a single pane. And to the right we see two options: the Connections and the Workflow tasks. The Connections are used to make the connections to a wide variety of data sources and destinations like Excel, Flat Files, Sql Server and Access essentially anything that we have an ODBC, OLEDB, Jet driver etc. connectivity to. The Work Flow tasks add the functionality to the package. The thick line or what we call the data transformation task between the source and the destination in the above example transforms the data and loads into the destination. One can write custom code for the transformations or simply use the inbuilt capabilities of the data transformation task.&lt;/p&gt; &lt;p&gt;In SSIS, the designer is split into 4 design panes:&lt;br /&gt;a)    Control Flow,&lt;br /&gt;b)    Data Flow,&lt;br /&gt;c)    Event Handlers, and&lt;br /&gt;d)    Package Explorer.&lt;/p&gt; &lt;p&gt;The &lt;b&gt;control flow&lt;/b&gt; pane is used to design the workflow inside the package. There is also a great improvement in the number of tasks and additional functionality has been added to some of the existing tasks. The control flow is like a program flow. All the workflow tasks in the DTS come under the Control Flow tasks in SSIS except the Data Transformation Task.&lt;/p&gt; &lt;p&gt;The Data Transformation Task in DTS has been converted into &lt;b&gt;Data Flow&lt;/b&gt; task. As the name suggests, the Data Flow task handles the flow of data. Microsoft has introduced a wide variety of data flow tasks in SSIS for building an entire ETL. All the data transformation from the source to the destination takes place in this Data Flow task. Examples of Data Flow Task are Multicast, OLEDB Command, Sort transformation, Pivot transformation, Unpivot transformation etc.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Event Handlers&lt;/b&gt; is something new to SSIS. Event handlers respond to various events raised in the package like on error, on warning, on pre execute and on post execute. When an event is raised then the control goes to the Event Handler Pane, and the package does whatever is instructed in the Event Handler Pane. Again Event Handlers Contain the Control Flow Tasks because Control Flow determines the workflow of the package.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Package Explorer&lt;/b&gt; is also a new pane in SSIS. It gives the overall view of the package.&lt;/p&gt; &lt;p&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_4.jpg" title="ssis_4.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_4.thumbnail.jpg" alt="ssis_4.jpg" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The image shown above shows the package explorer. As said earlier, the package explorer gives the over all gist of the entire package like Executables, Precedence Constraints, Connection Managers, Event Handlers and the Variables. Precedence Constraints and Connection Managers are described later in the post.&lt;/p&gt; &lt;p&gt;&lt;b&gt;The Solution Explorer&lt;/b&gt;:&lt;/p&gt; &lt;p&gt;The Solution Explorer is also a new concept in SSIS. The solution explorer consists of the SSIS packages, connections and Data Source Views (DSV). The solution contains a series of projects. Each project contains a series of objects used in the projects. In DTS we were allowed to create only independent packages. There was no possibility to store the related packages of the module in a single place. The Solution Explorer allows us to do that. We can have multiple packages relation to one module in a single Solution.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Data Source View (DSV)&lt;/b&gt;&lt;/p&gt; &lt;p&gt;This is also new to SSIS. A data source view is a document that describes the schema of an underlying data source. A data source view provides a named, browseable, persisted selection of database objects that can be used to define sources, destinations, and lookup tables for SQL Server 2005 Integration Services (SSIS) tasks, transformations, data sources, and destinations. Example: In some ERPs like SAP or even in some databases, the columns might be named like A0012, A0013, AABE etc. Naming the columns this way is typically done by some designers for obfuscation (especially in packaged applications) but does not help the SSIS developers. As far as the SSIS developer is concerned it is just another column on which data transformations have to be applied. In this case we can create a data source view over this data source and can rename the columns in some meaningful way by not renaming the columns in the data source. In other words we are overlapping the table with another transparent table with change in the column names. So we see the column names of the transparent table and the data of the original table.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Connection Managers&lt;/b&gt;:&lt;/p&gt; &lt;p&gt;Connection Manager is also something new in SSIS. To understand this let us consider the following screen shot of DTS.&lt;/p&gt; &lt;p&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_5.jpg" title="ssis_5.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_5.thumbnail.jpg" alt="ssis_5.jpg" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this package we see two connections. The first one is to the database on the left and the other one is to the text file on the right. What happens when we move this package from one environment to another for example from development to QA? The connections to the databases and the file locations change. Therefore we have to open up each package and then each connection to configure it to point to the intended environment. Typically each DTS package might contain up to 5-10 connections. And when we are moving a large number of packages from one environment to another it becomes cumbersome. Please do note that this can easily be overcome by using dynamic properties and disconnected edits in DTS and we can either pick up the connection information from a file at run-time or even from a configuration table from a database but one needed to code for it or the configuration wasn’t that straight forward.&lt;/p&gt; &lt;p&gt;Now, let’s see how the connection manager helps in making this process easy in SSIS. Let us understand this with the help of an SSIS example shown in the image below:&lt;/p&gt; &lt;p&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_6.jpg" title="ssis_6.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_6.thumbnail.jpg" alt="ssis_6.jpg" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In the above package we see two connections and one database connection. In SSIS, we have a centralized place where we can configure the connection to a particular data source or data destination called connection managers. All the connections inside the package make use of these connection managers to make the connection to the data sources and data destinations. As in DTS, SSIS also provides a wide variety of connection managers to make connections to a variety of sources and destinations. So when moving from one environment to another, we should open up the SSIS package and just make the change only in one place, which are the connection managers as opposed to multiple places as in DTS. This saves us time and also is less cumbersome. In a little while we will see how to dynamically alter the connections even without opening up the packages. This is done with Configurations.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Variables&lt;/b&gt;:&lt;/p&gt; &lt;p&gt;Variables are a powerful piece of the SSIS architecture; they allow you to dynamically control the package at runtime. There are two types of variables: system and user. System variables are ones that are built into SSIS, whereas user variables are created by the SSIS developer. Variables can also have varying scope, with the default scope being the entire package. They can also be set to be in scope of a container, task, or event handler inside the package. The addition of scope to variables is the main differentiating factor between SSIS variables and DTS global variables.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Configurations&lt;/b&gt;:&lt;/p&gt; &lt;p&gt;SSIS provides us with a way of altering the connection information and also the variable values at run time. This is done by using the Configuration Files. The following screen shot shows us how to open up the configuration editor in SSIS.&lt;/p&gt; &lt;p&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_7.jpg" title="ssis_7.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_7.thumbnail.jpg" alt="ssis_7.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://decipherinfosys.files.wordpress.com/2008/03/ssis_8.jpg" title="ssis_8.jpg"&gt;&lt;img src="http://decipherinfosys.files.wordpress.com/2008/03/ssis_8.thumbnail.jpg" alt="ssis_8.jpg" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Right click on the control flow pane and click on the Configurations menu. This will open up the configuration wizard. This is also something which did not exist in the DTS. We will explore more of package configurations and how to create configuration files in the upcoming posts.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Transactions&lt;/b&gt;:&lt;/p&gt; &lt;p&gt;All Microsoft SQL Server 2005 Integration Services (SSIS) container types—packages, the For Loop, For each Loop, and Sequence containers, and the task hosts that encapsulate each task—can be configured to use transactions. Integration Services provides three options for configuring transactions: NotSupported, Supported, and Required.&lt;/p&gt; &lt;p&gt;•    &lt;b&gt;Required&lt;/b&gt; indicates that the container starts a transaction, unless one is already started by its parent container. If a transaction already exists, the container joins the transaction&lt;br /&gt;•    &lt;b&gt;Supported&lt;/b&gt; indicates that the container does not start a transaction, but joins any transaction started by its parent container. For example, if a package with four Execute SQL tasks starts a transaction and all four tasks use the Supported option, the database updates performed by the Execute SQL tasks are rolled back if any task fails. If the package does not start a transaction, the four Execute SQL tasks are not bound by a transaction, and no database updates except the ones performed by the failed task are rolled back.&lt;br /&gt;•    &lt;b&gt;NotSupported&lt;/b&gt; indicates that the container does not start a transaction or join an existing transaction. A transaction started by a parent container does not affect child containers that have been configured to not support transactions. For example, if a package is configured to start a transaction and a For Loop container in the package uses the NotSupported option, none of the tasks in the For Loop can roll back if they fail.&lt;/p&gt; &lt;p&gt;In this post, we covered a brief introduction to SSIS, its important features and how SSIS differs from its predecessor: DTS. In future posts, we will discuss each task in detail and will also cover the best practices as well as go into the usage of SSIS in building up business intelligence applications like explaining how to handle slowly changing dimensions etc..&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-3919458807744542909?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://decipherinfosys.wordpress.com/2008/03/11/dts-vs-ssis-a-basic-overview/' title='DTS vs SSIS'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/3919458807744542909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=3919458807744542909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/3919458807744542909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/3919458807744542909'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/09/dts-vs-ssis.html' title='DTS vs SSIS'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8000272603776314003</id><published>2009-09-10T20:35:00.001-07:00</published><updated>2009-09-10T20:35:53.400-07:00</updated><title type='text'>Deploying Reports</title><content type='html'>&lt;h3 class="section"&gt;Introduction&lt;/h3&gt; &lt;p&gt;Tight integration with the .NET environment is the important feature for the popularity of Microsoft SQL Server 2005. As a result, it is possible to perform the some of the common tasks by using different options. This allows the developers/administrators to do their work by selecting the options that they are comfortable with. For example, you can manage/administer the report sever using the SQL Server Management Studio OR the web-based Report Manager. In this article, will look at the various ways for deploying reports on the report server. [It is assumed that the reports are already created]  &lt;/p&gt;&lt;h3 class="section"&gt;How to deploy reports? &lt;/h3&gt; It is possible to deploy the reports in 3 ways: &lt;ul&gt;&lt;li&gt;Using the BI Development studio. &lt;/li&gt;&lt;li&gt;Using the SQL Server Management Studio. &lt;/li&gt;&lt;li&gt;Programmatically. [Using the RS.EXE utility] &lt;/li&gt;&lt;/ul&gt;  &lt;b&gt;Using BI Development studio:&lt;/b&gt; &lt;ol&gt;&lt;li&gt;Open the Project Properties dialog-box and set the TargetServerURL. It is the URL of the report server, on which the reports will be deployed. [Figure 1]&lt;br /&gt;&lt;img src="http://www.sqlservercentral.com/articles/Administration/2967/DeployingReports/image002.jpg" width="576" height="178" /&gt;&lt;br /&gt;[Figure 1]&lt;br /&gt; &lt;/li&gt;&lt;li&gt;Right-Click on the Project and select Deploy [Figure 2]. This will deploy the reports and Data-sources defined in the project on the specified report server.&lt;br /&gt;&lt;img src="http://www.sqlservercentral.com/articles/Administration/2967/DeployingReports/image003.jpg" width="312" height="182" /&gt;&lt;br /&gt;[Figure 2]&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt; &lt;b&gt;Using SQL Server Management Studio:&lt;/b&gt; &lt;ol&gt;&lt;li&gt;Connect to the Reporting services database. &lt;/li&gt;&lt;li&gt;Right-click on Home and select the desired options. [Figure3]&lt;br /&gt;&lt;img src="http://www.sqlservercentral.com/articles/Administration/2967/DeployingReports/image004.jpg" width="235" height="70" /&gt;&lt;br /&gt;[Figure 3] &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Select New Folder to create a new folder on the server. Select New Data Source option for defining a data-source for the reports. Select Import File for adding/deploying the reports on the server. &lt;/p&gt;&lt;p&gt; &lt;b&gt;Using the RS.EXE utility:&lt;/b&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;It is a Command-line utility. &lt;/li&gt;&lt;li&gt;Used for performing Deployment and Administrative tasks programmatically. &lt;/li&gt;&lt;li&gt;Executes the &lt;b&gt;RSS&lt;/b&gt; file. [Reporting Services Script file] &lt;/li&gt;&lt;li&gt;Command to execute:&lt;br /&gt;&lt;pre class="code"&gt;rs i MyRSS.rss -s http://localhost/reportserver&lt;br /&gt;&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Parameters can also be passed. These parameters are the global variables in the RSS script file. Multiple parameters can be passed.&lt;br /&gt;For example:&lt;br /&gt;&lt;pre class="code"&gt;rs i MyRSS.rss -s http://localhost/reportserver -v param1="value1" -v param2="value2" &lt;/pre&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;b&gt;How to write the RSS file:&lt;/b&gt; &lt;ul&gt;&lt;li&gt;VB.NET code file [with rss extension]. &lt;/li&gt;&lt;li&gt;Can contain user-defined function and global parameters. The value for the global parameters has to be supplied from the command line. &lt;/li&gt;&lt;li&gt;It should have a Main () procedure. &lt;/li&gt;&lt;li&gt;By default, the namespaces System.IO, System.Xml and System.Web.Services are included. &lt;/li&gt;&lt;li&gt;A reference variable &lt;b&gt;rs&lt;/b&gt; for the reporting services web service is generated automatically when the script is executed using the RS.EXE utility. This variable allows access to all the functionality of web service class library [of reporting services]. &lt;/li&gt;&lt;/ul&gt;  &lt;h3 class="section"&gt;Sample code:&lt;/h3&gt; Extract the &lt;a href="http://www.sqlservercentral.com/articles/Administration/2967/DeployingReports/MyReport.zip"&gt;MyReport.zip&lt;/a&gt; file in the D\MyReports folder. &lt;p&gt;The sample RSS file creates a data-source, which points to the Northwind database on the (local) sql server instance using Windows authentication. The function used is: CreateDataSource(&lt;i&gt;name&lt;/i&gt;, &lt;i&gt;extension&lt;/i&gt;, &lt;i&gt;connectionstring&lt;/i&gt;)&lt;br /&gt;&lt;br /&gt;Example: &lt;/p&gt;&lt;pre class="code"&gt;CreateDataSource("MyDataSource", "SQL", "Data Source= (local);Initial Catalog=Northwind")&lt;/pre&gt;  &lt;p&gt;It also publishes a sample report using the CreateReport function.&lt;br /&gt;CreateReport(&lt;i&gt;NameofReport&lt;/i&gt;, &lt;i&gt;ParentFolder&lt;/i&gt;, &lt;i&gt;Overwrite&lt;/i&gt;, &lt;i&gt;ReportDefinition&lt;/i&gt;, &lt;i&gt;Properties&lt;/i&gt;)&lt;br /&gt;&lt;br /&gt; Example: &lt;/p&gt;&lt;pre class="code"&gt;CreateReport(MyReport, /MyReports, False, definition, Nothing)&lt;/pre&gt;  &lt;p&gt;If report contains any external images, then it has to be also deployed as a resource. This is not required if the image is embedded in the report. The function used is: CreateResource(&lt;i&gt;ImageName&lt;/i&gt;, &lt;i&gt;ParentFolder&lt;/i&gt;, &lt;i&gt;Overwrite&lt;/i&gt;, &lt;i&gt;Definition&lt;/i&gt;, &lt;i&gt;MIME type&lt;/i&gt;, &lt;i&gt;Properties&lt;/i&gt;)&lt;br /&gt;&lt;br /&gt; Example: &lt;/p&gt;&lt;pre class="code"&gt;CreateResource(ImageName, parentPath, False, definition, "image/jpeg",Nothing)&lt;/pre&gt;  For executing the rss file, open the command prompt and set the directory to D:\MyReports and run the following command:&lt;br /&gt;&lt;pre class="code"&gt;rs -i MyRSS.rss -s http://localhost/ReportServer&lt;/pre&gt;  &lt;p&gt;Output will look like:&lt;br /&gt;&lt;img src="http://www.sqlservercentral.com/articles/Administration/2967/DeployingReports/image006.jpg" width="576" border="0" height="107" /&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;After successful execution, MyReports folder will be created on the report server. It can be viewed using the Report Manager.  &lt;/p&gt;&lt;h3 class="section"&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;The reports can be deployed using the above 3 methods. Reporting Services script files can be used to run any of the Report Server Web service operations like creating schedules, subscriptions, security settings, etc. Replicating report server would be easy using the Reporting Services script file. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8000272603776314003?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.sqlservercentral.com/articles/Administration/2967/' title='Deploying Reports'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8000272603776314003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8000272603776314003' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8000272603776314003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8000272603776314003'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/09/deploying-reports.html' title='Deploying Reports'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8747710949957271256</id><published>2009-09-10T20:33:00.000-07:00</published><updated>2009-09-10T20:34:27.712-07:00</updated><title type='text'>Report Models in Reporting Services 2005</title><content type='html'>A report model, in technical terms, is a metadata description of a data source and the relationships that reside within that data source.  What it is in practical terms is so much more.  For a user it's their own little sandbox.  But creating a Report Model is a multi-step process.  &lt;p&gt;The first process is to analyze the needs of the users so you know what fields they are going to need in thier reports.  Providing too little information renders the reporting service useless, but providing too much information could eventually cause performance issues as more users access reports.  The second step is to ensure you have the appropriate referential integrity in place.  Having a series of reports running on a poorly normalized database or poorly designed Analysis Services cube will cause additional headaches.  When the project is first created, go into the properties of the project and set the URL of the Report Server (default setting is http://localhost/reportserver): &lt;/p&gt; &lt;center&gt;&lt;img alt="Setting the URL for the Report Server" src="http://www.mssqltips.com/tipimages/1115_reporturl.gif" /&gt; &lt;/center&gt; &lt;p&gt;After setting the URL of the Report you must specify a data source. Right-click &lt;i&gt;Data Sources&lt;/i&gt; and choose &lt;i&gt;New Data Source&lt;/i&gt;. Then choose the server you wish to connect to and the authentication method: &lt;/p&gt; &lt;center&gt;&lt;img alt="Creating a new data source in Solution Explorer" src="http://www.mssqltips.com/tipimages/1115_newdatasource.gif" /&gt; &lt;/center&gt; &lt;p&gt;The next step is to create a Data Source View. Right-click &lt;i&gt;Data Source Views&lt;/i&gt; and choose &lt;i&gt;New Data Source View&lt;/i&gt;: &lt;/p&gt; &lt;center&gt;&lt;img alt="Creating a new Data Source View in Solution Explorer" src="http://www.mssqltips.com/tipimages/1115_newdsv.gif" /&gt; &lt;/center&gt; &lt;p&gt;As usual, you must select the data source you wish to use or, if not created yet, do so inside the wizard: &lt;/p&gt; &lt;center&gt;&lt;img alt="Selecting the data source" src="http://www.mssqltips.com/tipimages/1115_selectdatasource.gif" /&gt; &lt;/center&gt; &lt;p&gt;The next screen in the wizard is one of interest, because here you can either choose from the entire list of tables and views, or narrow your selection based on the schema the object belongs to: &lt;/p&gt; &lt;center&gt;&lt;img alt="Selecting from all tables and views" src="http://www.mssqltips.com/tipimages/1115_selecttablesviews.gif" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt="Filtering objects based on schema" src="http://www.mssqltips.com/tipimages/1115_selectwithfilter.gif" /&gt;&lt;br /&gt;&lt;/center&gt; &lt;p&gt;As stated before, you can choose either a view or one or more tables, although you should create a view if joining more than two tables is necessary. Once the choice of objects is made, click &lt;i&gt;Next&lt;/i&gt; and provide a name for the data source view: &lt;/p&gt; &lt;center&gt;&lt;img alt="Naming the Data Source View" src="http://www.mssqltips.com/tipimages/1115_dsvcomplete.gif" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt="View of Solution Explorer with Data Source View" src="http://www.mssqltips.com/tipimages/1115_solexp.gif" /&gt; &lt;/center&gt; &lt;p&gt;Now you have everything you need to create a report model. Right-click &lt;i&gt;Report Models&lt;/i&gt; and choose &lt;i&gt;Add New Report Model&lt;/i&gt;: &lt;/p&gt; &lt;center&gt;&lt;img alt="Creating a New Report Model" src="http://www.mssqltips.com/tipimages/1115_newreportmodel.gif" /&gt; &lt;/center&gt; &lt;p&gt;Choose the data source view you wish to create the report model for and click Next: &lt;/p&gt; &lt;center&gt;&lt;img alt="Choosing the Data Source View" src="http://www.mssqltips.com/tipimages/1115_rptmodedsv.gif" /&gt; &lt;/center&gt; &lt;p&gt;Then select the rules you want for metadata generation: &lt;/p&gt; &lt;center&gt;&lt;img alt="Choosing the Rules for Metadata Generation" src="http://www.mssqltips.com/tipimages/1115_rptmodelgeneration.gif" /&gt; &lt;/center&gt; &lt;p&gt;The wizard then gives you an option on whether you want to update data statistics for the data source view or use the existing ones (the default is to use the current ones): &lt;/p&gt; &lt;center&gt;&lt;img alt="Collection of model statistics on the Data Source View" src="http://www.mssqltips.com/tipimages/1115_collectmodelstats.gif" /&gt; &lt;/center&gt; &lt;p&gt;Once all the information is collected for creating the report model, click &lt;i&gt;Run&lt;/i&gt; to complete the wizard: &lt;/p&gt; &lt;center&gt;&lt;img alt="Building statistics on the Report Model" src="http://www.mssqltips.com/tipimages/1115_rptmodelcompletion.gif" /&gt; &lt;/center&gt; &lt;p&gt;Now you have to deploy the Data Source and Report Model to the Report Server (there is no need to deploy the data source view). Right-click each of the objects and select &lt;i&gt;Deploy&lt;/i&gt;. From there you can assign security permissions to ensure that only those who need to access the data are able to access it. Users can also use Report Builder to create the ad-hoc reports and deploy either to their My Reports folder or to another folder on the Report Server. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8747710949957271256?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.mssqltips.com/tip.asp?tip=1115' title='Report Models in Reporting Services 2005'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8747710949957271256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8747710949957271256' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8747710949957271256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8747710949957271256'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/09/report-models-in-reporting-services.html' title='Report Models in Reporting Services 2005'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-7239549400053131897</id><published>2009-09-10T20:23:00.000-07:00</published><updated>2009-09-10T20:27:46.704-07:00</updated><title type='text'>SQL Server Clustering</title><content type='html'>&lt;span class="textBoldBlue"&gt;What Are the Types of Clustering?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you decide you want to cluster SQL Server, you have a choice of configuring what is called Active/Active or an Active/Passive cluster. Each has its own pros and cons. Let’s look at each, in the context of a two-node SQL Server cluster.&lt;br /&gt;&lt;br /&gt;An Active/Active SQL Server cluster means that SQL Server is running on both nodes of a two-way cluster. Each copy of SQL Server acts independently, and users see two different SQL Servers. If one of the SQL Servers in the cluster should fail, then the failed instance of SQL Server will failover to the remaining server. This means that then both instances of SQL Server will be running on one physical server, instead of two.&lt;br /&gt;&lt;br /&gt;As you can imagine, if two instances have to run on one physical server, performance can be affected, especially if the server’s have not been sized appropriately.&lt;br /&gt;&lt;br /&gt;An Active/Passive SQL Server cluster refers to a SQL Server cluster where only one instance of SQL Server is running on one of the physical servers in the cluster, and the other physical server does nothing, other than waiting to takeover should the primary node would fail.&lt;br /&gt;&lt;br /&gt;From a performance perspective, this is the better solution. On the other hand, this option makes less productive use of your physical hardware, which means this solution is more expensive.&lt;br /&gt;&lt;br /&gt;Personally, I prefer an Active/Passive configuration as it is easier to set up and administer, and overall it will provide better performance. Assuming you have the budget, this is what I recommend.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="textBoldBlue"&gt;Two- or Four-Node Clustering?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;SQL Server can be clustered using two nodes (using Windows 2000 Advanced Server), or it can be clustered using more than two nodes (using Windows 2000 Datacenter). Since I don’t personally have any experience is three or four node clustering, I won’t be discussing it here. But for the most part, what I say about two-node clustering also applies to three- or four-node clustering.&lt;br /&gt;&lt;br /&gt;&lt;span class="textBoldBlue"&gt;How Does Clustering Work?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Clustering is a very complex technology, so I will focus here on the big picture. In a two-cluster node, one of the SQL Servers is referred to as the primary node, and the second one is referred to as the secondary node. In an Active/Passive cluster design, SQL Server will run on the primary node, and should the primary node fail, then the secondary node will take over.&lt;br /&gt;&lt;br /&gt;When you build a two-node cluster using Windows 2000 Advanced Server and Microsoft Clustering Service, each node must be connected to a shared disk array using either SCSI cables or fibre channel.&lt;br /&gt;&lt;br /&gt;Typically, this shared disk array is a stand-alone unit that houses a RAID 5 or RAID 10 disk array. All of the shared data in the cluster must be stored on this disk array, otherwise when a failover occurs, the secondary node in the cluster cannot access it. As I have already mentioned earlier, clustering does not help protect data or the shared disk array that it is stored on. Because of this, it is very important that you select a shared disk array that is very reliable and includes fault tolerance.&lt;br /&gt;&lt;br /&gt;Besides both servers being connected to a shared disk array, both nodes of the cluster are also connected to each other via a private network. This private network is used for each node to keep track of the status of the other node. For example, if the primary node experiences a hardware failure, the secondary node will detect this and will automatically initiate a failover.&lt;br /&gt;&lt;br /&gt;So how do clients who are accessing SQL Server know what to do when a failover occurs in a cluster? This is the cleverest part of Microsoft Cluster Service. Essentially what happens in a SQL Server cluster is that you assign SQL Server its own virtual name and virtual TCP/IP address. This name and address is shared by both of the servers in the cluster.&lt;br /&gt;&lt;br /&gt;Typically, a client will connect to the SQL Server cluster using the virtual name used by the cluster. And as far as a client is concerned, there is only one physical SQL Server, not two. Assuming that the primary node of the SQL Server cluster is the node running SQL Server on an Active/Passive cluster design, then the primary node will respond to the client’s requests. But if the primary node fails, and failover to the secondary node occurs, the cluster will still retain the same SQL Server virtual name and TCP/IP address, although now a new physical server will be responding to client’s requests.&lt;br /&gt;&lt;br /&gt;During the failover period, which can last several minutes (the exact amount of time depends on the number and sizes of the databases on SQL Server, and how active they are), clients will be unable to access SQL Server, so there is a small amount of downtime when failover occurs.&lt;br /&gt;&lt;br /&gt;How the client software reacts to the failover process depends on the software. Some software will just wait the failover out, and when the failover has completed, it will continue just as nothing had happened. Some software will present a message box on the screen, describing a lost connection. Other client software will not know what to do, and users may have to exit, and then reload the client before they can access SQL Server again.&lt;br /&gt;&lt;br /&gt;As part of the testing process when implementing a SQL Server cluster, it is important to find out how all of the client software that connects to SQL Server reacts to a failover. This way, you can inform your users of what to expect, so they are better able to deal with it when it does occur.&lt;br /&gt;&lt;br /&gt;Once a failover occurs, you will want to find out what caused the failover, and then take the necessary action and correct the problem. Once the problem has been fixed, the next step is to failover SQL Server back to the primary node from the secondary node. You can schedule to do this anytime, preferably when user activity is light on the system.&lt;br /&gt;&lt;br /&gt;What are the Pros and Cons of Clustering?&lt;br /&gt;&lt;br /&gt;Implementing SQL Server clustering is a big decision, and one fraught with many gochas. Before you undertake such a large and important project, you will want to carefully evaluate the pros and cons of clustering, which include, but are not limited to:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Pros of SQL Server Clustering&lt;/i&gt;  &lt;ul&gt;&lt;li&gt;Reduces downtime to a bare minimum.&lt;/li&gt;&lt;li&gt;Permits an automatic response to a failed server or software. No human intervention is required.&lt;/li&gt;&lt;li&gt;It allows you to perform upgrades without forcing users off the system for extended periods of time.&lt;/li&gt;&lt;li&gt;It allows you to reduce downtime due to routine server, network, or database maintenance.&lt;/li&gt;&lt;li&gt;Clustering doesn't require any servers to be renamed. So when failover occurs, it is relatively transparent to end-users.&lt;/li&gt;&lt;li&gt;Failing back is quick, and can be done whenever the primary server if fixed and put back on-line.&lt;/li&gt;&lt;li&gt;In some cases, clustering can be used to increase the scalability of an application. For example, if a current cluster is getting too busy, another server could be added to the cluster to expand the resources and help boost the performance of the application.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;i&gt;Cons of Clustering&lt;/i&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;More expensive than other failover alternatives, such as log shipping or stand-by servers.&lt;/li&gt;&lt;li&gt;Requires more set up time than other alternatives.&lt;/li&gt;&lt;li&gt;Requires more on-going maintenance than other alternatives.&lt;/li&gt;&lt;li&gt;Requires more experienced DBAs and network administrators.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;br /&gt;&lt;span class="textBoldBlue"&gt;Software Needed for Clustering&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The software you need for SQL Server clustering depends on whether you want to cluster two nodes, or more than two nodes.&lt;br /&gt;&lt;br /&gt;To cluster two nodes, you will need the following:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Two Microsoft Windows 2000 Advanced Server Licenses&lt;/li&gt;&lt;li&gt;One SQL Server 7.0 Enterprise or SQL Server 2000 Enterprise Licenses for Active/Passive, or two licenses for Active/Active&lt;/li&gt;&lt;li&gt;The latest Windows 2000 and SQL Server Service Packs&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;To cluster more than two nodes, you will need the following:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Two or More Microsoft Windows 2000 Datacenter Server Licenses&lt;/li&gt;&lt;li&gt;Two or More SQL Server 7.0 Enterprise or SQL Server 2000 Enterprise Licenses&lt;/li&gt;&lt;li&gt;The latest Windows 2000 and SQL Server Service Packs&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I want to emphasize that you always want to go with the latest service packs, as many irritating cluster-related bugs have been fixed by them.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="textBoldBlue"&gt;Hardware Needed for Clustering&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Assuming you are clustering two SQL Servers, you will need at the very minimum the following:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Two servers with a minimum of 256MB RAM and a single Pentium III CPU.&lt;/li&gt;&lt;li&gt;One shared disk array that supports RAID 5 or 10, either SCSI or fibre channel.&lt;/li&gt;&lt;li&gt;Each server must have at least one local SCSI hard disk on its own SCSI controller.&lt;/li&gt;&lt;li&gt;Each server must have a SCSI or fiber channel adapter to talk to the shared disk array. The shared disk array cannot use the SCSI controller used by the local hard disk or CD-ROM.&lt;/li&gt;&lt;li&gt;Each server must have two PCI network cards (one for the private connection and one for the public connection).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;How you size the physical servers (CPUs, RAM, amount of shared disk array) is very similar to how you would size a non-clustered server if you plan to use an Active/Passive configuration. But, if you intend to use an Active/Active configuration, then ideally each physical server needs to be sized to run all instances of SQL Server that run on both the primary and secondary nodes, should failover occur and both instances of SQL Server have to run on the same physical server.&lt;br /&gt;&lt;br /&gt;Ideally, both physical servers should be identical in hardware, drivers, software, and configuration. There are some exceptions to this allowed, but I would not recommend making them. The closer each physical server is to each other, the less problems you will have.&lt;br /&gt;&lt;br /&gt;Another very important consideration when selecting clustering hardware is that is must be on Microsoft’s Hardware Compatibility List (HCL) as a supported system. What do I mean by a supported system? Before Microsoft will support your cluster, all of the cluster hardware you select (servers, cards, shared array, etc.) must have been tested as an entire system and approved by Microsoft. If the system you purchase isn’t an approved system, then Microsoft will not help you if you call them, even if you pay them for support.&lt;br /&gt;&lt;br /&gt;Even if all of the individual components of your cluster system have been approved individually by Microsoft for clustering, if they have not all been tested as a single system, then you will still not receive any support. That’s why you need to check out the HCL carefully before you order your equipment to ensure that you purchase an approved clustering system.&lt;br /&gt;&lt;br /&gt;Unfortunately, Microsoft’s HCL website is often outdated. What this means is that as new equipment comes out (and we always seem to want to use the latest and the greatest), it may not be added to their approved cluster systems for months. You can of course take the risk of selecting equipment that is not part of an approved Microsoft system (hoping that it will eventually be tested and certified by Microsoft), but should you have a problem and call Microsoft, you risk not getting any help from them.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="textBoldBlue"&gt;Setting Up and Managing a SQL Server Cluster&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This topic could fill a book, but unfortunately, there is not enough room here for that. So what I will do here is just cover the basics so you have some feel for what you face.&lt;br /&gt;&lt;br /&gt;Based on my experience with SQL Server clustering, you should keep the following in mind:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Buy an approved cluster system and have it delivered to you 4-8 weeks before you plan to implement it. This will give you lots of time to learn about it and work out any problems. I guarantee you, you will have problems.&lt;/li&gt;&lt;li&gt;Consider attending training on clustering, or at least bringing in a consultant in early in the game to help you plan your implementation. If you have never done this before, you will need all the help you can get. Unfortunately, there is not a lot of good information available on clustering, so you will have to fend for yourself more than you usually do.&lt;/li&gt;&lt;li&gt;Once your cluster is up and running, test it thoroughly as possible using the same databases and clients you intend to use on it when you start production.&lt;/li&gt;&lt;li&gt;Thoroughly document everything as you build your cluster.&lt;/li&gt;&lt;li&gt;Develop a plan to regularly monitor the cluster.&lt;/li&gt;&lt;li&gt;Develop a plan to regularly test the cluster to ensure that it will failover as expected.&lt;/li&gt;&lt;li&gt;Develop a formal backup and recovery plan, and test it.&lt;/li&gt;&lt;li&gt;Create a disaster recovery plan for what you intend to do should you loose all the nodes in your cluster.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Implementing and managing a cluster is complex. You will want to assign a team of top network and database administrators to implement and manage it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="textBoldBlue"&gt;Is Clustering for You?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hopefully, this article has provided you with some additional information on SQL Server clustering that you didn’t have before. And I hope I haven't scared you away from SQL Server clustering.&lt;br /&gt;&lt;br /&gt;While SQL Server clustering is not an easy challenge, it is often a worthwhile one. After installing two SQL Server clusters myself, and currently working on a third, I feel that SQL Server clustering is very valuable for many organizations, and in fact it has reduced my stress own level somewhat. Now I don’t have to worry (as much) about extended periods of down time. Now that the clusters are up, they haven’t presented any problems and are purring away.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-7239549400053131897?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.sql-server-performance.com/articles/clustering/clustering_intro_p1.aspxhttp://www.sql-server-performance.com/articles/clustering/clustering_intro_p1.aspx' title='SQL Server Clustering'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/7239549400053131897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=7239549400053131897' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/7239549400053131897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/7239549400053131897'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/09/sql-server-clustering.html' title='SQL Server Clustering'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-2188597660382984820</id><published>2009-08-14T14:45:00.000-07:00</published><updated>2009-08-14T15:35:39.133-07:00</updated><title type='text'>SQL Server Replication 2005</title><content type='html'>&lt;h2 id="first"&gt;&lt;span style="font-size:100%;"&gt;Introduction&lt;/span&gt;&lt;/h2&gt; &lt;p class="start"&gt;Replication is intended to be a way of distributing data automatically from a source database to one or more recipient databases. As such, it can have obvious uses in a distributed system. It has also been used to implement high-availability systems. It is not useful for one-off synchronization, or for simply copying data. It is intended as a long-term data relationship between databases. Typical uses are in:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Data warehousing and reporting  &lt;/li&gt;&lt;li&gt;Integrating data from several, possibly only partially connected, sites  &lt;/li&gt;&lt;li&gt;Improving scalability and availability  &lt;/li&gt;&lt;li&gt;Integrating heterogeneous data from other databases via OLE DB, integrating data from mobile users, getting data to and from Point-Of-Sale systems &lt;/li&gt;&lt;li&gt;Offloading/delegating batch processing tasks. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Examples of the use of replication within an application could be&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Distributing data 'owned' by a particular application to other applications that are 'consumers' of that data. (For example, sales records to reporting services, manufacturing stock levels to purchasing systems.) &lt;/li&gt;&lt;li&gt;Creating several instances of a database to distribute load on it  &lt;/li&gt;&lt;li&gt;Updating a central database with information from a number of remote Laptops that might be only partially connected, and to resynchronise the laptops. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;There are three methods of replication: Snapshot, Transactional, and Merge. These are provided to try to meet the wide range of business requirements for replication.&lt;/p&gt; &lt;p&gt;Replication uses a 'Magazine Publishing' vocabulary. Anything from an 'Article' to an entire database can be replicated. An Article is the smallest component of distribution, and can be a table, procedure or function. If it is a table, then a filter can be applied to it so that only certain rows or columns are replicated. This 'Magazine Publishing' analogy can be confusing because, in replication, a Subscriber can sometimes make updates, and a Publisher usually sends out incremental changes to the articles in a publication.&lt;/p&gt; &lt;p&gt;A 'Publisher' maintains the original copy of the data. It holds the definition of the 'Publication', which defines the 'articles' that are to be 'published'. (The database with the original location of the data determines what is to be distributed).&lt;/p&gt; &lt;p&gt;A 'Subscriber' receives the articles from a publisher. It can subscribe to one or more publications. Any database can take on either role or even both roles at once.&lt;/p&gt; &lt;p&gt;A Distributor is a specialist database that runs the 'Replication agents'.&lt;/p&gt; &lt;p&gt;Replication is not part of the SQL Server engine, but an external application. This makes it much easier to involve other database systems in replication. Any SQL Server database, or other database system with an OLE DB provider, can be a publisher or subscriber in snapshot or transactional replication.&lt;/p&gt; &lt;p&gt;It is essential to plan out the replication in detail as a first stage, and to be very certain of the type of replication you wish to implement. A common mistake is to use replication in cases where a much less complex solution is possible.&lt;/p&gt; &lt;p&gt;A problem with production systems using replication is the difficulty of restoring the topology after a disaster.. This requires a fully documented recovery strategy, which has to be periodically tested and practiced. This means that the whole replication topology and configuration must be scripted so it can be re-created in an emergency, even if the system was originally built using the GUI tools. The Object Browser (or Enterprise Manager) makes the initial deployment relatively simple to do, and there are plenty of step-by-step guides, but it is not the best option when trying to restore an existing topology, and settings, in order to achieve a recovery from major failures.&lt;/p&gt; &lt;p&gt;Problems often follow from developers adding or dropping articles, changing publication properties, and changing schema on published databases. It is therefore best to create the replication once the design of the publisher is relatively stable.&lt;/p&gt; &lt;h2 id="second"&gt;&lt;span style="font-size:100%;"&gt;Replication topologies&lt;/span&gt;&lt;/h2&gt; &lt;p class="start"&gt;In most topologies, it makes sense for publishers, distributors, and subscribers to be on separate physical hardware.&lt;/p&gt; &lt;h3 id="third"&gt;&lt;span style="font-size:100%;"&gt;Central Publisher&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;The commonest form of replication is to have a single publisher with the source data, with one or more subscribers. The Distributor database can be on the same, or preferably different, server.&lt;/p&gt; &lt;h3 id="fourth"&gt;&lt;span style="font-size:100%;"&gt;Central Subscriber&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;Often, where the data from several databases need to be 'warehoused' centrally in an OLAP or reporting database, one will find a single 'reporting' database subscribing to several publications.&lt;/p&gt; &lt;p class="indent1"&gt;One can come across other topologies such as 'bi-directional' and 'peer to peer' which are really special cases of Central Publisher or Central Subscriber and use transactional replication&lt;/p&gt; &lt;h3 id="fifth"&gt;&lt;span style="font-size:100%;"&gt;Publishing Subscriber&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;The distribution of data can be relayed to other subscribers via a publishing subscriber. This allows replication to be implemented over low-bandwidth WANs to a subscriber that, in turn, distributes it to other servers within its high-bandwidth LAN&lt;/p&gt; &lt;h2 id="sixth"&gt;&lt;span style="font-size:100%;"&gt;How Replication Works&lt;/span&gt;&lt;/h2&gt; &lt;p&gt;Replication begins with the initial synchronization of the published objects between the Publisher and Subscribers, using a snapshot. A snapshot is a copy of all of the objects and data specified by a publication. After the snapshot is created on the publisher, it is delivered to the Subscribers via the distributor.&lt;/p&gt; &lt;p&gt;For Snapshot replication, this is sufficient. For other types of replication, all subsequent data changes to the publication flow to the Subscriber as they happen, in a queue, or on request.&lt;/p&gt; &lt;h3 id="eighth"&gt;&lt;span style="font-size:100%;"&gt;Snapshot Replication&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;The snapshot replication process provides the initial synchronization for transactional and merge publications. However, in several cases, this initial synchronization is all that is necessary. This would include circumstances where data hardly changes, or if the latest version of the data is not essential to the subscriber, where the amount of data is small, or if a large number of changes takes place rapidly.&lt;/p&gt; &lt;p class="indent1"&gt;Snapshot replication involves copying the articles that make up the publication. Normally, if they exist already on the subscriber, they are over-written, though this behavior can be changed. Snapshot replication is more expensive in terms of overhead and network traffic and only takes place at intervals. Because locks are held during snapshot replication, this can impact other users of the subscriber database. It is therefore more suitable for static data and enumerations. In SQL Server 2005, several articles can be processed in parallel, and interrupted snapshots can be recommenced from the point of interruption. Snapshots can be queued or immediate.&lt;/p&gt; &lt;p class="indent1"&gt;Data changes are not tracked for snapshot replication; each time a snapshot is applied, it completely overwrites the existing data.&lt;/p&gt; &lt;h3 id="nineth"&gt;&lt;span style="font-size:100%;"&gt;Transactional Replication&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;Transactional replication is used if:&lt;/p&gt; &lt;ul class="indent1"&gt;&lt;li&gt;Changes to the data must be propagated immediately  &lt;/li&gt;&lt;li&gt;The database application taking out a subscription needs to react to every change  &lt;/li&gt;&lt;li&gt;The Publisher has a very high volume of insert, update, and delete activity  &lt;/li&gt;&lt;li&gt;The Publisher or Subscriber is a different database application reached via OLE DB. &lt;/li&gt;&lt;/ul&gt; &lt;p class="indent1"&gt;Essentially, Transaction replication distributes data in one direction, but transactional replication does offer options that allow updates at the Subscriber. Once a snapshot replication has synchronized the subscribers with the publisher, all committed transactions on the publisher are then propagated to the subscribers in sequence, via distributed transactions. One can select a queued update or immediate, depending on requirements.&lt;/p&gt; &lt;h4 id="tenth"&gt;&lt;span style="font-size:100%;"&gt;Peer-to-peer Replication&lt;/span&gt;&lt;/h4&gt; &lt;p class="indent2"&gt;This is a special type of transactional replication in which every participant is both a publisher and subscriber (2005 Enterprise only) and is most useful for up to ten databases in a load-balancing or high-availability group.&lt;/p&gt; &lt;h4 id="eleventh"&gt;&lt;span style="font-size:100%;"&gt;Bidirectional Replication&lt;/span&gt;&lt;/h4&gt; &lt;p class="indent2"&gt;This is where two databases replicate the same articles to each other via a distributor. There must be loopback detection. Data conflicts aren't handled and the replication must be implemented in code, since the GUI doesn't support it.&lt;/p&gt; &lt;p class="indent1"&gt;Transactional replication tracks changes through the SQL Server transaction log&lt;/p&gt; &lt;h3 id="twelveth"&gt;&lt;span style="font-size:100%;"&gt;Merge Replication&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;Merge replication allows various sites to work autonomously and later merge updates into a single, uniform result.&lt;/p&gt; &lt;p class="indent1"&gt;Merge Replication is complex, but provides the means to implement part of a high-availability system, as well as its original purpose of serving mobile and disconnected users. It is designed for cases where the publishers are not in constant communication with the subscribers. After the initial snapshot synchronization, subsequent changes are tracked locally with triggers, and the databases are merged when in contact, using a series of rules to resolve all possible conflicts.&lt;/p&gt; &lt;p class="indent1"&gt;Merge replication is used when several Subscribers might need to update the same data at various times and propagate those changes back to the Publisher and thence to other Subscribers. It is also required in applications that involve Subscribers receiving data, making changes offline, and finally reconnecting with the publisher to synchronize changes with the Publisher and other Subscribers.&lt;/p&gt; &lt;p class="indent1"&gt;To make this possible, each Subscriber requires a different partition of data and there has to be a set of rules to determine how every conflict that takes place in the update of the data is detected and resolved. These conflicts occur when the data is merged because there can be no 'locking' and so the same data may have been updated by the Publisher and by more than one Subscriber.&lt;/p&gt; &lt;p class="indent1"&gt;Merge Replication does not use transactions. Merge replication uses a set of conflict-resolution rules to deal with all the problems that occur when two databases alter the same data in different ways, before updating the subscribers with a 'consensus' version. It normally works on a row-by-row basis but can group rows of related information into a logical record. One can specify the order in which 'articles' are processed during synchronisation.&lt;/p&gt; &lt;p class="indent1"&gt;Merge replication tracks changes through triggers and metadata tables.&lt;/p&gt; &lt;h2 id="thirteenth"&gt;&lt;span style="font-size:100%;"&gt;Replication Agents&lt;/span&gt;&lt;/h2&gt; &lt;p class="start"&gt;Replication is done by several different agents, which are separate applications each responsible for part of the process. The replication agents should not be run under the SQL Server Agent account in a production system. Instead, they need the minimal permissions necessary to perform their function.&lt;/p&gt; &lt;h3 id="fourteenth"&gt;&lt;span style="font-size:100%;"&gt;SQL Server Agent&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;This manages the overall replication process via SQL Server Agent jobs.&lt;/p&gt; &lt;h3 id="fifteenth"&gt;&lt;span style="font-size:100%;"&gt;The Snapshot agent&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;&lt;span style="font-size:100%;"&gt;&lt;strong&gt;Snapshot.exe&lt;/strong&gt;&lt;/span&gt; executes on the Distributor. It extracts the schema and data defined by the publication, which is then sent to the subscriber via a 'snapshot folder'. It also updates status information on the distribution database. . It is used in all forms of replication&lt;/p&gt; &lt;h3 id="sixteenth"&gt;&lt;span style="font-size:100%;"&gt;The Log Reader Agent&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;&lt;span style="font-size:100%;"&gt;&lt;strong&gt;LogRead.exe&lt;/strong&gt;&lt;/span&gt; is used in transactional replication to extract relevant committed transactions from the publisher's log, repackage them and send them to the distributor in the correct sequence.&lt;/p&gt; &lt;h3 id="seventeenth"&gt;&lt;span style="font-size:100%;"&gt;Distribution Agent&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;&lt;span style="font-size:100%;"&gt;&lt;strong&gt;Distrib.exe&lt;/strong&gt; &lt;/span&gt;takes the snapshots, and log entries from the agents we've described, and dispatches them to the subscribers.&lt;/p&gt; &lt;h3 id="eighteenth"&gt;&lt;span style="font-size:100%;"&gt;Merge Agent&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;&lt;strong&gt;ReplMer.exe&lt;/strong&gt; is used only in Merge Replication to send a snapshot when the subscriber is initialized, and also exchanges transactions between publisher and subscriber&lt;/p&gt; &lt;h3 id="nineteenth"&gt;&lt;span style="font-size:100%;"&gt;Queue Reader Agent&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;&lt;strong&gt;QrDrSvc.exe&lt;/strong&gt; is used to queue the updates in transactional or snapshot replication when queuing has been specified.&lt;/p&gt; &lt;h2 id="twentieth"&gt;&lt;span style="font-size:100%;"&gt;Monitoring Replication&lt;/span&gt;&lt;/h2&gt; &lt;p class="start"&gt;Many problems associated with replication can be avoided by .regular checks. The most obvious check is to make sure that the data has been transferred as expected. Periodic checks with SQL Compare and SQL Data Compare can be very useful in addition to the tools that come with Replication. Additionally the replication processes and jobs need to be checked to make sure they are working.&lt;/p&gt; &lt;h3 id="twentyfirst"&gt;&lt;span style="font-size:100%;"&gt;Checking throughput&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;The performance of replication must be regularly monitored, and performance-tuned as necessary.&lt;/p&gt; &lt;p class="indent1"&gt;The Replication Monitor is used to check on the operational state of publications, and inspect the history, and errors. Right-clicking the replication node in Object Explorer will gain access to it.&lt;/p&gt; &lt;p class="indent1"&gt;One of the most important concerns is the time delay, or latency, of transactions from the publications appearing in the subscriber database. At times of high transaction throughput on the publisher database, bottlenecks can occur. Whereas the stored procedure sp_browseReplCmds on the distribution database can tell you how far behind the synchronisation is at any particular time, one cannot determine where the problems lies just from the data. Tracer tokens are now used to measure the actual throughput of the replication architecture at any particular time to help diagnose such bottlenecks.&lt;/p&gt; &lt;h3 id="tewntysecond"&gt;&lt;span style="font-size:100%;"&gt;Validating&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;There is always an element of doubt as to whether the replication has entirely worked. There are stored procedures provided to compare the 'articles' on the publisher and subscribers to make sure they are the same.&lt;/p&gt; &lt;p class="indent1"&gt;The sp_publication_validation stored procedure validates the data associated with each article by calling sp_article_validation (after the articles associated with a publication have been activated). The sp_article_validation stored procedure invokes sp_table_validation stored procedure, which calculates the number of lines and, optionally, the checksum of the published table. It is considered good practice to perform a daily row-count and weekly checksum. SQL Data Compare is ideal for mending a broken replication.&lt;/p&gt; &lt;p class="indent1"&gt;The Distribution Agent raises the '20574' system message if validation fails, or the '20575' system message if it passes. The Distribution Agent will replicate changes to a subscriber even if the validation shows that the subscriber is out of synchronization. It is a good policy to configure the Replication Alert on the '20574' message so as to send E-Mail, Pager, or Network notification.&lt;/p&gt; &lt;p class="indent1"&gt;This validation approach will only work within certain restrictions. For example, it will not work if certain filters have been applied. They should be used with caution.&lt;/p&gt; &lt;h3 id="twentythird"&gt;&lt;span style="font-size:100%;"&gt;Changing the settings&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;It is best to use the default replication settings unless there are clear performance gains to be made, or if the application design forces the issue. However, one cannot assume that the changes will be generally beneficial to the entire topology without comprehensive testing.&lt;/p&gt; &lt;h2 id="twentyfourth"&gt;&lt;span style="font-size:100%;"&gt;Articles&lt;/span&gt;&lt;/h2&gt; &lt;p class="start"&gt;Articles are the smallest unit of a publication. An article can be a table, view, stored Procedure or function. Where an article is based on a table or view, it can contain all the data or just part of it. These filters of two types.: More common are the static 'WHERE' clauses, but filters can be used dynamically in Merge Replication to publish different 'content' (rows) to different 'subscribers' (databases receiving data). These latter Filters are called 'Dynamic' and can be simple Row Filters, or Join Filters, where the selection of rows to publish is based on a join with other tables, rather than a simple WHERE clause.&lt;/p&gt; &lt;p&gt;Normally, any alteration to an article that is a table is propagated to all the subscribers. You can also opt to propagate schema objects associated with the article such as indexes, constraints, triggers, collation and extended properties.&lt;/p&gt; &lt;h3 id="twentyfifth"&gt;&lt;span style="font-size:100%;"&gt;Updating articles&lt;/span&gt;&lt;/h3&gt; &lt;p class="indent1"&gt;In Merge replication, the subscriber can update the article. This is, of course, a recipe for conflict, and these have to be resolved automatically. When the Merge Agent comes across a row that might have changed recently, it examines the history or 'lineage' of each site's version of the row to see if there is a conflict. If so, then the update that is finally used. Has to be based on either&lt;/p&gt; &lt;ul class="indent1"&gt;&lt;li&gt;A "first wins" resolution,  &lt;/li&gt;&lt;li&gt;a user-specified priority scheme to determine the update to select,  &lt;/li&gt;&lt;li&gt;a customised resolution, using COM and stored procedures. &lt;/li&gt;&lt;/ul&gt; &lt;p class="indent1"&gt;The 'lineage' is a history of changes in a table row in MSmerge_contents, which is maintained automatically when a user updates a row. Each column contains one entry for each site that has updated the row.&lt;/p&gt; &lt;p class="indent1"&gt;Conflicts to the data in the base table can occur within a column or a row. Most usual are column-tracked articles this means that, within any row, updates are only recognized as conflicts if the same column is updated by more than one subscriber. Occasionally, however, the business rules of the application may treat simultaneous changes to the any column within the row as a conflict, in which case row-level tracking is used.&lt;/p&gt; &lt;h2 id="twentysixth"&gt;&lt;span style="font-size:100%;"&gt;Programming Replication Topologies&lt;/span&gt;&lt;/h2&gt; &lt;p class="start"&gt;Replication agents and replication topologies can be administered and monitored remotely via SQL Scripts or RMO scripts. The task of building and maintaining replication topologies is made much easier of all parts of the deployments are scripted, even if this is done after the other methods such as wizards or RMO are used for the initial operation.&lt;/p&gt; &lt;p&gt;There are other uses for a replication script. It will be required in end-user application where, for example, such as s a pull subscription is synchronized when the user clicks a button, or where a routine administration task such as monitoring replication throughput is performed from a custom console. It is also generally used for writing customized business rules that are executed when a merge subscription is synchronized.&lt;/p&gt; &lt;p&gt;One can use the Object Explorer in SSMS, or the Enterprise Manager in earlier versions of SQL Server, to set up replication. BOL provide worked examples. Alternatively, RMO can be used with VB or C# to script the replication. Whatever system you use, it is a good idea to use the Transact SQL script as the reference for the replication topology you create&lt;/p&gt; &lt;p&gt;Ultimately, the functionality in a replication topology is provided by system stored procedures. The easiest approach is to use Transact-SQL script files to perform a logical sequence of replication tasks, because it provides a permanent, repeatable, copy of the steps used to deploy the replication topology that can, for example, be used to configure more than one subscriber. It also provides a measure of documentation and disaster-recovery. A script can be stored as a query object in a SQL Server Management Studio project.&lt;/p&gt; &lt;p&gt;Replication scripts can be created by hand, by the script generation of the replication wizards in SQL Server Management Studio, or by using Replication Management Objects (RMOs) to programmatically generate the script to create an RMO object.&lt;/p&gt; &lt;p&gt;When creating scripts to configure replication, it is best to use Windows Authentication so as to avoid storing security credentials in the script file. Otherwise you must secure the script file&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-2188597660382984820?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.simple-talk.com/sql/database-administration/sql-server-replication-crib-sheet/' title='SQL Server Replication 2005'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/2188597660382984820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=2188597660382984820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2188597660382984820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2188597660382984820'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/08/sql-server-replication.html' title='SQL Server Replication 2005'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-2187259674383915018</id><published>2009-06-28T19:47:00.000-07:00</published><updated>2009-06-28T20:00:37.969-07:00</updated><title type='text'>Database programming guidelines, conventions</title><content type='html'>Databases are the heart and soul of many of the recent enterprise applications and it is very essential to pay special attention to database programming. I've seen in many occasions where database programming is overlooked, thinking that it's something easy and can be done by anyone. This is wrong. For a better performing database you need a real DBA and a specialist database programmer, let it be Microsoft SQL Server, Oracle, Sybase, DB2 or whatever! If you don't use database specialists during your development cycle, database often ends up becoming the performance bottleneck. I decided to write this article, to put together some of the database programming best practices, so that my fellow DBAs and database developers can benefit!&lt;br /&gt;&lt;br /&gt;Here are some of the programming guidelines, best practices, keeping quality, performance and maintainability in mind. This list many not be complete at this moment, and will be constantly updated.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Decide upon a database naming convention, standardize it across your organization and be consistent in following it. It helps make your code more readable and understandable. Click here to see the database object naming convention that I follow.&lt;/li&gt;&lt;li&gt;Do not depend on undocumented functionality. The reasons being:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      - You will not get support from Microsoft, when something goes wrong with your undocumented code&lt;br /&gt;      - Undocumented functionality is not guaranteed to exist (or behave the same) in a future release or service pack, there by breaking your code&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Try not to use system tables directly. System table structures may change in a future release. Wherever possible, use the sp_help* stored procedures or INFORMATION_SCHEMA views. There will be situattions where you cannot avoid accessing system table though!&lt;/li&gt;&lt;li&gt;Make sure you normalize your data at least till 3rd normal form. At the same time, do not compromize on query performance. A little bit of denormalization helps queries perform faster.&lt;/li&gt;&lt;li&gt;Write comments in your stored procedures, triggers and SQL batches generously, whenever something is not very obvious. This helps other programmers understand your code clearly. Don't worry about the length of the comments, as it won't impact the performance, unlike interpreted languages like ASP 2.0.&lt;/li&gt;&lt;li&gt;Do not use SELECT * in your queries. Always write the required column names after the SELECT statement, like SELECT CustomerID, CustomerFirstName, City. This technique results in less disk IO and less network traffic and hence better performance.&lt;/li&gt;&lt;li&gt;Try to avoid server side cursors as much as possible. Always stick to 'set based approach' instead of a 'procedural approach' for accessing/manipulating data. Cursors can be easily avoided by SELECT statements in many cases. If a cursor is unavoidable, use a simpleWHILE loop instead, to loop through the table. I personally tested and concluded that a WHILE loop is faster than a cursor most of the times. But for a WHILE loop to replace a cursor you need a column (primary key or unique key) to identify each row uniquely and I personally believe every table must have a primary or unique key. Click here to see one of the many examples of using WHILE loop.&lt;/li&gt;&lt;li&gt;Avoid the creation of temporary tables while processing data, as much as possible, as creating a temporary table means more disk IO. Consider advanced SQL or views or table variables of SQL Server 2000 or derived tables, instead of temporary tables. Keep in mind that, in some cases, using a temporary table performs better than a highly complicated query.&lt;/li&gt;&lt;li&gt;Try to avoid wildcard characters at the beginning of a word while searching using the LIKE keyword, as that results in an index scan, which is defeating the purpose of having an index. The following statement results in an index scan, while the second statement results in an index seek:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      1. SELECT LocationID FROM Locations WHERE Specialities LIKE '%pples'&lt;br /&gt;      2. SELECT LocationID FROM Locations WHERE Specialities LIKE 'A%s'&lt;br /&gt;&lt;br /&gt;      Also avoid searching with not equals operators (&lt;&gt; and NOT) as they result in table and index scans. If you must do heavy text-based searches, consider using the Full-Text search feature of SQL Server for better performance.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use 'Derived tables' wherever possible, as they perform better. Consider the following query to find the second highest salary from Employees table:&lt;/li&gt;&lt;/ul&gt;      SELECT MIN(Salary)&lt;br /&gt;      FROM Employees&lt;br /&gt;      WHERE EmpID IN&lt;br /&gt;      (&lt;br /&gt;      SELECT TOP 2 EmpID&lt;br /&gt;      FROM Employees&lt;br /&gt;      ORDER BY Salary Desc&lt;br /&gt;      )&lt;br /&gt;&lt;br /&gt;      The same query can be re-written using a derived table as shown below, and it performs twice as fast as the above query:&lt;br /&gt;&lt;br /&gt;      SELECT MIN(Salary)&lt;br /&gt;      FROM&lt;br /&gt;      (&lt;br /&gt;      SELECT TOP 2 Salary&lt;br /&gt;      FROM Employees&lt;br /&gt;      ORDER BY Salary Desc&lt;br /&gt;      ) AS A&lt;br /&gt;&lt;br /&gt;      This is just an example, the results might differ in different scenarios depending upon the database design, indexes, volume of data etc. So, test all the possible ways a query could be written and go with the efficient one. With some practice and understanding of 'how SQL Server optimizer works', you will be able to come up with the best possible queries without this trial and error method.&lt;br /&gt;&lt;ul&gt;&lt;li&gt; While designing your database, design it keeping 'performance' in mind. You can't really tune performance later, when your database is in production, as it involves rebuilding tables/indexes, re-writing queries. Use the graphical execution plan in Query Analyzer or SHOWPLAN_TEXT or SHOWPLAN_ALL commands to analyze your queries. Make sure your queries do 'Index seeks' instead of 'Index scans' or 'Table scans'. A table scan or an index scan is a very bad thing and should be avoided where possible (sometimes when the table is too small or when the whole table needs to be processed, the optimizer will choose a table or index scan).&lt;/li&gt;&lt;li&gt;Prefix the table names with owner names, as this improves readability, avoids any unnecessary confusions. Microsoft SQL Server Books Online even states that qualifying tables names, with owner names helps in execution plan reuse.&lt;/li&gt;&lt;li&gt;Use SET NOCOUNT ON at the beginning of your SQL batches, stored procedures and triggers in production environments, as this suppresses messages like '(1 row(s) affected)' after executing INSERT, UPDATE, DELETE and SELECT statements. This inturn improves the performance of the stored procedures by reducing the network traffic.&lt;/li&gt;&lt;li&gt;Use the more readable ANSI-Standard Join clauses instead of the old style joins. With ANSI joins the WHERE clause is used only for filtering data. Where as with older style joins, the WHERE clause handles both the join condition and filtering data. The first of the following two queries shows an old style join, while the second one shows the new ANSI join syntax:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      SELECT a.au_id, t.title&lt;br /&gt;      FROM titles t, authors a, titleauthor ta&lt;br /&gt;      WHERE&lt;br /&gt;      a.au_id = ta.au_id AND&lt;br /&gt;      ta.title_id = t.title_id AND&lt;br /&gt;      t.title LIKE '%Computer%'&lt;br /&gt;&lt;br /&gt;      SELECT a.au_id, t.title&lt;br /&gt;      FROM authors a&lt;br /&gt;      INNER JOIN&lt;br /&gt;      titleauthor ta&lt;br /&gt;      ON&lt;br /&gt;      a.au_id = ta.au_id&lt;br /&gt;      INNER JOIN&lt;br /&gt;      titles t&lt;br /&gt;      ON&lt;br /&gt;      ta.title_id = t.title_id&lt;br /&gt;      WHERE t.title LIKE '%Computer%'&lt;br /&gt;&lt;br /&gt;      Be aware that the old style *= and =* left and right outer join syntax may not be supported in a future release of SQL Server, so you are better off adopting the ANSI standard outer join syntax.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Do not prefix your stored procedure names with 'sp_'. The prefix sp_ is reserved for system stored procedure that ship with SQL Server. Whenever SQL Server encounters a procedure name starting with sp_,, it first tries to locate the procedure in the master database, then looks for any qualifiers (database, owner) provided, then using dbo as the owner. So, you can really save time in locating the stored procedure by avoiding sp_ prefix. But there is an exception! While creating general purpose stored procedures that are called from all your databases, go ahead and prefix those stored procedure names with sp_ and create them in the master database.&lt;/li&gt;&lt;li&gt;Views are generally used to show specific data to specific users based on their interest. Views are also used to restrict access to the base tables by granting permission on only views. Yet another significant use of views is that, they simplify your queries. Incorporate your frequently required complicated joins and calculations into a view, so that you don't have to repeat those joins/calculations in all your queries, instead just select from the view.&lt;/li&gt;&lt;li&gt;Use 'User Defined Datatypes', if a particular column repeats in a lot of your tables, so that the datatype of that column is consistent across all your tables.&lt;/li&gt;&lt;li&gt;Do not let your front-end applications query/manipulate the data directly using SELECT or INSERT/UPDATE/DELETE statements. Instead, create stored procedures, and let your applications access these stored procedures. This keeps the data access clean and consistent across all the modules of your application, at the same time centralizing the business logic within the database.&lt;/li&gt;&lt;li&gt;Try not to use text, ntext datatypes for storing large textual data. 'text' datatype has some inherent problems associated with it. You can not directly write, update text data using INSERT, UPDATE statements (You have to use special statements like READTEXT, WRITETEXT and UPDATETEXT). There are a lot of bugs associated with replicating tables containing text columns. So, if you don't have to store more than 8 KB of text, use char(8000) or varchar(8000)datatypes.&lt;/li&gt;&lt;li&gt;If you have a choice, do not store binary files, image files (Binary large objects or BLOBs) etc. inside the database. Instead store the path to the binary/image file in the database and use that as a pointer to the actual binary file. Retrieving, manipulating these large binary files is better performed outside the database and after all, database is not meant for storing files.&lt;/li&gt;&lt;li&gt;Use char data type for a column, only when the column is non-nullable. If a char column is nullable, it is treated as a fixed length column in SQL Server 7.0+. So, a char(100), when NULL, will eat up 100 bytes, resulting in space wastage. So, use varchar(100) in this situation. Of course, variable length columns do have a very little processing overhead over fixed length columns. Carefully choose between char and varchar depending up on the length of the data you are going to store.&lt;/li&gt;&lt;li&gt;Avoid dynamic SQL statements as much as possible. Dynamic SQL tends to be slower than static SQL, as SQL Server must generate an execution plan every time at runtime. IF and CASE statements come in handy to avoid dynamic SQL. Another major disadvantage of using dynamic SQL is that, it requires the users to have direct access permissions on all accessed objects like tables and views. Generally, users are given access to the stored procedures which reference the tables, but not directly on the tables. In this case, dynamic SQL will not work. Consider the following scenario, where a user named 'dSQLuser' is added to the pubs database, and is granted access to a procedure named 'dSQLproc', but not on any other tables in the pubs database. The procedure dSQLproc executes a direct SELECT on titles table and that works. The second statement runs the same SELECT on titles table, using dynamic SQL and it fails with the following error:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      Server: Msg 229, Level 14, State 5, Line 1&lt;br /&gt;      SELECT permission denied on object 'titles', database 'pubs', owner 'dbo'.&lt;br /&gt;&lt;br /&gt;      To reproduce the above problem, use the following commands:&lt;br /&gt;&lt;br /&gt;      sp_addlogin 'dSQLuser'&lt;br /&gt;      GO&lt;br /&gt;      sp_defaultdb 'dSQLuser', 'pubs'&lt;br /&gt;      USE pubs&lt;br /&gt;      GO&lt;br /&gt;      sp_adduser 'dSQLUser', 'dSQLUser'&lt;br /&gt;      GO&lt;br /&gt;      CREATE PROC dSQLProc&lt;br /&gt;      AS&lt;br /&gt;      BEGIN&lt;br /&gt;      SELECT * FROM titles WHERE title_id = 'BU1032' --This works&lt;br /&gt;      DECLARE @str CHAR(100)&lt;br /&gt;      SET @str = 'SELECT * FROM titles WHERE title_id = ''BU1032'''&lt;br /&gt;      EXEC (@str) --This fails&lt;br /&gt;      END&lt;br /&gt;      GO&lt;br /&gt;      GRANT EXEC ON dSQLProc TO dSQLuser&lt;br /&gt;      GO&lt;br /&gt;&lt;br /&gt;      Now login to the pubs database using the login dSQLuser and execute the procedure dSQLproc to see the problem.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Consider the following drawbacks before using IDENTITY property for generating primary keys. IDENTITY is very much SQL Server specific, and you will have problems if you want to support different database backends for your application.IDENTITY columns have other inherent problems. IDENTITY columns run out of numbers one day or the other. Numbers can't be reused automatically, after deleting rows. Replication and IDENTITY columns don't always get along well. So, come up with an algorithm to generate a primary key, in the front-end or from within the inserting stored procedure. There could beissues with generating your own primary keys too, like concurrency while generating the key, running out of values. So, consider both the options and go with the one that suits you well.&lt;/li&gt;&lt;li&gt;Minimize the usage of NULLs, as they often confuse the front-end applications, unless the applications are coded intelligently to eliminate NULLs or convert the NULLs into some other form. Any expression that deals with NULL results in a NULL output. ISNULL and COALESCE functions are helpful in dealing with NULL values. Here's an example that explains the problem:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      Consider the following table, Customers which stores the names of the customers and the middle name can be NULL.&lt;br /&gt;&lt;br /&gt;      CREATE TABLE Customers&lt;br /&gt;      (&lt;br /&gt;      FirstName varchar(20),&lt;br /&gt;      MiddleName varchar(20),&lt;br /&gt;      LastName varchar(20)&lt;br /&gt;      )&lt;br /&gt;&lt;br /&gt;      Now insert a customer into the table whose name is Tony Blair, without a middle name:&lt;br /&gt;&lt;br /&gt;      INSERT INTO Customers&lt;br /&gt;      (FirstName, MiddleName, LastName)&lt;br /&gt;      VALUES ('Tony',NULL,'Blair')&lt;br /&gt;&lt;br /&gt;      The following SELECT statement returns NULL, instead of the customer name:&lt;br /&gt;&lt;br /&gt;      SELECT FirstName + ' ' + MiddleName + ' ' + LastName FROM Customers&lt;br /&gt;&lt;br /&gt;      To avoid this problem, use ISNULL as shown below:&lt;br /&gt;&lt;br /&gt;      SELECT FirstName + ' ' + ISNULL(MiddleName + ' ','') + LastName FROM Customers&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use Unicode datatypes like nchar, nvarchar, ntext, if your database is going to store not just plain English characters, but a variety of characters used all over the world. Use these datatypes, only when they are absolutely needed as they need twice as much space as non-unicode datatypes.&lt;/li&gt;&lt;li&gt;Always use a column list in your INSERT statements. This helps in avoiding problems when the table structure changes (like adding a column). Here's an example which shows the problem.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      Consider the following table:&lt;br /&gt;&lt;br /&gt;      CREATE TABLE EuropeanCountries&lt;br /&gt;      (&lt;br /&gt;      CountryID int PRIMARY KEY,&lt;br /&gt;      CountryName varchar(25)&lt;br /&gt;      )&lt;br /&gt;&lt;br /&gt;      Here's an INSERT statement without a column list , that works perfectly:&lt;br /&gt;&lt;br /&gt;      INSERT INTO EuropeanCountries&lt;br /&gt;      VALUES (1, 'Ireland')&lt;br /&gt;&lt;br /&gt;      Now, let's add a new column to this table:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      ALTER TABLE EuropeanCountries&lt;br /&gt;      ADD EuroSupport bit&lt;br /&gt;&lt;br /&gt;      Now run the above INSERT statement. You get the following error from SQL Server:&lt;br /&gt;&lt;br /&gt;      Server: Msg 213, Level 16, State 4, Line 1&lt;br /&gt;      Insert Error: Column name or number of supplied values does not match table definition.&lt;br /&gt;&lt;br /&gt;      This problem can be avoided by writing an INSERT statement with a column list as shown below:&lt;br /&gt;&lt;br /&gt;      INSERT INTO EuropeanCountries&lt;br /&gt;      (CountryID, CountryName)&lt;br /&gt;      VALUES (1, 'England')&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Perform all your referential integrity checks, data validations using constraints (foreign key and check constraints). These constraints are faster than triggers. So, use triggers only for auditing, custom tasks and validations that can not be performed using these constraints. These constraints save you time as well, as you don't have to write code for these validations and the RDBMS will do all the work for you.    * Always access tables in the same order in all your stored procedures/triggers consistently. This helps in avoiding deadlocks. Other things to keep in mind to avoid deadlocks are: Keep your transactions as short as possible. Touch as less data as possible during a transaction. Never, ever wait for user input in the middle of a transaction. Do not use higher level locking hints or restrictive isolation levels unless they are absolutely needed. Make your front-end applications deadlock-intelligent, that is, these applications should be able to resubmit the transaction incase the previous transaction fails with error 1205. In your applications, process all the results returned by SQL Server immediately, so that the locks on the processed rows are released, hence no blocking.&lt;/li&gt;&lt;li&gt;Offload tasks like string manipulations, concatenations, row numbering, case conversions, type conversions etc. to the front-end applications, if these operations are going to consume more CPU cycles on the database server (It's okay to do simple string manipulations on the database end though). Also try to do basic validations in the front-end itself during data entry. This saves unnecessary network roundtrips.&lt;/li&gt;&lt;li&gt;If back-end portability is your concern, stay away from bit manipulations with T-SQL, as this is very much RDBMS specific. Further, using bitmaps to represent different states of a particular entity conflicts with the normalization rules.&lt;/li&gt;&lt;li&gt;Consider adding a @Debug parameter to your stored procedures. This can be of bit data type. When a 1 is passed for this parameter, print all the intermediate results, variable contents using SELECT or PRINT statements and when 0 is passed do not print debug information. This helps in quick debugging of stored procedures, as you don't have to add and remove these PRINT/SELECT statements before and after troubleshooting problems.&lt;/li&gt;&lt;li&gt;Do not call functions repeatedly within your stored procedures, triggers, functions and batches. For example, you might need the length of a string variable in many places of your procedure, but don't call the LEN function whenever it's needed, instead, call the LEN function once, and store the result in a variable, for later use.&lt;/li&gt;&lt;li&gt;Make sure your stored procedures always return a value indicating the status. Standardize on the return values of stored procedures for success and failures. The RETURN statement is meant for returning the execution status only, but not data. If you need to return data, use OUTPUT parameters.&lt;/li&gt;&lt;li&gt;If your stored procedure always returns a single row resultset, consider returning the resultset using OUTPUT parameters instead of a SELECT statement, as ADO handles output parameters faster than resultsets returned by SELECT statements.&lt;/li&gt;&lt;li&gt;Always check the global variable @@ERROR immediately after executing a data manipulation statement (like INSERT/UPDATE/DELETE), so that you can rollback the transaction in case of an error (@@ERROR will be greater than 0 in case of an error). This is important, because, by default, SQL Server will not rollback all the previous changes within a transaction if a particular statement fails. This behavior can be changed by executing SET XACT_ABORT ON. The @@ROWCOUNT variable also plays an important role in determining how many rows were affected by a previous data manipulation (also, retrieval) statement, and based on that you could choose to commit or rollback a particular transaction.&lt;/li&gt;&lt;li&gt;To make SQL Statements more readable, start each clause on a new line and indent when needed. Following is an example:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      SELECT title_id, title&lt;br /&gt;      FROM titles&lt;br /&gt;      WHERE title LIKE 'Computing%' AND&lt;br /&gt;                       title LIKE 'Gardening%'&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Though we survived the Y2K, always store 4 digit years in dates (especially, when using char or int datatype columns), instead of 2 digit years to avoid any confusion and problems. This is not a problem with datetime columns, as the century is stored even if you specify a 2 digit year. But it's always a good practice to specify 4 digit years even with datetime datatype columns.&lt;/li&gt;&lt;li&gt;In your queries and other SQL statements, always represent date in yyyy/mm/dd format. This format will always be interpreted correctly, no matter what the default date format on the SQL Server is. This also prevents the following error, while working with dates:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;     Server: Msg 242, Level 16, State 3, Line 2&lt;br /&gt;      The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;As is true with any other programming language, do not use GOTO or use it sparingly. Excessive usage of GOTO can lead to hard-to-read-and-understand code.&lt;/li&gt;&lt;li&gt;Do not forget to enforce unique constraints on your alternate keys.&lt;/li&gt;&lt;li&gt;Always be consistent with the usage of case in your code. On a case insensitive server, your code might work fine, but it will fail on a case sensitive SQL Server if your code is not consistent in case. For example, if you create a table in SQL Server or database that has a case-sensitive or binary sort order, all references to the table must use the same case that was specified in the CREATE TABLE statement. If you name the table as 'MyTable' in the CREATE TABLE statement and use 'mytable' in the SELECT statement, you get an 'object not found' or 'invalid object name' error.&lt;/li&gt;&lt;li&gt;Though T-SQL has no concept of constants (like the ones in C language), variables will serve the same purpose. Using variables instead of constant values within your SQL statements, improves readability and maintainability of your code. Consider the following example:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;      UPDATE dbo.Orders&lt;br /&gt;      SET OrderStatus = 5&lt;br /&gt;      WHERE OrdDate &lt; '2001/10/25'&lt;br /&gt;&lt;br /&gt;      The same update statement can be re-written in a more readable form as shown below:&lt;br /&gt;&lt;br /&gt;      DECLARE @ORDER_PENDING int&lt;br /&gt;      SET  @ORDER_PENDING = 5&lt;br /&gt;&lt;br /&gt;      UPDATE dbo.Orders&lt;br /&gt;      SET OrderStatus = @ORDER_PENDING&lt;br /&gt;      WHERE OrdDate &lt; '2001/10/25'&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Do not use the column numbers in the ORDER BY clause as it impairs the readability of the SQL statement. Further, changing the order of columns in the SELECT list has no impact on the ORDER BY when the columns are referred by names instead of numbers. Consider the following example, in which the second query is more readable than the first one:&lt;/li&gt;&lt;/ul&gt;      SELECT OrderID, OrderDate&lt;br /&gt;      FROM Orders&lt;br /&gt;      ORDER BY 2&lt;br /&gt;&lt;br /&gt;      SELECT OrderID, OrderDate&lt;br /&gt;      FROM Orders&lt;br /&gt;      ORDER BY OrderDate&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-2187259674383915018?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='text/html' href='http://vyaskn.tripod.com/coding_conventions.htm' length='0'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/2187259674383915018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=2187259674383915018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2187259674383915018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2187259674383915018'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/database-programming-guidelines.html' title='Database programming guidelines, conventions'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8679006094191011639</id><published>2009-06-28T19:39:00.000-07:00</published><updated>2009-06-28T19:44:20.477-07:00</updated><title type='text'>What are federated database servers?</title><content type='html'>"Federated database servers" is a feature introduced in SQL Server 2000. A federation is a group of SQL Servers that cooperate to share the processing load of a system. Federated database servers let you scale out a set of servers to support the processing needs of large systems and websites.&lt;br /&gt;&lt;br /&gt;Scaling out is the process of increasing the processing power of a system by adding one or more additional computers, or nodes, instead of beefing up the hardware of a single computer (Scaling up).&lt;br /&gt;&lt;br /&gt;Federated database servers can be implemented using "Distributed Partitioned Views" (DPV). You can partition tables horizontally across several servers, and define a distributed partitioned view on one server, covering all member server partitions. This view makes it appear as if a full copy of the original table is stored on one server.&lt;br /&gt;&lt;br /&gt;SQL Server 7.0 supports partitioned views too, but SQL Server 2000 came up with the following enhancements, that allow the views to scale out and form federations of database servers:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In SQL Server 2000, partitioned views are updateable&lt;/li&gt;&lt;li&gt;The SQL Server 2000 query optimizer supports new optimizations that minimize the amount of distributed data that has to be transferred. The distributed execution plans generated by SQL Server 2000 result in good performance for a larger set of queries than the plans generated by SQL Server 7.0 &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Why federated database servers and when to scale out?&lt;/span&gt;&lt;br /&gt;When websites, applications generate processing loads that exceed the capacity of large individual servers, scaling out is the best option for increasing the processing capacity of the system. When the server for a particular application is at its maximum potential, and is no longer able to meet user demands, you should consider scaling out.&lt;br /&gt;&lt;br /&gt;According to Microsoft, a federation of servers running SQL Server 2000 is capable of supporting the growth requirements of any Web site, or of the largest enterprise systems.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How are we able to gain performance by scaling out?&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Distributed processing of data, which means individual member servers of the federation are working with smaller subsets of data, instead of the complete data.&lt;/li&gt;&lt;li&gt;More CPUs working in parallel.&lt;/li&gt;&lt;li&gt;Parallel disk I/O.&lt;/li&gt;&lt;li&gt;Availability of more RAM, as each member server is working with a smaller subset of data.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;How to create distributed partitioned views?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Creation of partitioned views is explained in SQL Server Books Online, in the page titled "Creating a Partitioned View". The rules for creating updateable partitioned views are also explained in this page.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What is the impact of partitioned views on my front-end applications?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Instead of accessing the base tables directly, your front-end applications or stored procedures will access the partitioned view. SQL Server will take care of getting the right data from right servers, transparent to your application. Even in OLTP scenarios SQL Server manages the INSERT, UPDATE and DELETE commands transparently and sends them to the right partition.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What other things I should consider before implementing federated database servers?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Availability: Make sure all table partitions spread across different servers are accessible all the time, or else you will not be able to use the partitioned view.&lt;/li&gt;&lt;li&gt;Backup/Restore: If transactional consistency across the partitioned is not a concern, you can backup and restore some or all of your partitions individually. If you must achieve transactional consistency, perform coordinated backup and restore operations. This means that you backup all your partitions simultaneously and in case you have to restore them, you will have to restore all your partitions to a certain point in time.&lt;/li&gt;&lt;li&gt;Security: Since you have your data partitioned across multiple database servers, you have to follow consistent security practices across all your servers.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;What is the performance gain I can expect by scaling out?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is no easy way to calculate the performance gain, without actually implementing and testing the scenario, as the performance depends on a lot of other factors too. But in general, in a simulated DSS system, I achieved a performance gain of 25 to 30% by scaling out to just two SQL Servers.&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8679006094191011639?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='text/html' href='http://vyaskn.tripod.com/what_are_federated_databases.htm' length='0'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8679006094191011639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8679006094191011639' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8679006094191011639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8679006094191011639'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/what-are-federated-database-servers.html' title='What are federated database servers?'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-2721240001814723882</id><published>2009-06-28T19:28:00.000-07:00</published><updated>2009-06-28T19:37:41.532-07:00</updated><title type='text'>Evaluation  of fedarated databases.</title><content type='html'>Okay, there are no high end systems, no quad processor boxes, no RAID, and no dedicated network. It's an evaluation scenario at it's simplest form.&lt;br /&gt;&lt;br /&gt;I horizontally partitioned a huge table (5 Million rows, not so huge anyways!) across two database servers with 2.5 million rows on each server. Idea is to compare the response times in the following two scenarios:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Having the table on one server (5 million rows)&lt;/li&gt;&lt;li&gt;Having the table spread across two servers (2.5 million rows on each server)&lt;/li&gt;&lt;/ul&gt;Here is the hardware configuration of both the servers:&lt;br /&gt;Server1: Server1&lt;br /&gt;OS: Microsoft Windows 2000 Advanced Server with SP1&lt;br /&gt;System model: DELL OptiPlex GX1&lt;br /&gt;Processor: Pentium III, 500MHz&lt;br /&gt;RAM: 128 MB&lt;br /&gt;&lt;br /&gt;Server2: Server2&lt;br /&gt;OS: Microsoft Windows 2000 Advanced Server with SP1&lt;br /&gt;System model: DELL OptiPlex GX1&lt;br /&gt;Processor: Pentium III, 500MHz&lt;br /&gt;RAM: 128 MB&lt;br /&gt;&lt;br /&gt;Here is the table structure:&lt;br /&gt;CREATE TABLE [dbo].[tblPriceDefn] (&lt;br /&gt;[ConfigID] [numeric](19, 0) NOT NULL ,&lt;br /&gt;[PriceListID] [varchar] (40) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,&lt;br /&gt;[ValidityDate] [datetime] NOT NULL ,&lt;br /&gt;[Price] [money] NOT NULL&lt;br /&gt;) ON [PRIMARY]&lt;br /&gt;GO&lt;br /&gt;ALTER TABLE [dbo].[tblPriceDefn] WITH NOCHECK ADD&lt;br /&gt;CONSTRAINT [PK_PriceDefn] PRIMARY KEY CLUSTERED&lt;br /&gt;(&lt;br /&gt;[ConfigID],&lt;br /&gt;[PriceListID],&lt;br /&gt;[ValidityDate]&lt;br /&gt;) ON [PRIMARY]&lt;br /&gt;&lt;br /&gt;Horizontal partitioning of the data:&lt;br /&gt;For this evaluation purpose I took the tblPriceDefn table which has 5 Million rows. I divided the table into two equal halves depending upon the value of the PriceListID column. Stored the first half on the first server (Server1) and the second half on the second server (Server2). Then I created a distributed partioned view named View1 in the first server (Server1) which cobmines both the halves of the table tblPriceDefn. Here is the view definition:&lt;br /&gt;&lt;br /&gt;CREATE VIEW View1&lt;br /&gt;AS&lt;br /&gt;SELECT * FROM [Server1].test.dbo.table1&lt;br /&gt;UNION ALL&lt;br /&gt;SELECT * FROM [Server2\inst1].test.dbo.table1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Performance testing:&lt;br /&gt;The following queries are executed on the first server locally on both the base table and the partitioned view and the response times were recorded. Each query is executed 5 times and the average response time is recorded&lt;br /&gt;&lt;br /&gt;Query 1:&lt;br /&gt;--On the base table:&lt;br /&gt;SELECT&lt;br /&gt;PriceListID,&lt;br /&gt;COUNT(*) [# of rows]&lt;br /&gt;FROM&lt;br /&gt;ArenaDBRel2.dbo.tblPriceDefn&lt;br /&gt;GROUP BY&lt;br /&gt;PriceListID&lt;br /&gt;ORDER BY&lt;br /&gt;PriceListID&lt;br /&gt;&lt;br /&gt;Average response time on the base table with 5 million rows: 59 seconds&lt;br /&gt;&lt;br /&gt;--On the partitioned view:&lt;br /&gt;SELECT&lt;br /&gt;PriceListID,&lt;br /&gt;COUNT(*) [# of rows]&lt;br /&gt;FROM&lt;br /&gt;test.dbo.View1&lt;br /&gt;GROUP BY&lt;br /&gt;PriceListID&lt;br /&gt;ORDER BY&lt;br /&gt;PriceListID&lt;br /&gt;&lt;br /&gt;Average response time on the partitioned view : 41 seconds&lt;br /&gt;A gain of 18 seconds which is a 30% improvement in performance&lt;br /&gt;&lt;br /&gt;Query 2:&lt;br /&gt;&lt;br /&gt;--On the base table:&lt;br /&gt;SELECT&lt;br /&gt;DISTINCT PriceListID&lt;br /&gt;FROM&lt;br /&gt;ArenaDBRel2.dbo.tblPriceDefn&lt;br /&gt;Average response time on the base table with 5 million rows: 45 seconds&lt;br /&gt;&lt;br /&gt;--On the partitioned view:&lt;br /&gt;SELECT&lt;br /&gt;DISTINCT PriceListID&lt;br /&gt;FROM&lt;br /&gt;test.dbo.View1&lt;br /&gt;&lt;br /&gt;Average response time on the partitioned view: 32 seconds&lt;br /&gt;A gain of 13 seconds which is a 28% improvement in performance&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Query 3:&lt;br /&gt;&lt;br /&gt;--On the base table:&lt;br /&gt;SELECT&lt;br /&gt;PriceListID,&lt;br /&gt;ConfigID,&lt;br /&gt;Price&lt;br /&gt;FROM&lt;br /&gt;ArenaDBRel2.dbo.tblPriceDefn&lt;br /&gt;WHERE&lt;br /&gt;PriceListID = 'M05-05'&lt;br /&gt;OR&lt;br /&gt;PriceListID = 'M10-01'&lt;br /&gt;&lt;br /&gt;Average response time on the base table with 5 million rows: 59 seconds&lt;br /&gt;--On the partitioned view:&lt;br /&gt;SELECT&lt;br /&gt;PriceListID,&lt;br /&gt;ConfigID,&lt;br /&gt;Price&lt;br /&gt;FROM&lt;br /&gt;test.dbo.View1&lt;br /&gt;WHERE&lt;br /&gt;PriceListID = 'M05-05'&lt;br /&gt;OR&lt;br /&gt;PriceListID = 'M10-01'&lt;br /&gt;&lt;br /&gt;Average response time on the partitioned view: 44 seconds&lt;br /&gt;A gain of 15 seconds which is a 25% improvement in performance&lt;br /&gt;&lt;br /&gt;Conclusion:&lt;br /&gt;The federated database servers feature in SQL Server 2000 is a very useful one and we can be sure to see performance gains in the query response times. As I mentioned earlier, this is a very simple evaluation of the feature. I am going to try it out with more concurrent connections and complicated queries and will post more information on this site. Be sure to check back after a while! Please let me know if you have any suggestions regarding this page!&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-2721240001814723882?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='text/html' href='http://vyaskn.tripod.com/federated.htm' length='0'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/2721240001814723882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=2721240001814723882' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2721240001814723882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2721240001814723882'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/evaluation-of-fedarated-databases.html' title='Evaluation  of fedarated databases.'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-4176766346087585100</id><published>2009-06-28T18:54:00.000-07:00</published><updated>2009-06-28T19:15:30.987-07:00</updated><title type='text'>SQL Server security model</title><content type='html'>Security is a major concern for the modern age systems/network/database administrators. It is natural for an administrator to worry about hackers and external attacks while implementing security. But there is more to it. It is essential to first implement security within the organization, to make sure right people have access to the right data. Without these security measures in place, you might find someone destroying your valuable data, or selling your company's secrets to your competitors or someone invading the privacy of others. Primarily a security plan must identify which users in the organization can see which data and perform which activities in the database.&lt;br /&gt;&lt;br /&gt;SQL Server security model&lt;br /&gt;To be able to access data from a database, a user must pass through two stages of authentication, one at the SQL Server level and the other at the database level. These two stages are implemented using Logins names and User accounts respectively. A valid login is required to connect to SQL Server and a valid user account is required to access a database.&lt;br /&gt;&lt;br /&gt;    Login: A valid login name is required to connect to an SQL Server instance. A login could be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A Windows NT/2000 login that has been granted access to SQL Server&lt;/li&gt;&lt;li&gt;An SQL Server login, that is maintained within SQL Server&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;    These login names are maintained within the master database. So, it is essential to backup the master database after adding new logins to SQL Server.&lt;br /&gt;&lt;br /&gt;    User: A valid user account within a database is required to access that database. User accounts are specific to a database. All permissions and ownership of objects in the database are controlled by the user account. SQL Server logins are associated with these user accounts. A login can have associated users in different databases, but only one user per database.&lt;br /&gt;&lt;br /&gt;During a new connection request, SQL Server verifies the login name supplied, to make sure, that login is authorized to access SQL Server. This verification is called Authentication. SQL Server supports two authentication modes:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Windows authentication mode: With Windows authentication, you do not have to specify a login name and password, to connect to SQL Server. Instead, your access to SQL Server is controlled by your Windows NT/2000 account (or the group to which your account belongs to), that you used to login to the Windows operating system on the client computer/workstation. A DBA must first specify to SQL Server, all the Microsoft Windows NT/2000 accounts or groups that can connect to SQL Server&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Mixed mode: Mixed mode allows users to connect using Windows authentication or SQL Server authentication. Your DBA must first create valid SQL Server login accounts and passwords. These are not related to your Microsoft Windows NT/2000 accounts. With this authentication mode, you must supply the SQL Server login and password when you connect to SQL Server. If you do not specify SQL Server login name and password, or request Windows Authentication, you will be authenticated using Windows Authentication.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Point to note is that, whatever mode you configure your SQL Server to use, you can always login using Windows authentication.&lt;br /&gt;&lt;br /&gt;Windows authentication is the recommended security mode, as it is more secure and you don't have to send login names and passwords over the network. You should avoid mixed mode, unless you have a non-Windows NT/2000 environment or when your SQL Server is installed on Windows 95/98 or for backward compatibility with your existing applications.&lt;br /&gt;&lt;br /&gt;SQL Server's authentication mode can be changed using Enterprise Manager (Right click on the server name and click on Properties. Go to the Security tab).&lt;br /&gt;&lt;br /&gt;Authentication mode can also be changed using SQL DMO object model.&lt;br /&gt;&lt;br /&gt;Here is a list of helpful stored procedures for managing logins and users:&lt;br /&gt;&lt;br /&gt;&lt;table style="font-weight: bold;" width="100%" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_addlogin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Creates a new                 login that allows users to connect to SQL Server                 using SQL Server authentication&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_grantlogin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Allows a                 Windows NT/2000 user account or group to connect                 to SQL Server using Windows authentication&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_droplogin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Drops an SQL                 Server login&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_revokelogin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Drops a                 Windows NT/2000 login/group from SQL Server&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_denylogin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Prevents a                 Windows NT/2000 login/group from connecting to                 SQL Server&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_password&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Adds or                 changes the password for an SQL Server login&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helplogins&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Provides                 information about logins and their associated                 users in each database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_defaultdb&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Changes the                 default database for a login&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_grantdbaccess&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Adds an                 associated user account in the current database                 for an SQL Server login or Windows NT/2000 login&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_revokedbaccess&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Drops a user                 account from the current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helpuser                 &lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Reports                 information about the Microsoft users and roles                 in the current database&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Now let's talk about controlling access to objects within the database and managing permissions. Apart from managing permissions at the individual database user level, SQL Server 7.0/2000 implements permissions using roles. A role is nothing but a group to which individual logins/users can be added, so that the permissions can be applied to the group, instead of applying the permissions to all the individual logins/users. There are three types of roles in SQL Server 7.0/2000:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;    Fixed server roles&lt;/li&gt;&lt;li&gt;    Fixed database roles&lt;/li&gt;&lt;li&gt;    Application roles&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Fixed server roles: These are server-wide roles. Logins can be added to these roles to gain the associated administrative permissions of the role. Fixed server roles cannot be altered and new server roles cannot be created. Here are the fixed server roles and their associated permissions in SQL Server 2000:&lt;br /&gt;&lt;br /&gt;&lt;table width="100%" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;Fixed                 server role&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sysadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can perform                 any activity in SQL Server&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;serveradmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can set                 server-wide configuration options, shut down the                 server&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;setupadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can manage                 linked servers and startup procedures&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;securityadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can manage                 logins and CREATE DATABASE permissions, also read                 error logs and change passwords&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;processadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can manage                 processes running in SQL Server&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;dbcreator&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can create,                 alter, and drop databases&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;diskadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can manage                 disk files&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;bulkadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can execute                 BULK INSERT statements&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Here is a list of stored procedures that are helpful in managing fixed server roles:&lt;br /&gt;&lt;br /&gt;&lt;table width="100%" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_addsrvrolemember&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Adds a login                 as a member of a fixed server role&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_dropsrvrolemember&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Removes an SQL                 Server login, Windows user or group from a fixed                 server role&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helpsrvrole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Returns a list                 of the fixed server roles&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helpsrvrolemember&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Returns                 information about the members of fixed server                 roles&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_srvrolepermission&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Returns the                 permissions applied to a fixed server role&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Fixed database roles: Each database has a set of fixed database roles, to which database users can be added. These fixed database roles are unique within the database. While the permissions of fixed database roles cannot be altered, new database roles can be created. Here are the fixed database roles and their associated permissions in SQL Server 2000:&lt;br /&gt;&lt;br /&gt;&lt;table width="100%" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;Fixed                 database role&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_owner&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Has all                 permissions in the database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_accessadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can add or                 remove user IDs&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_securityadmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can manage all                 permissions, object ownerships, roles and role                 memberships&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_ddladmin&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can issue ALL                 DDL, but cannot issue GRANT, REVOKE, or DENY                 statements&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_backupoperator&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can issue                 DBCC, CHECKPOINT, and BACKUP statements&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_datareader&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can select all                 data from any user table in the database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_datawriter&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Can modify any                 data in any user table in the database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_denydatareader&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Cannot select                 any data from any user table in the database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;db_denydatawriter&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Cannot modify                 any data in any user table in the database&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Here is a list of stored procedures that are helpful in managing fixed database roles:&lt;br /&gt;&lt;br /&gt;&lt;table width="100%" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_addrole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Creates a new                 database role in the current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_addrolemember&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Adds a user to                 an existing database role in the current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_dbfixedrolepermission&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Displays                 permissions for each fixed database role&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_droprole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Removes a                 database role from the current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helpdbfixedrole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Returns a list                 of fixed database roles&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helprole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Returns                 information about the roles in the current                 database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_helprolemember&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Returns                 information about the members of a role in the                 current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_droprolemember&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Removes users                 from the specified role in the current database&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Application roles: Application roles are another way of implementing permissions. These are quite different from the server and database roles. After creating and assigning the required permissions to an application role, the client application needs to activate this role at run-time to get the permissions associated with that application role. Application roles simplify the job of DBAs, as they don't have to worry about managing permissions at individual user level. All they need to do is to create an application role and assign permissions to it. The application that is connecting to the database activates the application role and inherits the permissions associated with that role. Here are the characteristics of application roles:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There are no built-in application roles&lt;/li&gt;&lt;li&gt;Application roles contain no members&lt;/li&gt;&lt;li&gt;Application roles need to be activated at run-time, by the application, using a password&lt;/li&gt;&lt;li&gt;Application roles override standard permissions. For example, after activating the application role, the application will lose all the permissions associated with the login/user account used while connecting to SQL Server and gain the permissions associated with the application role.&lt;/li&gt;&lt;li&gt;Application roles are database specific. After activating an application role in a database, if that application wants to run a cross-database transaction, the other database must have a guest user account enabled&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Here are the stored procedures that are required to manage application roles:&lt;br /&gt;&lt;br /&gt;&lt;table width="100%" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_addapprole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Adds an                 application role in the current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_approlepassword&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Changes the                 password of an application role in the current                 database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_dropapprole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Drops an                 application role from the current database&lt;/span&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;&lt;strong&gt;sp_setapprole&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;                 &lt;td&gt;&lt;span style="font-family:MS Serif;font-size:130%;"&gt;Activates the                 permissions associated with an application role                 in the current database&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Now that we discussed different kinds of roles, let's talk about granting/revoking permissions to/from database users and database roles and application roles. The following T-SQL commands are used to manage permissions at the user and role level.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;GRANT: Grants the specific permission (Like SELECT, DELETE etc.) to the specified user or role in the current database&lt;/li&gt;&lt;li&gt;REVOKE: Removes a previously granted or denied permission from a user or role in the current database&lt;/li&gt;&lt;li&gt;DENY: Denies a specific permission to the specified user or role in the current database&lt;/li&gt;&lt;/ul&gt;Using the above commands, permissions can be granted/denied/revoked to users/roles on all database objects. You can manage permissions at as low as the column level.&lt;br /&gt;&lt;br /&gt;Note: There is no way to manage permissions at the row level. That is, in a given table, you can't grant SELECT permission on a specific row to User1 and deny SELECT permission on another row to User2. This kind of security can be implemented by using views and stored procedures effectively. Click here to read about row level security implementation in SQL Server databases. Just an FYI, Oracle has a feature called "Virtual Private Databases" (VPD) that allows DBAs to configure permissions at row level.&lt;br /&gt;SQL Server security best practices&lt;br /&gt;Here is an ideal implementation of security in a Windows NT/2000 environment with SQL Server 7.0/2000 database server:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Configure SQL Server to use Windows authentication mode&lt;/li&gt;&lt;li&gt;Depending upon the data access needs of your domain users, group them into different global groups in the domain&lt;/li&gt;&lt;li&gt;Consolidate these global groups from all the trusted domains into the Windows NT/2000 local groups in your SQL Server computer&lt;/li&gt;&lt;li&gt;The Windows NT/2000 local groups are then granted access to log into the SQL Server&lt;/li&gt;&lt;li&gt;Add these Windows NT/2000 local groups to the required fixed server roles in SQL Server&lt;/li&gt;&lt;li&gt;Associate these local group logins with individual user accounts in the databases and grant them the required permissions using the database roles.&lt;/li&gt;&lt;li&gt;Create custom database roles if required, for finer control over permissions&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Here is a security checklist and some standard security practices and tips:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Restrict physical access to the SQL Server computer. Always lock the server while not in use.&lt;/li&gt;&lt;li&gt;Make sure, all the file and disk shares on the SQL Server computer are read-only. In case you have read-write shares, make sure only the right people have access to those shares.&lt;/li&gt;&lt;li&gt;Use the NTFS file system as it provides advanced security and recovery features.&lt;/li&gt;&lt;li&gt;Prefer Windows authentication to mixed mode. If mixed mode authentication is inevitable, for backward compatibility reasons, make sure you have complex passwords for sa and all other SQL Server logins. It is recommended to have mixed case passwords with a few numbers and/or special characters, to counter the dictionary based password guessing tools and user identity spoofing by hackers.&lt;/li&gt;&lt;li&gt;Rename the Windows NT/2000 Administrator account on the SQL Server computer to discourage hackers from guessing the administrator password.&lt;/li&gt;&lt;li&gt;In a website environment, keep your databases on a different computer than the one running the web service. In other words, keep your SQL Server off the Internet, for security reasons.&lt;/li&gt;&lt;li&gt;Keep yourself up-to-date with the information on latest service packs and security patches released by Microsoft. Carefully evaluate the service packs and patches before applying them on the production SQL Server. Bookmark this page for the latest in the security area from Microsoft: http://www.microsoft.com/security/&lt;/li&gt;&lt;li&gt;If it is appropriate for your environment, hide the SQL Server service from appearing in the server enumeration box in Query Analyzer, using the /HIDDEN:YES switch of NET CONFIG SERVER command.&lt;/li&gt;&lt;li&gt;Enable login auditing at the Operating System and SQL Server level. Examine the audit for login failure events and look for trends to detect any possible intrusion.&lt;/li&gt;&lt;li&gt;If it fits your budget, use Intrusion Detection Systems (IDS), especially on high-risk online database servers. IDS can constantly analyze the inbound network traffic, look for trends and detect Denial of Service (DoS) attacks and port scans. IDS can be configured to alert the administrators upon detecting a particular trend.&lt;/li&gt;&lt;li&gt;Disable guest user account of Windows. Drop guest user from production databases using sp_dropuser.&lt;/li&gt;&lt;li&gt;Do not let your applications query and manipulate your database directly using SELECT/INSERT/UPDATE/DELETE statements. Wrap these commands within stored procedures and let your applications call these stored procedures. This helps centralize business logic within the database, at the same time hides the internal database structure from client applications.&lt;/li&gt;&lt;li&gt;Let your users query views instead of giving them access to the underlying base tables.&lt;/li&gt;&lt;li&gt;Discourage applications from executing dynamic SQL statements. To execute a dynamic SQL statement, users need explicit permissions on the underlying tables. This defeats the purpose of restricting access to base tables using stored procedures and views.&lt;/li&gt;&lt;li&gt;Don't let applications accept SQL commands from users and execute them against the database. This could be dangerous (known as SQL injection), as a skilled user can input commands that can destroy the data or gain unauthorized access to sensitive information.&lt;/li&gt;&lt;li&gt;Take advantage of the fixed server and database roles by assigning users to the appropriate roles. You could also create custom database roles that suit your needs.&lt;/li&gt;&lt;li&gt;Carefully choose the members of the sysadmin role, as the members of the sysadmin role can do anything in the SQL Server. Note that, by default, the Windows NT/2000 local administrators group is a part of the sysadmin fixed server role.&lt;/li&gt;&lt;li&gt;Constantly monitor error logs and event logs for security related alerts and errors.&lt;/li&gt;&lt;li&gt;SQL Server error logs can reveal a great deal of information about your server. So, secure your error logs by using NTFS permissions.&lt;/li&gt;&lt;li&gt;Secure your registry by restricting access to the SQL Server specific registry keys like HKEY_LOCAL_MACHINE\Software\Microsoft\MSSQLServer.&lt;/li&gt;&lt;li&gt;If your databases contain sensitive information, consider encrypting the sensitive pieces (like credit card numbers and Social Security Numbers (SSN)). There are undocumented encryption functions in SQL Server, but I wouldn't recommend those. If you have the right skills available in your organization, develop your own encryption/decryption modules using Crypto API or other encryption libraries.&lt;/li&gt;&lt;li&gt;If you are running SQL Server 7.0, you could use the encryption capabilities of the Multi-Protocol net library for encrypted data exchange between the client and SQL Server. SQL Server 2000 supports encryption over all protocols using Secure Socket Layer (SSL). See SQL Server 7.0 and 2000 Books Online (BOL) for more information on this topic. Please note that, enabling encryption is always a tradeoff between security and performance, because of the additional overhead of encryption and decryption.&lt;/li&gt;&lt;li&gt;Prevent unauthorized access to linked servers by deleting the linked server entries that are no longer needed. Pay special attention to the login mapping between the local and remote servers. Use logins with the bare minimum privileges for configuring linked servers.&lt;/li&gt;&lt;li&gt;DBAs generally tend to run SQL Server service using a domain administrator account. That is asking for trouble. A malicious SQL Server user could take advantage of these domain admin privileges. Most of the times, a local administrator account would be more than enough for SQL Server service.&lt;/li&gt;&lt;li&gt;DBAs also tend to drop system stored procedures like xp_cmdshell and all the OLE automation stored procedures (sp_OACreate and the likes). Instead of dropping these procedures, deny EXECUTE permission on them to specific users/roles. Dropping these procedures would break some of the SQL Server functionality.&lt;/li&gt;&lt;li&gt;Be prompt in dropping the SQL Server logins of employees leaving the organization. Especially, in the case of a layoff, drop the logins of those poor souls ASAP as they could do anything to your data out of frustration.&lt;/li&gt;&lt;li&gt;When using mixed mode authentication, consider customizing the system stored procedure sp_password, to prevent users from using simple and easy-to-guess passwords.&lt;/li&gt;&lt;li&gt;To setup secure data replication over Internet or Wide Area Networks (WAN), implement Virtual Private Networks (VPN) . Securing the snapshot folder is important too, as the snapshot agent exports data and object scripts from published databases to this folder in the form of text files. Only the replication agents should have access to the snapshot folder.&lt;/li&gt;&lt;li&gt;It is good to have a tool like Lumigent Log Explorer handy, for a closer look at the transaction log to see who is doing what in the database.&lt;/li&gt;&lt;li&gt;Do not save passwords in your .udf files, as the password gets stored in clear text.&lt;/li&gt;&lt;li&gt;If your database code is proprietary, encrypt the definition of stored procedures, triggers, views and user defined functions using the WITH ENCRYPTION clause. dbLockdown is a tool that automates the insertion of the WITH ENCRYPTION clause and handles all the archiving of encrypted database objects so that they can be restored again in a single click. Click here to find out more information about this product.&lt;/li&gt;&lt;li&gt;In database development environments, use a source code control system like Visual Source Safe (VSS) or Rational Clear Case. Control access to source code by creating users in VSS and giving permissions by project. Reserve the 'destroy permanently' permission for VSS administrator only. After project completion, lock your VSS database or leave your developers with just read-only access.&lt;/li&gt;&lt;li&gt;Store the data files generated by DTS or BCP in a secure folder/share and delete these files once you are done.&lt;/li&gt;&lt;li&gt;Install anti-virus software on the SQL Server computer, but exclude your database folders from regular scans. Keep your anti-virus signature files up to date.&lt;/li&gt;&lt;li&gt;SQL Server 2000 allows you to specify a password for backups. If a backup is created with a password, you must provide that password to restore from that backup. This discourages unauthorized access to backup files.&lt;/li&gt;&lt;li&gt;Windows 2000 introduced Encrypted File System (EFS) that allows you to encrypt individual files and folders on an NTFS partition. Use this feature to encrypt your SQL Server database files. You must encrypt the files using the service account of SQL Server. When you want to change the service account of SQL Server, you must decrypt the files, change the service account and encrypt the files again with the new service account.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-4176766346087585100?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='text/html' href='http://vyaskn.tripod.com/sql_server_security_best_practices.htm' length='0'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/4176766346087585100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=4176766346087585100' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/4176766346087585100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/4176766346087585100'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/sql-server-security-model.html' title='SQL Server security model'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-28224460346108216</id><published>2009-06-23T20:40:00.001-07:00</published><updated>2009-06-28T18:54:29.164-07:00</updated><title type='text'>Q &amp; A</title><content type='html'>&lt;strong&gt;What is a self join? Explain it with an example.&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Self join is just like any other join, except that two instances of the same table will be joined in the query. Here is an example: Employees table which contains rows for normal employees as well as managers. So, to find out the managers of all the employees, you need a self join.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;CREATE TABLE emp &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;empid int,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;mgrid int,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;empname char(10)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;INSERT emp SELECT 1,2,'Vyas'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;INSERT emp SELECT 2,3,'Mohan'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;INSERT emp SELECT 3,NULL,'Shobha'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;INSERT emp SELECT 4,2,'Shridhar'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;INSERT emp SELECT 5,2,'Sourabh'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;SELECT t1.empname [Employee], t2.empname [Manager]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;FROM emp t1, emp t2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;WHERE t1.mgrid = t2.empid&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Here's an advanced query using a LEFT OUTER JOIN that even returns the employees without managers (super bosses)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;SELECT t1.empname [Employee], COALESCE(t2.empname, 'No manager') [Manager]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;FROM emp t1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;LEFT OUTER JOIN&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;emp t2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;ON&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;t1.mgrid = t2.empid &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There is a trigger defined for INSERT operations on a table, in an OLTP system. The trigger is written to instantiate a COM object and pass the newly insterted rows to it for some custom processing. What do you think of this implementation? Can this be implemented better?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Instantiating COM objects is a time consuming process and since you are doing it from within a trigger, it slows down the data insertion process. Same is the case with sending emails from triggers. This scenario can be better implemented by logging all the necessary data into a separate table, and have a job which periodically checks this table and does the needful.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are triggers? How many triggers you can have on a table? How to invoke a trigger on demand?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Triggers are special kind of stored procedures that get executed automatically when an INSERT, UPDATE or DELETE operation takes place on a table. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;In SQL Server 6.5 you could define only 3 triggers per table, one for INSERT, one for UPDATE and one for DELETE. From SQL Server 7.0 onwards, this restriction is gone, and you could create multiple triggers per each action. But in 7.0 there's no way to control the order in which the triggers fire. In SQL Server 2000 you could specify which trigger fires first or fires last using sp_settriggerorder&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Triggers can't be invoked on demand. They get triggered only when an associated action (INSERT, UPDATE, DELETE) happens on the table on which they are defined.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Triggers are generally used to implement business rules, auditing. Triggers can also be used to extend the referential integrity checks, but wherever possible, use constraints for this purpose, instead of triggers, as constraints are much faster.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Till SQL Server 7.0, triggers fire only after the data modification operation happens. So in a way, they are called post triggers. But in SQL Server 2000 you could create pre triggers also. Search SQL Server 2000 books online for INSTEAD OF triggers. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Also check out books online for 'inserted table', 'deleted table' and COLUMNS_UPDATED()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is the system function to get the current user's user id?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;USER_ID(). Also check out other system functions like USER_NAME(), SYSTEM_USER, SESSION_USER, CURRENT_USER, USER, SUSER_SID(), HOST_NAME(). &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is an extended stored procedure? Can you instantiate a COM object by using T-SQL?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;An extended stored procedure is a function within a DLL (written in a programming language like C, C++ using Open Data Services (ODS) API) that can be called from T-SQL, just the way we call normal stored procedures using the EXEC statement. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Yes, you can instantiate a COM (written in languages like VB, VC++) object from T-SQL by using sp_OACreate stored procedure. Also see books online for sp_OAMethod, sp_OAGetProperty, sp_OASetProperty, sp_OADestroy. For an example of creating a COM object in VB and calling it from T-SQL, see 'My code library' section of this site. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Can you have a nested transaction?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Yes, very much. Check out BEGIN TRAN, COMMIT, ROLLBACK, SAVE TRAN and @@TRANCOUNT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is a join and explain different types of joins.&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Joins are used in queries to explain how different tables are related. Joins also let you select data from a table depending upon data from another table.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Types of joins: INNER JOINs, OUTER JOINs, CROSS JOINs. OUTER JOINs are further classified as LEFT OUTER JOINS, RIGHT OUTER JOINS and FULL OUTER JOINS.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Write down the general syntax for a SELECT statements covering all the options.&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Here's the basic syntax: &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;SELECT select_list&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;[INTO new_table_]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;FROM table_source&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;[WHERE search_condition]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;[GROUP BY group_by_expression]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;[HAVING search_condition]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;[ORDER BY order_expression [ASC | DESC] ]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are cursors? Explain different types of cursors. What are the disadvantages of cursors? How can you avoid cursors?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Cursors allow row-by-row prcessing of the resultsets.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Types of cursors: Static, Dynamic, Forward-only, Keyset-driven. See books online for more information.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Disadvantages of cursors: Each time you fetch a row from the cursor, it results in a network roundtrip, where as a normal SELECT query makes only one rowundtrip, however large the resultset is. Cursors are also costly because they require more resources and temporary storage (results in more IO operations). Furthere, there are restrictions on the SELECT statements that can be used with some types of cursors.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Most of the times, set based operations can be used instead of cursors. Here is an example:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;If you have to give a flat hike to your employees using the following criteria:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Salary between 30000 and 40000 -- 5000 hike&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Salary between 40000 and 55000 -- 7000 hike&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Salary between 55000 and 65000 -- 9000 hike&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;In this situation many developers tend to use a cursor, determine each employee's salary and update his salary according to the above formula. But the same can be achieved by multiple update statements or can be combined in a single UPDATE statement as shown below:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;UPDATE tbl_emp SET salary =&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;CASE WHEN salary BETWEEN 30000 AND 40000 THEN salary + 5000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;WHEN salary BETWEEN 40000 AND 55000 THEN salary + 7000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;WHEN salary BETWEEN 55000 AND 65000 THEN salary + 10000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Another situation in which developers tend to use cursors: You need to call a stored procedure when a column in a particular row meets certain condition. You don't have to use cursors for this. This can be achieved using WHILE loop, as long as there is a unique key to identify each row.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is database replicaion? What are the different types of replication you can set up in SQL Server?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Replication is the process of copying/moving data between databases on the same or different servers. SQL Server supports the following types of replication scenarios:&lt;/span&gt;&lt;br /&gt;&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Snapshot replication&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Transactional replication (with immediate updating subscribers, with queued updating subscribers)&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Merge replication&lt;/strong&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Explian different types of BACKUPs avaialabe in SQL Server? Given a particular scenario, how would you go about choosing a backup plan?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Types of backups you can create in SQL Sever 7.0+ are Full database backup, differential database backup, transaction log backup, filegroup backup. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are the different ways of moving data/databases between servers and databases in SQL Server?&lt;br /&gt;A.&lt;span style="font-weight: normal;"&gt;There are lots of options available, you have to choose your option depending upon your requirements. Some of the options you have are: BACKUP/RESTORE, dettaching and attaching databases, replication, DTS, BCP, logshipping, INSERT...SELECT, SELECT...INTO, creating INSERT scripts to generate data.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are statistics, under what circumstances they go out of date, how do you update them&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Statistics determine the selectivity of the indexes. If an indexed column has unique values then the selectivity of that index is more, as opposed to an index with non-unique values. Query optimizer uses these indexes in determining whether to choose an index or not while executing a query. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Some situations under which you should update statistics:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;1) If there is significant change in the key values in the index&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;2) If a large amount of data in an indexed column has been added, changed, or removed (that is, if the distribution of key values has changed), or the table has been truncated using the TRUNCATE TABLE statement and then repopulated&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;3) Database is upgraded from a previous version&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Look up SQL Server books online for the following commands: UPDATE STATISTICS, STATS_DATE, DBCC SHOW_STATISTICS, CREATE STATISTICS, DROP STATISTICS, sp_autostats, sp_createstats, sp_updatestats&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As a part of your job, what are the DBCC commands that you commonly use for database maintenance?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.DBCC CHECKDB, DBCC CHECKTABLE, DBCC CHECKCATALOG, DBCC CHECKALLOC, DBCC SHOWCONTIG, DBCC SHRINKDATABASE, DBCC SHRINKFILE etc. But there are a whole load of DBCC commands which are very useful for DBAs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;How to restart SQL Server in single user mode? How to start SQL Server in minimal configuration mode?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;SQL Server can be started from command line, using the SQLSERVR.EXE. This EXE has some very important parameters with which a DBA should be familiar with. -m is used for starting SQL Server in single user mode and -f is used to start the SQL Server in minimal confuguration mode. Check out SQL Server books online for more parameters and their explanations.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Explain CREATE DATABASE syntax&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Many of us are used to craeting databases from the Enterprise Manager or by just issuing the command: CREATE DATABAE MyDB. But what if you have to create a database with two filegroups, one on drive C and the other on drive D with log on drive E with an initial size of 600 MB and with a growth factor of 15%? That's why being a DBA you should be familiar with the CREATE DATABASE syntax. Check out SQL Server books online for more information.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is blocking and how would you troubleshoot it?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Blocking happens when one connection from an application holds a lock and a second connection requires a conflicting lock type. This forces the second connection to wait, blocked on the first. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is a deadlock and what is a live lock? How will you go about resolving deadlocks?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Deadlock is a situation when two processes, each having a lock on one piece of data, attempt to acquire a lock on the other's piece. Each process  would wait indefinitely for the other to release the lock, unless one of the user processes is terminated. SQL Server detects deadlocks and terminates one user's process.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A livelock is one, where a  request for an exclusive lock is repeatedly denied because a series of overlapping shared locks keeps interfering. SQL Server detects the situation after four denials and refuses further shared locks. A livelock also occurs when read transactions monopolize a table or page, forcing a write transaction to wait indefinitely.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What are the steps you will take, if you are tasked with securing an SQL Server?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Again this is another open ended question. Here are some things you could talk about: Preferring NT authentication, using server, databse and application roles to control access to the data, securing the physical database files using NTFS permissions, using an unguessable SA password, restricting physical access to the SQL Server, renaming the Administrator account on the SQL Server computer, disabling the Guest account, enabling auditing, using multiprotocol encryption, setting up SSL, setting up firewalls, isolating SQL Server from the web server etc.&lt;a href="http://vyaskn.tripod.com/sql_server_security_best_practices.htm"&gt;&lt;br /&gt;http://vyaskn.tripod.com/sql_server_security_best_practices.htm&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are the steps you will take to improve performance of a poor performing query?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.This is a very open ended question and there could be a lot of reasons behind the poor performance of a query. But some general issues that you could talk about would be: No indexes, table scans, missing or out of date statistics, blocking, excess recompilations of stored procedures, procedures and triggers without SET NOCOUNT ON, poorly written query with unnecessarily complicated joins, too much normalization, excess usage of cursors and temporary tables.&lt;br /&gt;Some of the tools/ways that help you troubleshooting performance problems are: SET SHOWPLAN_ALL ON, SET SHOWPLAN_TEXT ON, SET STATISTICS IO ON, SQL Server Profiler, Windows NT /2000 Performance monitor, Graphical execution plan in Query Analyzer.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;What is RAID and what are different types of RAID configurations?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;RAID stands for Redundant Array of Inexpensive Disks, used to provide fault tolerance to database servers. There are six RAID levels 0 through 5 offering different levels of performance, fault tolerance.&lt;br /&gt;&lt;a href="http://www.raid-advisory.com/"&gt;http://www.raid-advisory.com/&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;What is an index? What are the types of indexes? How many clustered indexes can be created on a table? I create a separate index on each column of a table. what are the advantages and disadvantages of this approach?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Indexes in SQL Server are similar to the indexes in books. They help SQL Server retrieve the data quicker.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;Indexes are of two types. Clustered indexes and non-clustered indexes. When you craete a clustered index on a table, all the rows in the table are stored in the order of the clustered index key. So, there can be only one clustered index per table. Non-clustered indexes have their own storage separate from the table data storage. Non-clustered indexes are stored as B-tree structures (so do clustered indexes), with the leaf level nodes having the index key and it's row locater. The row located could be the RID or the Clustered index key, depending up on the absence or presence of clustered index on the table.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;If you create an index on each column of a table, it improves the query performance, as the query optimizer can choose from all the existing indexes to come up with an efficient execution plan. At the same t ime, data modification operations (such as INSERT, UPDATE, DELETE) will become slow, as every time data changes in the table, all the indexes need to be updated. Another disadvantage is that, indexes need disk space, the more indexes you have, more disk space is used.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What's the difference between DELETE TABLE and TRUNCATE TABLE commands?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.DELETE TABLE is a logged operation, so the deletion of each row gets logged in the transaction log, which makes it slow. TRUNCATE TABLE also deletes all the rows in a table, but it won't log the deletion of each row, instead it logs the deallocation of the data pages of the table, which makes it faster. Of course, TRUNCATE TABLE can be rolled back.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is lock escalation?&lt;br /&gt;A.&lt;span style="font-weight: normal;"&gt;Lock escalation is the process of converting a lot of low level locks (like row locks, page locks) into higher level locks (like table locks). Every lock is a memory structure too many locks would mean, more memory being occupied by locks. To prevent this from happening, SQL Server escalates the many fine-grain locks to fewer coarse-grain locks. Lock escalation threshold was definable in SQL Server 6.5, but from SQL Server 7.0 onwards it's dynamically managed by SQL Server.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CREATE INDEX myIndex ON myTable(myColumn)&lt;br /&gt;What type of Index will get created after executing the above statement?&lt;br /&gt;A.&lt;span style="font-weight: normal;"&gt;Non-clustered index. Important thing to note: By default a clustered index gets created on the primary key, unless specified otherwise.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Explain different isolation levels&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;An isolation level determines the degree of isolation of data between concurrent transactions. The default SQL Server isolation level is Read Committed. Here are the other isolation levels (in the ascending order of isolation): Read Uncommitted, Read Committed, Repeatable Read, Serializable. See SQL Server books online for an explanation of the isolation levels. Be sure to read about SET TRANSACTION ISOLATION LEVEL, which lets you customize the isolation level at the connection level.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is a transaction and what are ACID properties?&lt;br /&gt;A.&lt;span style="font-weight: normal;"&gt;A transaction is a logical unit of work in which, all the steps must be performed or none. ACID stands for Atomicity, Consistency, Isolation, Durability. These are the properties of a transaction.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are defaults? Is there a column to which a default can't be bound?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.A default is a value that will be used by a column, if no value is supplied to that column while inserting data. IDENTITY columns and timestamp columns can't have defaults bound to them.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Define candidate key, alternate key, composite key.&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A candidate key is one that can identify each row of a table uniquely. Generally a candidate key becomes the primary key of the table. If the table has more than one candidate key, one of them will become the primary key, and the rest are called alternate keys. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A key formed by combining at least two or more columns is called composite key.&lt;br /&gt;&lt;br /&gt;What is bit datatype and what's the information that can be stored inside a bit column?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Bit datatype is used to store boolean information like 1 or 0 (true or false). Untill SQL Server 6.5 bit datatype could hold either a 1 or 0 and there was no support for NULL. But from SQL Server 7.0 onwards, bit datatype can represent a third state, which is NULL. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are user defined datatypes and when you should go for them?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.User defined datatypes let you extend the base SQL Server datatypes by providing a descriptive name, and format to the database. Take for example, in your database, there is a column called Flight_Num which appears in many tables. In all these tables it should be varchar(8). In this case you could create a user defined datatype called Flight_num_type of varchar(8) and use it across all your tables. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What's the difference between a primary key and a unique key?&lt;br /&gt;&lt;span style="font-weight: normal;"&gt;A.Both primary key and unique enforce uniqueness of the column on which they are defined. But by default primary key creates a clustered index on the column, where are unique creates a nonclustered index by default. Another major difference is that, primary key doesn't allow NULLs, but unique key allows one NULL only.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;How you can rename a database ?&lt;br /&gt;       &lt;/strong&gt;A. To rename a database first get the database into Single user mode . by using the query below ( run these query in query analyzer) &lt;p&gt;ALTER DATABASE DBMydb            SET SINGLE_USER          WITH ROLLBACK IMMEDIATE          &lt;/p&gt;&lt;p&gt;then rename the database using sp_rename          &lt;/p&gt;&lt;p&gt;sp_renamedb 'DBMydb', 'DBmydb_new'         &lt;/p&gt;&lt;p&gt;then change the access mode of the database to multiuser         &lt;/p&gt;&lt;p&gt;ALTER DATABASE DBmydb_new          SET MULTI_USER                 &lt;/p&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;What is mean by suspect status of a database ?&lt;br /&gt;        &lt;/strong&gt;A. SQL Server gives a database 'suspect' status when it is unable to recover the database . reasons may be many , may be a torn page detection , may be datafile location no found.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many access mode of database are in MSSQL&lt;br /&gt;       &lt;/strong&gt;A there are three access mode of a database SINGLE_USER , RESTRICTED_USER and MULTI_USER . SINGLE_USER mode restricts database access to one user Connection. RESTRICTED_USER mode restricts database access to db_owner, dbcreator, and sysadmin roles. All other users are disconnected.MULTI_USER mode lets all users with proper access connect to the database.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;What are the default databases in MSSQL Server Instance after Fresh installation&lt;br /&gt;        &lt;/strong&gt;A. there are 4 default databases .       &lt;ul&gt;&lt;li&gt;&lt;em&gt;Master&lt;/em&gt;&lt;br /&gt;         This is your most critical database, and is the core of your SQL Server implementation.&lt;br /&gt;         Limit changes and access to this database as much as possible. Without the master&lt;br /&gt;       database, your SQL Server instance will not start up.          &lt;/li&gt;&lt;li&gt;&lt;em&gt;MSDB&lt;/em&gt;&lt;br /&gt;         This database contains tables that control and track the elements of the SQL Server&lt;br /&gt;         Agent, as well as replication, log shipping (Enterprise Edition), database backup and&lt;br /&gt;         restore history, database maintenance plan configurations and history, and a subset of&lt;br /&gt;         tables participating in replication status and jobs. DTS packages saved to SQL Server are         also stored within this database.          &lt;/li&gt;&lt;li&gt;&lt;em&gt;Model&lt;/em&gt;&lt;br /&gt;         The model database is a template database, which, when modified, will affect the default&lt;br /&gt;         values of databases that are created in the future. For example, if a table is added to the&lt;br /&gt;         model database, future databases created for the SQL Server instance will include this&lt;br /&gt;       table.          &lt;/li&gt;&lt;li&gt;&lt;em&gt;Tempdb&lt;/em&gt;&lt;br /&gt;         The tempdb database is used to hold all temporary tables and temporary stored&lt;br /&gt;         procedures. SQL Server also uses it for internal sorting and query operations (called&lt;br /&gt;         work tables, or spooling). This database is re-created each time SQL Server is started,&lt;br /&gt;       and cannot be used to store permanent tables.        &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;What is replication ?&lt;br /&gt;        &lt;/strong&gt;A. Replication is a process which enables data and database objects to be copied and modified from one database to another across different networks and platforms.the physical seperation of the databases and latency are integral part of the design process in replication. MSSQL Server 2000 permits 3 different kind of replication. they are snapshot,transactional and merge.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many typf of backups are supported by MSSQL ?&lt;/strong&gt;&lt;br /&gt;     A. there are three type of backup     &lt;ul&gt;&lt;li&gt;          Full Database Backup.&lt;/li&gt;&lt;li&gt;Transaction Log Backup&lt;/li&gt;&lt;li&gt;Differential Backup&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Whats is Log Shipping ? &lt;/strong&gt;&lt;br /&gt;A. Log shipping is the process of  backing up of database and transaction log files on a production SQL server, and then restoring them onto a standby server. The key feature of log shipping is that it will automatically backup transaction logs throughout the day (for whatever interval you specify) and automatically restore them on the standby server. This in effect keeps the two SQL Servers in "sync". Should the production server fail, all you have to do is point the users to the new server, and you are all set.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Name the types of Recovery model in SQL Server ?&lt;br /&gt;   &lt;/strong&gt;A. There are thre recovery model in MSSQL Server&lt;br /&gt;•  Simple Recovery Model .&lt;br /&gt;• Full Recovery Model.&lt;br /&gt;• Bulk Logged Recovery Model.    &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;What is a Dead Lock ?&lt;/strong&gt;&lt;br /&gt;A . Deadlock occurs when two users have locks on separate objects and each user wants a lock on the other's object. For example, User1 has a lock on object "A" and wants a lock on object "B" and User2 has a lock on object "B" and wants a lock on object "A". In this case, SQL Server ends a deadlock by choosing the user, who will be a deadlock victim. After that, SQL Server rolls back the breaking user's transaction, sends message number 1205 to notify the user's application about breaking, and then allows the nonbreaking user's process to continue.&lt;br /&gt;     &lt;strong&gt;Note&lt;/strong&gt;. To reduce the chance of a deadlock, you should minimize the size of transactions and transaction times.         &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many type of Locks are there ?&lt;/strong&gt;&lt;br /&gt;     A. There are three main types of locks that SQL Server 7.0/2000 uses&lt;br /&gt;     Shared locks&lt;br /&gt;         Update locks&lt;br /&gt;         Exclusive locks       &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;A database is consists of how many type of files ? Name their extensions&lt;/strong&gt;&lt;br /&gt;     A. A database can consist of &lt;strong&gt;three types&lt;/strong&gt; of file :&lt;br /&gt;      &lt;em&gt;Primary file , Seconday file and transaction logs&lt;/em&gt;&lt;br /&gt;The primary data file is the starting point of the database and points to any other files in the database. If the primary file is not large enough to hold all the data in the database, then secondary files are required.Transaction logs files hold records of updates to the data files, and can be used to recover the database after an error. Every database has at least one transaction log file, and some databases may have more than one.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt; The recommended file name extension for primary data files is .mdf.&lt;br /&gt;       The recommended file name extension for secondary data files is .ndf.&lt;br /&gt;     The recommended file name extension for log files is .ldf   &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many type of indexes are there ? &lt;/strong&gt;&lt;strong&gt;How many Index can be created on a table ?&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt; A.&lt;/strong&gt; there are two type of indexes Clustered and Non-Clustured&lt;strong&gt;,&lt;/strong&gt; 249 Non Clustured and 1 Clustered index&lt;strong&gt; &lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How you can get the last identity value inserted in any table ?&lt;br /&gt;A.&lt;/strong&gt; SQL Server  has a System Variable @@IDENTITY which gives the last identity element value inserted in any table&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many type of Contraints are in MSSQL.&lt;br /&gt;A.&lt;/strong&gt; SQL Server 2000 supports five classes of constraints.&lt;br /&gt;1) NOT NULL&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;2) CHECK&lt;br /&gt;3) UNIQUE&lt;br /&gt;4) PRIMARY KEY&lt;br /&gt;5) FOREIGN KEY   &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How you can trap error in Sql Server&lt;br /&gt;     A. by using @@error .&lt;br /&gt;      &lt;/strong&gt;After each Transact-SQL statement, the server sets the variable to an integer value:&lt;br /&gt;     0—if the statement was successful&lt;br /&gt;     Error number—if the statement has failed          &lt;strong&gt;&lt;br /&gt;&lt;br /&gt;What is @@Fetch_status ?&lt;/strong&gt;&lt;br /&gt;A. @@fetch_status is a function (or global variable) that returns the success code of the last Fetch statement executed during the current connection. It is often used as an exit criterion in loops that fetch records from a cursor.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;Whats the limitation of user defined funtion ? &lt;/strong&gt;&lt;br /&gt;   A User-defined functions have one serious limitation. They cannot have side effects. A &lt;em&gt;function side effect &lt;/em&gt;is any permanent change to resources (such as tables) that have a scope outside of the function (such as a non-temporary table that is not declared in the function). Basically, this requirement means that a function should return a value while changing nothing in the database. it means in short that &lt;em&gt;"user defined function can not use UPDATE / DELETE on permament table objects in MSSQL" &lt;/em&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;In how many ways you can recieve information from stored procedure&lt;br /&gt;   &lt;/strong&gt;A. there are 4 ways to receive information from a stored procedure:&lt;br /&gt;    &lt;em&gt;Resultset , Parameters , Return value ,    A global cursor that can be referenced outside the stored procedure. &lt;/em&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many type of triggers are there in Sql Server.&lt;br /&gt;   &lt;/strong&gt;A. There are two type of triggers&lt;br /&gt;   •  After Triggers&lt;br /&gt;   •  Instead of Triggers  &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;Whats the Difference between  datetime and  smalldatetime datatype in SQL Server .&lt;/strong&gt;&lt;br /&gt;A . The main difference between these two datatypes is in the amount of space they occupy. datetime occupies eight bytes and smalldatetime only four. The difference in size is due to a difference in precision. The precision of smalldatetime is one minute, and it covers dates from January 1, 1900 , through June 6, 2079 , which is usually more than enough. The precision of datetime is 3.33 ms, and it covers dates from January 1, 1753 , to December 31, 9999 .&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many type of authentication method are there in SQL Server 2005 and 2000 and what is that ?&lt;/strong&gt;&lt;br /&gt;     A. There are two type of authentication method in SQL Server 2005 and 2000          &lt;br /&gt;Windows Authentication&lt;br /&gt;SQL Server Authentication&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How can you generate GUID in in Transact-SQL ?&lt;/strong&gt;&lt;br /&gt;A. GUIDs can be generated using the NEWID function.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How many system datatypes are in SQL Server.&lt;/strong&gt;&lt;br /&gt;     A. 27&lt;strong&gt;&lt;br /&gt;&lt;br /&gt;What is the Maximum number of input and output parameters in Stored procedure in SQL Server 2000 ?&lt;br /&gt;   &lt;/strong&gt;A. 1024&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How can we improve stored procedure performance? Explain the performance tuning techniques.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1. Use many WHERE clauses in the SELECT statements.&lt;br /&gt;2. Select only those fields which you really require.&lt;br /&gt;3. Joins are expensive in terms of time. Join the tables using related fields manly indexed fields.&lt;br /&gt;4. Don't use unused tables.&lt;br /&gt;&lt;br /&gt;NOTES: When you execute the stored proc, SQL Server generates an execution plan based on your indexes and statistics available. Now it is possible that the stored proc inserts a lot of rows into some table which is used in another statement in a join and the plan that was built is not efficient for the subsequent sql statement because the profile of the table has changed since the plan was generated. I would suggest splitting the stored proc into two and the split should be done such that the second proc deals with the updated table. When the second proc is executed, it will have a more realistic execution plan for the updated table.&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-28224460346108216?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/28224460346108216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=28224460346108216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/28224460346108216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/28224460346108216'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/q.html' title='Q &amp; A'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-6582936946647858494</id><published>2009-06-03T19:32:00.000-07:00</published><updated>2009-06-03T20:14:21.623-07:00</updated><title type='text'>TRY...CATCH in SQL Server 2005</title><content type='html'>&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;SQL Server 2005 offers a number of new features over its predecessor, including many features aimed at making working with databases more like writing .NET application code. For example, in SQL Server 2005, stored procedures, triggers, UDFs, and so on can be written using any .NET Framework programming language (such as Visual Basic or C#). Another feature, and the focus of this article, is SQL Server 2005's support for TRY...CATCH blocks. TRY...CATCH blocks are the standard approach to exception handling in modern programming languages, and involve: &lt;ul&gt;&lt;li&gt;&lt;b&gt;A TRY Block&lt;/b&gt; - the TRY block contains the instructions that might cause an exception&lt;/li&gt;&lt;li&gt;&lt;b&gt;A CATCH Block&lt;/b&gt; - if an exception occurs from one of the statements in the TRY block, control is branched to the  CATCH block, where the exception can be handled, logged, and so on.&lt;/li&gt;&lt;/ul&gt; &lt;i&gt;See the Wikipedia &lt;a href="http://en.wikipedia.org/wiki/Try-catch_block"&gt;Exception Handling&lt;/a&gt; entry for more information on the TRY...CATCH construct as well as exception handling concepts in general.&lt;/i&gt; &lt;p&gt; Prior to SQL Server 2005, detecting errors resulting from T-SQL statements could only be handled by checking a global error variable, &lt;a href="http://msdn2.microsoft.com/en-US/library/ms188790%28SQL.90%29.aspx"&gt;&lt;code&gt;@@ERROR&lt;/code&gt;&lt;/a&gt;. Because the &lt;code&gt;@@ERROR&lt;/code&gt; variable value is reset after each SQL statement, this antiquated approach leads to rather bloated stored procedures, as the variable must be checked after each statement with code to handle any problems. &lt;/p&gt;&lt;p&gt; The TRY...CATCH block in SQL Server 2005 offers a much more readable syntax and one that developers are more familiar with. In this article we'll look at the new TRY...CATCH block and examine how it can be used to rollback a transaction in the face of an error. Read on to learn more!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  &lt;b&gt;Checking &lt;code&gt;@@ERROR&lt;/code&gt; - the &lt;i&gt;Old&lt;/i&gt; Way of Handling Errors in T-SQL&lt;/b&gt;&lt;br /&gt;SQL Server provides an &lt;code&gt;@@ERROR&lt;/code&gt; variable that indicates the status of the last completed SQL statement in a given batch. If a SQL statement is completed successfully, &lt;code&gt;@@ERROR&lt;/code&gt; is assigned 0. If, however, an error occurs, &lt;code&gt;@@ERROR&lt;/code&gt; is set to the number of the error message. &lt;/p&gt;&lt;p&gt; To see how the &lt;code&gt;@@ERROR&lt;/code&gt; variable can be used, imagine that we have a data-driven web application that maintains employee information. Let's assume that our database has &lt;code&gt;Employees&lt;/code&gt; and &lt;code&gt;EmployeePhoneNumbers&lt;/code&gt; tables, among others. These two tables share a one-to-many relationship; that is, each &lt;code&gt;Employees&lt;/code&gt; record can have an arbitrary number of related records in the &lt;code&gt;EmployeePhoneNumbers&lt;/code&gt; table. There might be one for their office phone, one for their pager, one for their cell phone, and so on. Imagine that our database includes a &lt;a href="http://www.4guysfromrolla.com/webtech/111499-1.shtml"&gt;stored procedure&lt;/a&gt;,  &lt;code&gt;DeleteEmployee&lt;/code&gt;, which is comprised of two &lt;code&gt;DELETE&lt;/code&gt; statements - one to delete the employee's related phone numbers from the system and one to delete the actual employee record: &lt;/p&gt;&lt;p&gt;&lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt;&lt;/code&gt;&lt;pre&gt;CREATE PROCEDURE DeleteEmployee ( @EmployeeID int )&lt;br /&gt;AS&lt;br /&gt;&lt;br /&gt;-- Delete the Employee's phone numbers&lt;br /&gt;DELETE FROM EmployeePhoneNumbers&lt;br /&gt;WHERE EmployeeID = @EmployeeID&lt;br /&gt;&lt;br /&gt;-- Delete the Employee record&lt;br /&gt;DELETE FROM Employees&lt;br /&gt;WHERE EmployeeID = @EmployeeID&lt;br /&gt;&lt;/pre&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; Since we want these two delete statements to be atomic and either both fail or both succeed, we need to wrap up these two statements into a &lt;i&gt;transaction&lt;/i&gt;. By using a transaction, we can rollback the transaction in the face of an error and undo any changes made since the start of the exception. To accomplish this we might initially try to use the following  syntax: &lt;/p&gt;&lt;p&gt;&lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt;&lt;/code&gt;&lt;pre&gt;CREATE PROCEDURE DeleteEmployee ( @EmployeeID int )&lt;br /&gt;AS&lt;br /&gt;&lt;br /&gt;BEGIN TRANSACTION    -- Start the transaction&lt;br /&gt;&lt;br /&gt;-- Delete the Employee's phone numbers&lt;br /&gt;DELETE FROM EmployeePhoneNumbers&lt;br /&gt;WHERE EmployeeID = @EmployeeID&lt;br /&gt;&lt;br /&gt;-- Delete the Employee record&lt;br /&gt;DELETE FROM Employees&lt;br /&gt;WHERE EmployeeID = @EmployeeID&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;-- See if there is an error&lt;br /&gt;IF @@ERROR &lt;&gt; 0&lt;br /&gt;-- There's an error b/c @ERROR is not 0, rollback&lt;br /&gt;ROLLBACK&lt;br /&gt;ELSE&lt;br /&gt;COMMIT   -- Success!  Commit the transaction&lt;br /&gt;&lt;/pre&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; This stored procedure (it appears) starts a transaction, runs the two &lt;code&gt;DELETE&lt;/code&gt; statements, and then checks to see if there was an error. If there was one, it rolls the transaction back, else it commits the transaction. I say "it appears" because this syntax, while legal, is semantically incorrect because the &lt;code&gt;@@ERROR&lt;/code&gt; variable is set after &lt;i&gt;every&lt;/i&gt; SQL statement. Therefore, if the first &lt;code&gt;DELETE&lt;/code&gt; statement has an error the &lt;code&gt;@@ERROR&lt;/code&gt; variable will be set to its error number. Then, the second &lt;code&gt;DELETE&lt;/code&gt; will execute. If this second &lt;code&gt;DELETE&lt;/code&gt; succeeds,  &lt;code&gt;@@ERROR&lt;/code&gt; will be set back to 0, in which case the transaction will be committed even though there was a problem with the first statement! Whoops! &lt;/p&gt;&lt;p&gt; Instead, a check must be made after &lt;i&gt;every&lt;/i&gt; SQL statement to see if there has been an error. If so, the transaction must be rolled back and the stored procedure exited. This can lead to bulky scripts as a stored procedure with, say, five statements will have five checks against the &lt;code&gt;@@ERROR&lt;/code&gt; variable. And if you forget to cut and paste a check in for a particular statement you're opening yourself up to a potential problem. &lt;/p&gt;&lt;p&gt; For more information on transactions and the &lt;code&gt;@@ERROR&lt;/code&gt; syntax used for checking for errors and rolling back as needed, see &lt;a href="http://www.4guysfromrolla.com/webtech/080305-1.shtml"&gt;Managing Transactions in SQL Server Stored Procedures&lt;/a&gt;. &lt;/p&gt;&lt;p&gt; &lt;b&gt;Handling Errors With SQL Server 2005's TRY...CATCH Blocks&lt;/b&gt;&lt;br /&gt;While SQL Server 2005 still supports the &lt;code&gt;@@ERROR&lt;/code&gt; approach, a better alternative exists with its new &lt;a href="http://msdn2.microsoft.com/en-US/library/ms175976%28SQL.90%29.aspx"&gt;TRY...CATCH blocks&lt;/a&gt;. As with programming languages like Visual Basic, C#, and Java, the SQL Server 2005 TRY...CATCH block executes a number of statements in the TRY block. If there are no errors in any of the statements, control proceeds to &lt;i&gt;after&lt;/i&gt; the CATCH block. If, however, one of the statements causes an error, control branches immediately to the start of the CATCH block. Furthermore, like programming languages, nested TRY...CATCH blocks are allowed, meaning that you can have an entire TRY...CATCH block in the TRY or CATCH portions of an "outter" TRY...CATCH block. &lt;/p&gt;&lt;p&gt;&lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt;&lt;/code&gt;&lt;pre&gt;BEGIN TRY&lt;br /&gt; &lt;i&gt;Try Statement 1&lt;/i&gt;&lt;br /&gt; &lt;i&gt;Try Statement 2&lt;/i&gt;&lt;br /&gt; ...&lt;br /&gt; &lt;i&gt;Try Statement M&lt;/i&gt;&lt;br /&gt;END TRY&lt;br /&gt;BEGIN CATCH&lt;br /&gt; &lt;i&gt;Catch Statement 1&lt;/i&gt;&lt;br /&gt; &lt;i&gt;Catch Statement 2&lt;/i&gt;&lt;br /&gt; ...&lt;br /&gt; &lt;i&gt;Catch Statement N&lt;/i&gt;&lt;br /&gt;END CATCH&lt;br /&gt;&lt;/pre&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; The following system functions are available in the CATCH block and can be used to determine additional error information: &lt;/p&gt;&lt;p&gt;&lt;table width="77%" align="center" border="1" cellpadding="4" cellspacing="1"&gt; &lt;tbody&gt;&lt;tr bgcolor="lightyellow"&gt;&lt;th&gt;Function&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;&lt;code&gt;ERROR_NUMBER()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Returns the number of the error&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#eeeeee"&gt;&lt;td&gt;&lt;code&gt;ERROR_SEVERITY()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Returns the severity&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;&lt;code&gt;ERROR_STATE()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Returns the error state number&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#eeeeee"&gt;&lt;td&gt;&lt;code&gt;ERROR_PROCEDURE()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Returns the name of the stored procedure or trigger where the error occurred&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;&lt;code&gt;ERROR_LINE()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Returns the line number inside the routine that caused the error&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#eeeeee"&gt;&lt;td&gt;&lt;code&gt;ERROR_MESSAGE()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Returns the complete text of the error message. The text includes the values supplied for any substitutable parameters, such as lengths, object names, or times&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/p&gt;&lt;p&gt; Also realize that not all errors generating by the TRY block statements are passed onto the CATCH block. Any errors with a severity of 10 or less are considered to be warnings and do not branch control flow to the CATCH block. Also, any errors that sever the database connection will not cause the CATCH block to be reached. &lt;/p&gt;&lt;p&gt; Let's look at a quick example of using TRY...CATCH, after which we'll turn our attention to using this new construct for rolling back transactions in the face of an error. The following example shows a very simply &lt;code&gt;INSERT&lt;/code&gt; query  on the Northwind database's &lt;code&gt;Products&lt;/code&gt; table. The &lt;code&gt;Products&lt;/code&gt; table's &lt;code&gt;ProductID&lt;/code&gt; column is an &lt;code&gt;IDENTITY&lt;/code&gt; column and therefore its value can't be specified when inserting a new record. However, I've specified this value in the following &lt;code&gt;INSERT&lt;/code&gt; statement. Hence, control is turned over to the CATCH block where error information is displayed. &lt;/p&gt;&lt;p&gt;&lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt;&lt;/code&gt;&lt;pre&gt;BEGIN TRY&lt;br /&gt; -- This will generate an error, as ProductID is an IDENTITY column&lt;br /&gt; -- Ergo, we can't specify a value for this column...&lt;br /&gt; INSERT INTO Products(ProductID, ProductName)&lt;br /&gt; VALUES(1, 'Test')&lt;br /&gt;END TRY&lt;br /&gt;BEGIN CATCH&lt;br /&gt; SELECT 'There was an error! ' + ERROR_MESSAGE()&lt;br /&gt;END CATCH&lt;br /&gt;&lt;/pre&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; This query will return a single record with a single column with the contents: "There was an error! Cannot insert  explicit value for identity column in table 'Products' when IDENTITY_INSERT is set to OFF." &lt;/p&gt;&lt;p&gt; &lt;b&gt;Using TRY...CATCH to Rollback a Transaction in the Face of an Error&lt;/b&gt;&lt;br /&gt;As discussed earlier in this article, one of the downsides of the &lt;code&gt;@@ERROR&lt;/code&gt; variable approach is that for transactions a check against this variable must be added after each and every SQL statement to determine if an error occurred and, if so, to rollback the transaction. With SQL Server 2005's TRY...CATCH block, however, these types of scripts are greatly simplified, as the following example illustrates: &lt;/p&gt;&lt;p&gt;&lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt;&lt;/code&gt;&lt;pre&gt;CREATE PROCEDURE DeleteEmployee ( @EmployeeID int )&lt;br /&gt;AS&lt;br /&gt;&lt;br /&gt;BEGIN TRY&lt;br /&gt; BEGIN TRANSACTION    -- Start the transaction&lt;br /&gt;&lt;br /&gt; -- Delete the Employee's phone numbers&lt;br /&gt; DELETE FROM EmployeePhoneNumbers&lt;br /&gt; WHERE EmployeeID = @EmployeeID&lt;br /&gt;&lt;br /&gt; -- Delete the Employee record&lt;br /&gt; DELETE FROM Employees&lt;br /&gt; WHERE EmployeeID = @EmployeeID&lt;br /&gt;&lt;br /&gt; -- If we reach here, success!&lt;br /&gt; COMMIT&lt;br /&gt;END TRY&lt;br /&gt;BEGIN CATCH&lt;br /&gt;-- Whoops, there was an error&lt;br /&gt;IF @@TRANCOUNT &gt; 0&lt;br /&gt;   ROLLBACK&lt;br /&gt;&lt;br /&gt;-- Raise an error with the details of the exception&lt;br /&gt;DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int&lt;br /&gt;SELECT @ErrMsg = ERROR_MESSAGE(),&lt;br /&gt;       @ErrSeverity = ERROR_SEVERITY()&lt;br /&gt;&lt;br /&gt;RAISERROR(@ErrMsg, @ErrSeverity, 1)&lt;br /&gt;END CATCH&lt;br /&gt;&lt;/pre&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; In the TRY block a transaction is started and the two &lt;code&gt;DELETE&lt;/code&gt; statements are performed. If both &lt;code&gt;DELETE&lt;/code&gt;s succeed, the &lt;code&gt;COMMIT&lt;/code&gt; will be reached and the transaction committed. If, however, either one produces an error, control will be routed to the CATCH block where the transaction will be rolled back. Also, the CATCH block re-raises the error (using &lt;a href="http://msdn2.microsoft.com/en-US/library/ms177497%28SQL.90%29.aspx"&gt;&lt;code&gt;RAISERROR&lt;/code&gt;&lt;/a&gt;) so that the error information will be percolated up to the application that invoked the stored procedure. For an ASP.NET web  application, that means that an exception will be raised in the .NET code that invoked this stored procedure, as chances are you not only want to rollback the transaction, but have some sort of error message handled in the web application as well so that the end user knows that their action failed. &lt;/p&gt;&lt;p&gt; Adding the call to &lt;code&gt;RAISERROR&lt;/code&gt; in the CATCH block is tantamount to having a TRY...CATCH block in a programming language that re-throws the exception in the CATCH block after logging it or performing other actions. The action performed in the example above is rolling back the transaction, but could also include logging logic. If you omit the &lt;code&gt;RAISERROR&lt;/code&gt;, the ASP.NET application won't throw an exception from executing the database command. Chances are you want to have an exception thrown on the ASP.NET side (so that you don't fail silently). If so, leave in the &lt;code&gt;RAISERROR&lt;/code&gt; call. &lt;/p&gt;&lt;p&gt; &lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;SQL Server 2005's new TRY...CATCH block brings the familiar TRY...CATCH exception handling to T-SQL. Prior to SQL Server 2005, errors could only be detected in SQL scripts through the use of the &lt;code&gt;@@ERROR&lt;/code&gt; variable, which annoyingly reset after each SQL statement, thereby requiring checks after each and every statement. This led to bloated script that was prone to typos or cut and paste errors leading to potentially serious problems. With SQL Server 2005's TRY...CATCH block, on the other hand, anytime an error is raised by one of the statements in the TRY block, control is directed to the CATCH block. As we saw in this article, the TRY...CATCH block allows for much more readable and cleaner error handling in transaction settings. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-6582936946647858494?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.4guysfromrolla.com/webtech/041906-1.shtml' title='TRY...CATCH in SQL Server 2005'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/6582936946647858494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=6582936946647858494' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/6582936946647858494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/6582936946647858494'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/trycatch-in-sql-server-2005.html' title='TRY...CATCH in SQL Server 2005'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-3700826198293675717</id><published>2009-06-03T18:59:00.000-07:00</published><updated>2009-06-03T19:07:43.196-07:00</updated><title type='text'>Common Table Expressions (CTE) in SQL Server 2005</title><content type='html'>When crafting a query in SQL, there are often times when we may need to operate over a set of data that doesn't inherently exist within the system. For example, the database for an eCommerce web application would have the standard tables - &lt;code&gt;Products&lt;/code&gt;, &lt;code&gt;Customers&lt;/code&gt;, &lt;code&gt;Orders&lt;/code&gt;, &lt;code&gt;OrderDetails&lt;/code&gt;, and so on - but we may need to run reports on a particular subset of the data or against aggregate data across these tables. Or the reporting queries we need might need to group or filter by results returned by scalar subqueries. Typically, &lt;a href="http://www.odetocode.com/Articles/299.aspx"&gt;views&lt;/a&gt; are used to break down complex queries into digestible chunks or to provide scalar subquery results that can be grouped and filtered. Views, however, are sometimes overkill, as they are permanent objects at the system-level. If we only need to reference this complex query in a single stored procedure or UDF, another option is to use a &lt;a href="http://www.4guysfromrolla.com/webtech/112098-1.shtml"&gt;derived  table&lt;/a&gt;. Unfortunately, derived tables muddle the readability of the query and must be repeated for each use in a statement. &lt;p&gt; Common Table Expressions, or CTE, are a new construct introduced in Microsoft SQL Server 2005 that offer a more readable form of the derived table that can be declared once and referenced multiple times in a query. Moreover, CTEs can be recursively defined, allowing a recursive entity to be enumerated without the need for recursive stored procedures. In this article we'll examine the benefits, uses, and syntax of both recursive and non-recursive CTEs. Read on to learn more!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt; &lt;b&gt;A Simple Common Table Expression Example&lt;/b&gt;&lt;br /&gt;Before we dive into the syntax or gritty details of CTEs, let's start by looking at a simple example. I think you'll agree that even without knowing the syntax of CTEs, they are pretty readable and straightforward (the hallmark of a well-designed programming language construct). &lt;/p&gt;&lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; &lt;b&gt;WITH ProductAndCategoryNamesOverTenDollars (ProductName, CategoryName, UnitPrice) AS&lt;br /&gt;(&lt;br /&gt;   SELECT&lt;br /&gt;      p.ProductName,&lt;br /&gt;      c.CategoryName,&lt;br /&gt;      p.UnitPrice&lt;br /&gt;   FROM Products p&lt;br /&gt;      INNER JOIN Categories c ON&lt;br /&gt;         c.CategoryID = p.CategoryID&lt;br /&gt;   WHERE p.UnitPrice &gt; 10.0&lt;br /&gt;)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;SELECT *&lt;br /&gt;FROM &lt;b&gt;ProductAndCategoryNamesOverTenDollars&lt;/b&gt;&lt;br /&gt;ORDER BY CategoryName ASC, UnitPrice ASC, ProductName ASC &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; This query creates a CTE named &lt;code&gt;ProductAndCategoryNamesOverTenDollars&lt;/code&gt; that returns the name, category name, and price of those products whose unit price exceeds $10.00. Once the CTE has been defined, it must then immediately be used in a query. The query treats the CTE as if were a view or table in the system, returning the three fields defined by the CTE (&lt;code&gt;ProductName&lt;/code&gt;, &lt;code&gt;CategoryName&lt;/code&gt;, and &lt;code&gt;UnitPrice&lt;/code&gt;), ordered alphabetically by category, then by price, and then alphabetically by product name.&lt;br /&gt;&lt;/p&gt;&lt;center&gt; &lt;img src="http://www.4guysfromrolla.com/webtech/images/cteresults1.gif" alt="The results of the query." width="360" border="1" height="300" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; In short, a Common Table Expression allows us to define a temporary, view-like construct. We start by (optionally) specifying the columns it returns, then define the query. Following that, the CTE can be used in a &lt;code&gt;SELECT&lt;/code&gt;, &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt; statement. &lt;/p&gt;&lt;p&gt; &lt;b&gt;Common Table Expression Syntax&lt;/b&gt;&lt;br /&gt;A Common Table Expression contains three core parts: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;The CTE name (this is what follows the &lt;code&gt;WITH&lt;/code&gt; keyword)&lt;/li&gt;&lt;li&gt;The column list (&lt;i&gt;optional&lt;/i&gt;)&lt;/li&gt;&lt;li&gt;The query (appears within parentheses after the &lt;code&gt;AS&lt;/code&gt; keyword)&lt;/li&gt;&lt;/ul&gt; The query using the CTE must be the first query appearing after the CTE. That is, you &lt;strong&gt;cannot&lt;/strong&gt; do the following: &lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; WITH ProductAndCategoryNamesOverTenDollars (ProductName, CategoryName, UnitPrice) AS&lt;br /&gt;(&lt;br /&gt;   SELECT&lt;br /&gt;      p.ProductName,&lt;br /&gt;      c.CategoryName,&lt;br /&gt;      p.UnitPrice&lt;br /&gt;   FROM Products p&lt;br /&gt;      INNER JOIN Categories c ON&lt;br /&gt;         c.CategoryID = p.CategoryID&lt;br /&gt;   WHERE p.UnitPrice &gt; 10.0&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SELECT *&lt;br /&gt;FROM Products&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;SELECT *&lt;br /&gt;FROM ProductAndCategoryNamesOverTenDollars&lt;br /&gt;ORDER BY CategoryName ASC, UnitPrice ASC, ProductName ASC &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; The &lt;code&gt;ProductAndCategoryNamesOverTenDollars&lt;/code&gt; CTE only applies to the first query following it. So when the second query is reached, &lt;code&gt;ProductAndCategoryNamesOverTenDollars&lt;/code&gt; is undefined, resulting in an "Invalid object name 'ProductAndCategoryNamesOverTenDollars'" error message. &lt;/p&gt;&lt;p&gt; You can, however, define multiple CTEs after the &lt;code&gt;WITH&lt;/code&gt; keyword by separating each CTE with a comma. For example, the following query uses two CTEs. The subsequent &lt;code&gt;SELECT&lt;/code&gt; query then uses an &lt;code&gt;INNER JOIN&lt;/code&gt; to match together the records from the two CTEs: &lt;/p&gt;&lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; &lt;b&gt;WITH CategoryAndNumberOfProducts (CategoryID, CategoryName, NumberOfProducts) AS&lt;br /&gt;(&lt;br /&gt;   SELECT&lt;br /&gt;      CategoryID,&lt;br /&gt;      CategoryName,&lt;br /&gt;      (SELECT COUNT(1) FROM Products p&lt;br /&gt;       WHERE p.CategoryID = c.CategoryID) as NumberOfProducts&lt;br /&gt;   FROM Categories c&lt;br /&gt;),&lt;br /&gt;&lt;br /&gt;ProductsOverTenDollars (ProductID, CategoryID, ProductName, UnitPrice) AS&lt;br /&gt;(&lt;br /&gt;   SELECT&lt;br /&gt;      ProductID,&lt;br /&gt;      CategoryID,&lt;br /&gt;      ProductName,&lt;br /&gt;      UnitPrice&lt;br /&gt;   FROM Products p&lt;br /&gt;   WHERE UnitPrice &gt; 10.0&lt;br /&gt;)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;SELECT c.CategoryName, c.NumberOfProducts,&lt;br /&gt;      p.ProductName, p.UnitPrice&lt;br /&gt;FROM &lt;b&gt;ProductsOverTenDollars&lt;/b&gt; p&lt;br /&gt;   INNER JOIN &lt;b&gt;CategoryAndNumberOfProducts&lt;/b&gt; c ON&lt;br /&gt;      p.CategoryID = c.CategoryID&lt;br /&gt;ORDER BY ProductName &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;center&gt; &lt;img src="http://www.4guysfromrolla.com/webtech/images/cteresults4.gif" alt="The results of the query." width="450" border="1" height="300" /&gt; &lt;/center&gt;&lt;p&gt; Unlike a derived table, CTEs can be defined just once, yet appear multiple times in the subsequent query. To demonstrate this, consider the following example: the Northwind database's &lt;code&gt;Employees&lt;/code&gt; table contains an optional  &lt;code&gt;ReportsTo&lt;/code&gt; column that, if specified, indicates the employee's manager. &lt;code&gt;ReportsTo&lt;/code&gt; is a  self-referencing foreign key, meaning that, if provided, it refers back to another &lt;code&gt;EmployeeID&lt;/code&gt; in the  &lt;code&gt;Employees&lt;/code&gt; table. Imagine that we wanted to display a list of employees including how many other employees they directly managed. This could be done using a simple, CTE-free &lt;code&gt;SELECT&lt;/code&gt; statement, but let's use a CTE for now (for reasons which will become clear soon): &lt;/p&gt;&lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; WITH EmployeeSubordinatesReport (EmployeeID, LastName, FirstName, NumberOfSubordinates, ReportsTo) AS&lt;br /&gt;(&lt;br /&gt;   SELECT&lt;br /&gt;      EmployeeID,&lt;br /&gt;      LastName,&lt;br /&gt;      FirstName,&lt;br /&gt;      (SELECT COUNT(1) FROM Employees e2&lt;br /&gt;       WHERE e2.ReportsTo = e.EmployeeID) as NumberOfSubordinates,&lt;br /&gt;      ReportsTo&lt;br /&gt;   FROM Employees e&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT LastName, FirstName, NumberOfSubordinates&lt;br /&gt;FROM EmployeeSubordinatesReport &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; This query will return the employees records, showing each employee's last and first name along with how many other employees they manage. As the figure below shows, only Andrew Fuller and Steven Buchanan are manager material. &lt;/p&gt;&lt;center&gt; &lt;img src="http://www.4guysfromrolla.com/webtech/images/cteresults2.gif" alt="The results of the query." width="300" border="1" height="215" /&gt; &lt;/center&gt;&lt;p&gt; Now, imagine that our boss (Andrew Fuller, perhaps) comes charging into our office and demands that the report also lists each employee's manager's name and number of subordinates (if the employee has a manager, that is - Mr. Fuller is all to quick to point out that &lt;i&gt;he&lt;/i&gt; reports to no one). Adding such functionality is a snap with the CTE - just add it in a &lt;code&gt;LEFT JOIN&lt;/code&gt;! &lt;/p&gt;&lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; WITH EmployeeSubordinatesReport (EmployeeID, LastName, FirstName, NumberOfSubordinates, ReportsTo) AS&lt;br /&gt;(&lt;br /&gt;   SELECT&lt;br /&gt;      EmployeeID,&lt;br /&gt;      LastName,&lt;br /&gt;      FirstName,&lt;br /&gt;      (SELECT COUNT(1) FROM Employees e2&lt;br /&gt;       WHERE e2.ReportsTo = e.EmployeeID) as NumberOfSubordinates,&lt;br /&gt;      ReportsTo&lt;br /&gt;   FROM Employees e&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT Employee.LastName, Employee.FirstName, Employee.NumberOfSubordinates,&lt;br /&gt;   &lt;b&gt;Manager.LastName as ManagerLastName, Manager.FirstName as ManagerFirstName, Manager.NumberOfSubordinates as ManagerNumberOfSubordinates&lt;/b&gt;&lt;br /&gt;FROM EmployeeSubordinatesReport Employee&lt;br /&gt;   &lt;b&gt;LEFT JOIN EmployeeSubordinatesReport Manager ON&lt;br /&gt;      Employee.ReportsTo = Manager.EmployeeID&lt;/b&gt; &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; With this additional &lt;code&gt;LEFT JOIN&lt;/code&gt;, the employee's manager's results are returned; if there's no manager for the employee, &lt;code&gt;NULL&lt;/code&gt;s are returned instead. &lt;/p&gt;&lt;center&gt; &lt;img src="http://www.4guysfromrolla.com/webtech/images/cteresults3.gif" alt="The results of the query." width="575" border="1" height="215" /&gt; &lt;/center&gt;&lt;p&gt;  &lt;table style="border: 1px solid black; padding: 5px; background-color: lightyellow;" width="77%" align="center"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;When to Use Common Table Expressions&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt; Common Table Expressions offer the same functionality as a view, but are ideal for one-off usages where you don't necessarily need a view defined for the system. Even when a CTE is not necessarily needed (as when listing just the employees and their subordinate count in the example above), it can improve readability. In &lt;a href="http://msdn2.microsoft.com/en-us/library/ms190766.aspx"&gt;Using Common Table Expressions&lt;/a&gt;, Microsoft offers the following four advantages of CTEs: &lt;blockquote&gt; &lt;ul&gt;&lt;li&gt;Create a recursive query.&lt;/li&gt;&lt;li&gt;Substitute for a view when the general use of a view is not required; that is, you do not have to store the definition in metadata.&lt;/li&gt;&lt;li&gt;Enable grouping by a column that is derived from a scalar subselect, or a function that is either not deterministic or has external access.&lt;/li&gt;&lt;li&gt;Reference the resulting table multiple times in the same statement.&lt;/li&gt;&lt;/ul&gt; Using a CTE offers the advantages of improved readability and ease in maintenance of complex queries. The query can be  divided into separate, simple, logical building blocks. These simple blocks can then be used to build more complex, interim  CTEs until the final result set is generated. &lt;/blockquote&gt; Using scalar subqueries (such as the &lt;code&gt;(SELECT COUNT(1) FROM ...)&lt;/code&gt; examples we've looked at in this article) cannot be grouped or filtered directly in the containing query. Similarly, when using SQL Server 2005's ranking functions - &lt;code&gt;ROW_NUMBER()&lt;/code&gt;, &lt;code&gt;RANK()&lt;/code&gt;, &lt;code&gt;DENSE_RANK()&lt;/code&gt;, and so on - the containing query cannot include a filter or grouping expression to return only a subset of the ranked results. For both of these instances, CTEs are quite handy. (For more on SQL Server 2005's ranking capabilities, be sure to read: &lt;a href="http://www.4guysfromrolla.com/webtech/010406-1.shtml"&gt;Returning Ranked Results with Microsoft SQL Server 2005&lt;/a&gt;.) &lt;p&gt; CTEs can also be used to recursively enumerate hierarchical data. We'll examine this next! &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;  &lt;b&gt;Recursive Common Table Expressions&lt;/b&gt;&lt;br /&gt;Recursion is the process of defining a solution to a problem in terms of itself. For example, a teacher needs to sort a stack of tests alphabetically by the students' names. She could process the tests one at a time and, for each test, insert it into the appropriate spot to the left (called &lt;a href="http://en.wikipedia.org/wiki/Insertion_sort"&gt;insertion sort&lt;/a&gt;), probably the way most people sort a hand of cards (at least that's the way I do it). However, depending on the distribution of the tests, the size of the work space, the number of tests to sort, and so on, it may be far more efficient to break down the problem into pieces. Rather than doing an insertion sort right off the bat, it might first make sense to divide the stack of papers in half, and then do an insertion sort on one half, an insertion sort on the second half, and then a merge of the two piles. Or perhaps it would make sense to divide the tests into four piles, or eight piles. (This approach is referred to as &lt;a href="http://en.wikipedia.org/wiki/Mergesort"&gt;merge  sort&lt;/a&gt;.) &lt;/p&gt;&lt;p&gt; With a recursive solution you will always have the following two pieces: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;The base case&lt;/b&gt; - what to do when you're done recursing. After dividing the tests into separate piles of say, eight elements per pile,   the base case is to sort these piles via insertion sort.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The recursive step&lt;/b&gt; - the action to perform that involves plugging the input "back into" the system. For merge sort, the recursive step is the division of one pile into two. Then into four. Then into eight, and so on, until the base case is reached.&lt;/li&gt;&lt;/ul&gt; For more on recursion, see &lt;a href="http://www.4guysfromrolla.com/webtech/060299-2.shtml"&gt;Recursion, Why It's Cool&lt;/a&gt;. &lt;p&gt; Returning to CTEs... the &lt;code&gt;Employees&lt;/code&gt; database table holds the corporate hierarchy within its rows. Imagine that good ol' Andrew Fuller has come back and insisted on a report that would list all persons in the company along with their position in the hierarchy. Since the &lt;code&gt;Employees&lt;/code&gt; table can capture an arbitrary number of hierarchy levels, we need a recursive solution. Enter CTEs... &lt;/p&gt;&lt;p&gt; Like any recursive definition, a recursive Common Table Expression requires both a base case and the recursive step. In SQL parlance, this translates into two SQL queries - one that gets the "initial" data &lt;code&gt;UNION&lt;/code&gt;ed with one that performs the recursion. For the &lt;code&gt;Employees&lt;/code&gt; example, the base case is returning those employees that have no manager: &lt;/p&gt;&lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; SELECT ...&lt;br /&gt;FROM Employees&lt;br /&gt;&lt;b&gt;WHERE ReportsTo IS NULL&lt;/b&gt; &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; The recursion includes a query on the CTE itself. The following shows the CTE - with both the base case and recursive step - along with a &lt;code&gt;SELECT&lt;/code&gt; query that returns the rows from the CTE: &lt;/p&gt;&lt;p&gt; &lt;table width="95%" border="0"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td width="100%" bgcolor="#cccccc"&gt; &lt;code&gt; WITH EmployeeHierarchy (EmployeeID, LastName, FirstName, ReportsTo, HierarchyLevel) AS&lt;br /&gt;(&lt;br /&gt;   -- Base case&lt;br /&gt;   SELECT&lt;br /&gt;      EmployeeID,&lt;br /&gt;      LastName,&lt;br /&gt;      FirstName,&lt;br /&gt;      ReportsTo,&lt;br /&gt;      1 as HierarchyLevel&lt;br /&gt;   FROM Employees&lt;br /&gt;   WHERE ReportsTo IS NULL&lt;br /&gt;&lt;br /&gt;   UNION ALL&lt;br /&gt;&lt;br /&gt;   -- Recursive step&lt;br /&gt;   SELECT&lt;br /&gt;      e.EmployeeID,&lt;br /&gt;      e.LastName,&lt;br /&gt;      e.FirstName,&lt;br /&gt;      e.ReportsTo,&lt;br /&gt;      eh.HierarchyLevel + 1 AS HierarchyLevel&lt;br /&gt;   FROM Employees e&lt;br /&gt;      INNER JOIN EmployeeHierarchy eh ON&lt;br /&gt;         e.ReportsTo = eh.EmployeeID&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT *&lt;br /&gt;FROM EmployeeHierarchy&lt;br /&gt;ORDER BY HierarchyLevel, LastName, FirstName &lt;/code&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt; The recursion occurs in the second query in the CTE by joining the results of &lt;code&gt;Employees&lt;/code&gt; against the CTE itself (&lt;code&gt;EmployeeHierarchy&lt;/code&gt;) where the employees' &lt;code&gt;ReportsTo&lt;/code&gt; field matches up to the CTE's &lt;code&gt;EmployeeID&lt;/code&gt;. Included in this query is the &lt;code&gt;HierarchyLevel&lt;/code&gt; field, which returns 1 for the base case and one greater than the previous level for each recursive step down the hierarchy. As requested, this resultset clearly shows that Mr. Fuller is the alpha male in this organization. Furthermore, we can see that Steven, Laura, Nancy, Janet, and Margaret make up the second tier in the organizational hierarchy, while poor Anne, Robert, and Michael are down at the bottom: &lt;/p&gt;&lt;center&gt; &lt;img src="http://www.4guysfromrolla.com/webtech/images/cteresults5.gif" alt="The results of the query." width="400" border="1" height="225" /&gt; &lt;/center&gt;&lt;p&gt; &lt;table style="border: 1px solid black; padding: 5px; background-color: lightyellow;" width="77%" align="center"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Alternatives to Recursive Common Table Expressions&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt; As we saw in this article, enumerating hierarchical data recursively can be accomplished via CTEs (for more on using recursive CTEs, don't forget to check out the official documentation - &lt;a href="http://msdn2.microsoft.com/en-us/library/ms186243.aspx"&gt;Recursive Queries Using Common Table Expressions&lt;/a&gt;). However, there are other options as well. One choice is to perform the recursion at the ASP/ASP.NET layer. That is, read in &lt;i&gt;all&lt;/i&gt; employee information to a Recordset of DataSet in code, and then recurse there. My article &lt;a href="http://www.4guysfromrolla.com/webtech/101202-1.shtml"&gt;Efficiently DisplayingParent-Child Data&lt;/a&gt; discusses this approach. &lt;p&gt; If you need to perform the recursion in SQL, you can use recursive stored procedures, as discussed in &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsqlmag01/html/recursion.asp"&gt;The Zen of Recursion&lt;/a&gt;. If you are designing a data model that needs to support hierarchical data, your best bet is to bake in some lineage information directly into the table from the get-go. See &lt;a href="http://www.sqlteam.com/item.asp?ItemID=1602"&gt;SQL for Threaded Discussions&lt;/a&gt; and &lt;a href="http://www.sqlteam.com/item.asp?ItemID=8866"&gt;More Trees &amp;amp; Hierarchies in SQL&lt;/a&gt; for more information. &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/p&gt;&lt;p&gt; &lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;One of the many new features in SQL Server 2005 are Common Table Expressions (CTEs), which provide a more readable and usable approach to derived tables. Additionally, CTEs may be recursively defined, allowing a recursive entity to be enumerated without  the need for recursive stored procedures. For more on the new features found in SQL Server 2005, be sure to also check out &lt;a href="http://www.4guysfromrolla.com/webtech/010406-1.shtml"&gt;Returning Ranked Results with Microsoft SQL Server 2005&lt;/a&gt; and &lt;a href="http://www.4guysfromrolla.com/webtech/041906-1.shtml"&gt;&lt;code&gt;TRY...CATCH&lt;/code&gt; in SQL Server 2005&lt;/a&gt;. &lt;/p&gt;&lt;br /&gt;&lt;/center&gt;&lt;img src="file:///C:/Users/Admin/AppData/Local/Temp/moz-screenshot.jpg" alt="" /&gt; &lt;p&gt; &lt;/p&gt; &lt;span style="font-size:-1;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-3700826198293675717?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.4guysfromrolla.com/webtech/071906-1.shtml' title='Common Table Expressions (CTE) in SQL Server 2005'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/3700826198293675717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=3700826198293675717' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/3700826198293675717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/3700826198293675717'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/06/common-table-expressions-cte-in-sql.html' title='Common Table Expressions (CTE) in SQL Server 2005'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8659963464378965702</id><published>2009-05-09T13:29:00.000-07:00</published><updated>2009-05-09T14:20:28.746-07:00</updated><title type='text'>To Search all columns of all tables for a given search string</title><content type='html'>&lt;p align="left"&gt;CREATE PROC SearchAllTables&lt;/p&gt;&lt;p align="left"&gt;(&lt;/p&gt;&lt;p align="left"&gt;@SearchStr nvarchar(100)&lt;/p&gt;&lt;p align="left"&gt;) &lt;/p&gt;&lt;p align="left"&gt;AS&lt;/p&gt;&lt;p align="left"&gt;BEGIN&lt;/p&gt;&lt;p align="left"&gt;CREATE TABLE #Results&lt;/p&gt;&lt;p align="left"&gt;(&lt;/p&gt;&lt;p align="left"&gt;ColumnName nvarchar(370), ColumnValue nvarchar(3630)) &lt;/p&gt;&lt;p align="left"&gt;SET NOCOUNT ON &lt;/p&gt;&lt;p align="left"&gt;DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) &lt;/p&gt;&lt;p align="left"&gt;SET @TableName = '' &lt;/p&gt;&lt;p align="left"&gt;SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') &lt;/p&gt;&lt;p align="left"&gt;WHILE @TableName IS NOT NULL &lt;/p&gt;&lt;p align="left"&gt;BEGIN &lt;/p&gt;&lt;p align="left"&gt;SET @ColumnName = '' &lt;/p&gt;&lt;p align="left"&gt;SET @TableName = &lt;/p&gt;&lt;p align="left"&gt;(&lt;/p&gt;&lt;p align="left"&gt;SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) &gt; @TableName AND OBJECTPROPERTY( OBJECT_ID( QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) ), 'IsMSShipped') = 0 &lt;/p&gt;&lt;p align="left"&gt;)&lt;/p&gt;&lt;p align="left"&gt;WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) &lt;/p&gt;&lt;p align="left"&gt;BEGIN&lt;/p&gt;&lt;p align="left"&gt;SET @ColumnName = &lt;/p&gt;&lt;p align="left"&gt;(&lt;/p&gt;&lt;p align="left"&gt;SELECT MIN(QUOTENAME(COLUMN_NAME)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA =&lt;/p&gt;&lt;p align="left"&gt;PARSENAME(@TableName, 2) &lt;/p&gt;&lt;p align="left"&gt;AND TABLE_NAME = PARSENAME(@TableName, 1) &lt;/p&gt;&lt;p align="left"&gt;AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar') &lt;/p&gt;&lt;p align="left"&gt;AND QUOTENAME(COLUMN_NAME) &gt; @ColumnName &lt;/p&gt;&lt;p align="left"&gt;) &lt;/p&gt;&lt;p align="left"&gt;IF @ColumnName IS NOT NULL &lt;/p&gt;&lt;p align="left"&gt;BEGIN &lt;/p&gt;&lt;p align="left"&gt;INSERT INTO #Results EXEC &lt;/p&gt;&lt;p align="left"&gt;(&lt;/p&gt;&lt;p align="left"&gt;'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 &lt;/p&gt;&lt;p align="left"&gt;)&lt;/p&gt;&lt;p align="left"&gt;END &lt;/p&gt;&lt;p align="left"&gt;END &lt;/p&gt;&lt;p align="left"&gt;END &lt;/p&gt;&lt;p align="left"&gt;SELECT ColumnName, ColumnValue FROM #Results &lt;/p&gt;&lt;p align="left"&gt;END&lt;/p&gt;&lt;p align="left"&gt;So execute the final script as mentioned below where 'testone' is the string which has to be searched through &lt;/p&gt;&lt;p align="left"&gt;EXEC SearchAllTables '%testone%' &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8659963464378965702?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://vyaskn.tripod.com' title='To Search all columns of all tables for a given search string'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8659963464378965702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8659963464378965702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8659963464378965702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8659963464378965702'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/05/create-proc-searchalltables-searchstr.html' title='To Search all columns of all tables for a given search string'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-2396483841158582159</id><published>2009-05-09T12:34:00.000-07:00</published><updated>2009-05-09T12:38:18.329-07:00</updated><title type='text'>To search all tables to find a column or field name in a database</title><content type='html'>&lt;div align="left"&gt;SELECT table_name=sysobjects.name,&lt;br /&gt;column_name=syscolumns.name,&lt;br /&gt;datatype=systypes.name,&lt;br /&gt;length=syscolumns.length&lt;br /&gt;FROM sysobjects&lt;br /&gt;JOIN syscolumns ON sysobjects.id = syscolumns.id&lt;br /&gt;JOIN systypes ON syscolumns.xtype=systypes.xtype&lt;br /&gt;WHERE syscolumns.name='EMPNAME'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;---------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;In this query it displays LIST OF TABLES ALONG WITH TABLE COUNT in a DATABASE&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="left"&gt;&lt;br /&gt;SELECT so.[name] as [table name],rowcnt as ROWS, &lt;/div&gt;&lt;div align="left"&gt;CASE WHEN si.indid between 1 and 254 &lt;/div&gt;&lt;div align="left"&gt;THEN si.[name] ELSE NULL END AS [Index Name] ,&lt;/div&gt;&lt;div align="left"&gt;si.indid FROM sysindexes si INNER JOIN sysobjects so ON&lt;/div&gt;&lt;div align="left"&gt;si.id = so.id WHERE si.indid &lt; type =" 'U'"&gt; &lt;/div&gt;&lt;div align="left"&gt;AND so.[name] != 'dtproperties'&lt;/div&gt;&lt;div align="left"&gt;ORDER BY so.[name]&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-2396483841158582159?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/2396483841158582159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=2396483841158582159' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2396483841158582159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/2396483841158582159'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/05/to-search-all-tables-to-find-column-or.html' title='To search all tables to find a column or field name in a database'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-4376475283922157297</id><published>2009-05-09T12:19:00.000-07:00</published><updated>2009-05-09T12:33:52.532-07:00</updated><title type='text'>ROW Count for LIST OF TABLES IN A DATABASE</title><content type='html'>Sometimes there is a need to get record counts from every table in your database. One way of doing this is to do a SELECT count(*) on all of your tables, but this could create a lot of overhead especially for large databases and large tables. If you don't require an exact answer, it isn't necessary to use a SELECT count(*) query on the rows in a table to get the row count.&lt;br /&gt;&lt;br /&gt;SELECT so.[name] as [table name],&lt;br /&gt;CASE WHEN si.indid between 1 and 254&lt;br /&gt;THEN si.[name] ELSE NULL END&lt;br /&gt;AS [Index Name] , si.indid&lt;br /&gt;FROM sysindexes si&lt;br /&gt;INNER JOIN sysobjects so ON si.id = so.id&lt;br /&gt;WHERE si.indid &lt; 2&lt;br /&gt;AND so.type = 'U' -- Only User Tables&lt;br /&gt;AND so.[name] != 'dtproperties'&lt;br /&gt;ORDER BY so.[name]&lt;br /&gt;&lt;br /&gt;----------------------------------&lt;br /&gt;Just the table name and no of rows&lt;br /&gt;&lt;br /&gt; SELECT so.[name] as [table name],rowcnt as ROWS&lt;br /&gt;     FROM sysindexes si&lt;br /&gt;          INNER JOIN sysobjects so&lt;br /&gt;             ON si.id = so.id&lt;br /&gt;     WHERE si.indid &lt; 2 &lt;br /&gt;       AND so.type = 'U' -- Only User Tables&lt;br /&gt;       AND so.[name] != 'dtproperties'&lt;br /&gt;     ORDER BY so.[name]&lt;br /&gt;&lt;br /&gt;----------------------------------&lt;br /&gt;&lt;strong&gt;ON A LINKEDSERVER&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;SELECT so.[name] as [table name],rowcnt as ROWS&lt;br /&gt;     FROM [SERVERNAME].&lt;br /&gt;[DATABASENAME].sys.sysindexes si&lt;br /&gt;          INNER JOIN &lt;br /&gt;[SERVERNAME].&lt;br /&gt;[DATABASENAME].sys.sysobjects so&lt;br /&gt;             ON si.id = so.id&lt;br /&gt;     WHERE si.indid &lt; 2 &lt;br /&gt;       AND so.type = 'U' -- Only User Tables&lt;br /&gt;       AND so.[name] != 'dtproperties'&lt;br /&gt;     ORDER BY so.[name]&lt;br /&gt;&lt;br /&gt;-----------------------------------&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-4376475283922157297?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/4376475283922157297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=4376475283922157297' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/4376475283922157297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/4376475283922157297'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/05/sometimes-there-is-need-to-get-record.html' title='ROW Count for LIST OF TABLES IN A DATABASE'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-637092882668486654</id><published>2009-05-09T10:27:00.000-07:00</published><updated>2009-05-09T15:04:47.208-07:00</updated><title type='text'>T-SQL Snippets, Codes,Tweaks</title><content type='html'>&lt;div align="left"&gt;&lt;strong&gt;Operators Allowed in the WHERE Clause&lt;/strong&gt;&lt;br /&gt;= Equal&lt;br /&gt;&lt;&gt; Not equal&lt;br /&gt;&gt; Greater than&lt;br /&gt;&lt;&gt;= Greater than or equal&lt;br /&gt;&lt;= Less than or equal BETWEEN Between an inclusive range LIKE Search for a pattern IN If you know the exact value you want to return for at least one of the columns &lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Taking a backup of a table,&lt;br /&gt;&lt;/strong&gt;The &lt;strong&gt;SQL SELECT INTO &lt;/strong&gt;statement can be used to create backup copies of tables.&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT *&lt;strong&gt;INTO new_table_name&lt;/strong&gt; [IN externaldatabase] FROM &lt;strong&gt;old_tablename&lt;/strong&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT&lt;strong&gt; column_name(s)INTO new_table_name&lt;/strong&gt; [IN externaldatabase]&lt;/div&gt;&lt;div align="left"&gt;FROM old_tablename &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Here it creates the table name &lt;strong&gt;DEF&lt;/strong&gt; and copies the content accordingly&lt;br /&gt;SELECT COLA,COLB,COLC,COLD,COLE,COLF &lt;strong&gt;INTO DEF&lt;/strong&gt; FROM &lt;strong&gt;ABC&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT * &lt;strong&gt;INTO DEF&lt;/strong&gt; FROM &lt;strong&gt;ABC&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;We can also use the IN clause to copy the table into another database:&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;SELECT * &lt;strong&gt;INTO Persons_Backup&lt;/strong&gt; IN &lt;strong&gt;'Backup.mdb' &lt;/strong&gt;FROM &lt;strong&gt;Persons&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="left"&gt;We can also copy only a few fields into the new table:&lt;br /&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT LastName,FirstName&lt;strong&gt; INTO Persons_Backup &lt;/strong&gt;FROM &lt;strong&gt;Persons&lt;/strong&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SQL SELECT INTO - With a WHERE ClauseWe can also add a WHERE clause.&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;The following SQL statement creates a "Persons_Backup" table with only the persons who lives in the city "Sandnes":&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;SELECT LastName,Firstname &lt;strong&gt;INTO Persons_Backup &lt;/strong&gt;FROM &lt;strong&gt;Persons &lt;/strong&gt;WHERE &lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;City='Sandnes' &lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SQL SELECT INTO - Joined TablesSelecting data from more than one table is also possible.&lt;br /&gt;The following example creates a "Persons_Order_Backup" table contains data from the two tables "Persons" and "Orders":&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;SELECT Persons.LastName,Orders.OrderNo &lt;strong&gt;INTO Persons_Order_Backup &lt;/strong&gt;FROM Persons &lt;strong&gt;INNER JOIN&lt;/strong&gt; &lt;strong&gt;Orders ON&lt;/strong&gt; Persons.P_Id=Orders.P_Id &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Exporting the output into a text or csv file: &lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;br /&gt;sqlcmd -S SERVERNAME -i C:\1.sql -o C:\hello.txt or [C:\hello.csv]&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Executing select statements in bcp&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;The below code, iam copying the output into a directory with , delimited values&lt;br /&gt;bcp "select * from [DATABASENAME]..[TABLENAME]" queryout C:\Output.csv -S SERVERNAME -c -t',' -T&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;NOTE: The two .. are must.&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Filter Out unmatching records between two tables&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;SELECT COLA FROM ABC A WHERE NOT EXISTS (SELECT * FROM DEF D WHERE (A.COLA=D.ABC))&lt;/p&gt;&lt;p&gt;or&lt;/p&gt;&lt;p&gt;SELECT COLA FROM DEF D WHERE NOT EXISTS (SELECT * FROM ABC A WHERE (D.COLA=A.ABC))&lt;/p&gt;&lt;p&gt;or&lt;br /&gt;&lt;/p&gt;&lt;p&gt;SELECT A.COLA from ABC A where A.COLA NOT IN (select D.COLA from DEF D)&lt;/p&gt;&lt;p align="center"&gt;------------------------------&lt;/p&gt;&lt;p&gt;Removing 0(zeros) from the begining of a particular number COLA is a column name and ABC is the table name&lt;br /&gt;&lt;/p&gt;&lt;p&gt;select REPLACE(LTRIM(REPLACE(COLA, '0', ' ')), ' ', '0') from ABC&lt;/p&gt;&lt;p&gt;or&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Select Replace(T.Col1,”@”, ‘at’) As [ColName] From MyTable T&lt;/p&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Retrieve MSSQL table information&lt;/strong&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;select * from information_schema.columnswhere table_name= 'ABC'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;To Query the list of columns in a table&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="left"&gt;&lt;br /&gt;select column_name 'Column Name', data_type 'Data Type', character_maximum_length 'Maximum Length' from information_schema.columns where table_name = 'master'&lt;br /&gt;&lt;/div&gt;&lt;div align="left"&gt;or&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.ColumnsWHERE TABLE_NAME = 'master' &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;To find the name of the table in which a particular column name exists.&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="left"&gt;&lt;br /&gt;Here it checks for the database for the tables which have the column name as COLA &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT name FROM sysobjects WHERE id IN ( SELECT id FROM syscolumns WHERE name = 'ABC' )&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;or&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;if you're unsure exactly what the column is named, but you suspect you know part of the name, then try...&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;SELECT name FROM sysobjects WHERE id IN(SELECT id FROM syscolumns WHERE name like '%COLA%')&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;To query the stored procedures in a table&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;select object_name(id) as objectname from syscommentswhere text like '%ABC%'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Finding a text in stored procedure&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT so.[name] AS 'storedProcedure' FROM sysobjects so JOIN syscomments sc ONso.[id] = sc.[id]WHERE so.[type] = 'P'AND sc.[text] LIKE '%action%'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;checking the column if it exists and add&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'ABC' AND COLUMN_NAME = 'COLA')&lt;/div&gt;&lt;div align="center"&gt;BEGIN &lt;/div&gt;&lt;div align="center"&gt;ALTER TABLE ABC ADD COLA int&lt;/div&gt;&lt;div align="center"&gt;END&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Renaming a column name&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;EXEC sp_rename 'TABLENAME.OLD_COLUM&lt;/div&gt;&lt;div align="center"&gt;NNAME', 'NEW_COLUMNAME', 'COLUMN'&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;To get the columns names&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="center"&gt;&lt;br /&gt;SELECT table_name=sysobjects.name,column_name=syscolumns.name, datatype=systypes.name, length=syscolumns.length FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id JOIN systypes ON syscolumns.xtype=systypes.xtype WHERE sysobjects.xtype='U'and syscolumns.NAME = 'assign the name of the column here'&lt;/div&gt;&lt;div align="center"&gt;ORDER BY sysobjects.name,syscolumns.colid&lt;br /&gt;&lt;/div&gt;&lt;div align="center"&gt;or&lt;br /&gt;&lt;/div&gt;&lt;div align="center"&gt;SELECT table_name=sysobjects.name,column_name=syscolumns.name,&lt;/div&gt;&lt;div align="center"&gt;datatype=systypes.name,length=syscolumns.length &lt;/div&gt;&lt;div align="center"&gt;FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id JOIN systypes &lt;/div&gt;&lt;div align="center"&gt;ON syscolumns.xtype=systypes.xtype WHERE syscolumns.name='COLA'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;strong&gt;To split a column into two using a SELECT statement based on a condition&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="center"&gt;&lt;br /&gt;SELECT CASE WHEN STATE = 'VA' &lt;/div&gt;&lt;div align="center"&gt;THEN STATE ELSE '' END as 'Higher income group', &lt;/div&gt;&lt;div align="center"&gt;CASE WHEN STATE = 'NY' &lt;/div&gt;&lt;div align="center"&gt;THEN STATE ELSE '' END as 'Lower income group',NUMBER FROM ABC&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;case query&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;SELECT NUMBER, STATE, priority = ( CASE STATE when 'WA' then 1 when 'VA' then 2 when 'NY' then 3 when 'CA' then 4 end) FROM ABC ORDER BY state&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;To find out the user name at SQL prompt.&lt;/strong&gt; &lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;Select user_name() &lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;strong&gt;If the table exists in the database&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="center"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;select name from sysobjects where xtype='u' and name = 'master'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Determining Your Session IDs for SQL Serversession id&lt;/strong&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;SELECT @@SPID&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;strong&gt;No of tables count in a database&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;SELECT COUNT(*) from information_schema.tables WHERE table_type = 'base table' &lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;strong&gt;list of table names&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;SELECT TABLE_NAME from information_schema.tables WHERE table_type = 'base table' order by table_name&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Returns list of tables that have no primary key&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;select name from sysobjects where id not in (select b.id from sysconstraints b, sysobjects c where c.type = 'K' and c.id = b.constid) and type = 'U' order by name&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;SQL Query to Update a Column Value in All Tables&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT 'UPDATE ',RTRIM(Name),' SET UserID=2 WHERE UserID=1' FROM sysobjectsWHERE Type='U'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Displaying structure of a table&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = 'DATABASENAME' AND TABLE_NAME = 'ABC'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="left"&gt;&lt;br /&gt;or&lt;br /&gt;&lt;/div&gt;&lt;div align="left"&gt;exec sp_columns ABC&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;To determine if a table exists in a SQL Server Database&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME='tablename') SELECT 'tablename exists.' ELSE SELECT 'tablename does not exist.'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;How do I find all the foreign keys in a database?&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="center"&gt;&lt;br /&gt;SELECT FK_Table = FK.TABLE_NAME,FK_Column = CU.COLUMN_NAME, &lt;/div&gt;&lt;div align="center"&gt;PK_Table = PK.TABLE_NAME,PK_Column = PT.COLUMN_NAME,&lt;/div&gt;&lt;div align="center"&gt;Constraint_Name = C.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C&lt;/div&gt;&lt;div align="center"&gt;INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME INNER JOIN (SELECT i1.TABLE_NAME, i2.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1 INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY') PT ON PT.TABLE_NAME = PK.TABLE_NAME &lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;PS:optional: ORDER BY 1,2,3,4&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;The statement takes two tables (ABC and DEF), and figures out which columns between the two are similar:&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;SELECT table_name=sysobjects.name,column_name=syscolumns.name, datatype=systypes.name,length=syscolumns.length FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id JOIN systypes ON syscolumns.xtype=systypes.xtype WHERE (sysobjects.xtype='U' OR sysobjects.xtype='v') AND syscolumns.name IN (SELECT syscolumns.name FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id JOIN systypes ON syscolumns.xtype=systypes.xtype WHERE sysobjects.name = 'ABC') AND sysobjects.name = 'DEF'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;How to find a text inside SQL Server procedures / triggers?&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;SELECT DISTINCT LEFT(so.name, 100) AS Object_Name,"object_type"= left(case so.type when 'U' then 'Table - User'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="left"&gt;when 'S' then 'Table - System'&lt;/div&gt;&lt;div align="left"&gt;when 'V' then 'Table - View' &lt;/div&gt;&lt;div align="left"&gt;when 'TR' then 'Trigger' &lt;/div&gt;&lt;div align="left"&gt;when 'P' then 'Stored Procedure' &lt;/div&gt;&lt;div align="left"&gt;when 'C' then 'Constraint - Check' &lt;/div&gt;&lt;div align="left"&gt;when 'D' then 'Default' &lt;/div&gt;&lt;div align="left"&gt;when 'K' then 'Key - Primary' &lt;/div&gt;&lt;div align="left"&gt;when 'F' then 'Key - Foreign' &lt;/div&gt;&lt;div align="left"&gt;when 'L' then 'Log' &lt;/div&gt;&lt;div align="left"&gt;when 'R' then 'Rule' &lt;/div&gt;&lt;div align="left"&gt;when 'RF' then 'Replication Filter stp' &lt;/div&gt;&lt;div align="left"&gt;else '&lt;&lt;unknown&gt;&gt;' &lt;/div&gt;&lt;div align="left"&gt;end -- case so.type ,25)&lt;/div&gt;&lt;div align="left"&gt;FROM syscomments sc &lt;/div&gt;&lt;div align="left"&gt;INNER JOIN sysobjects so &lt;/div&gt;&lt;div align="left"&gt;ON so.id = sc.id WHERE text Like '%empname%' ORDER BY 2,1&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;GETTING VALUES ROW BY ROW&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;DECLARE @cursor CURSOR&lt;br /&gt;SET @cursor=CURSOR FOR SELECT * FROM abc&lt;br /&gt;OPEN @cursorFETCH @cursor&lt;br /&gt;WHILE (@@FETCH_STATUS=0) BEGIN FETCH @cursorEND&lt;br /&gt;CLOSE @cursorDEALLOCATE @cursor&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;NO OF WAITING TASKS&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT COUNT(*) AS 'Number of waiting tasks'FROM sys.dm_os_waiting_tasks&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Number of threads used with MSSQL 2005&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;SELECT COUNT(*) AS 'Number of threads'FROM sys.dm_os_waiting_tasks&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Type of waiting tasks with MSSQL 2005&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div align="left"&gt;&lt;br /&gt;SELECT CAST(wait_type AS VARCHAR(30)) AS 'Waiting task',COUNT (*) AS 'Number of waiting tasks 'FROM sys.dm_os_waiting_tasks GROUP BY wait_type ORDER BY 'Number of waiting tasks' DESC WHERE wait_type &lt;&gt; 'THREADPOOL'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Resource Bottlenecks with MSSQL 2005&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT resource_address AS 'Resource Bottleneck',COUNT (*) AS '# of bottlenecks' FROM sys.dm_os_waiting_tasks WHERE resource_address &lt;&gt; 0 GROUP BY resource_address ORDER BY '# of bottlenecks' DESC&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;IO Bottlenecks with MSSQL 2005&lt;br /&gt;&lt;/div&gt;&lt;/strong&gt;&lt;div align="center"&gt;SELECT waiting_task_address AS 'Task address', session_id AS 'Session', exec_context_id AS 'Context', wait_duration_ms AS 'Wait in millsec',CAST(wait_type AS VARCHAR(30)) AS 'Type', resource_address AS 'Resource address', blocking_task_address AS 'Blocking task', blocking_session_id AS 'Blocking session',CAST(resource_description AS VARCHAR(30)) AS 'Resource' FROM sys.dm_os_waiting_tasks WHERE wait_duration_ms &gt; 20 AND wait_type LIKE '%PAGEIOLATCH%'&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Has a row been changed&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT UNIQ_ID,CD_TYPE,CODE1,CHECKSUM(UNIQ_ID,CD_TYPE,CODE1) AS 'Checksum specific',CHECKSUM(*) AS 'Checksum general' FROM INFO&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Create a comma delimited list (csv) of unique values&lt;/strong&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="center"&gt;DECLARE @uniquelist VARCHAR(1000);SELECT @uniquelist = LTRIM(COALESCE(@uniquelist+',' , ' ')) + CAST(UNIQ_ID AS VARCHAR(10))FROM (SELECT DISTINCT UNIQ_ID FROM INFO) ABC SELECT @uniquelist AS 'Unique emp_short list: comma delimited'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Incrementing counters that already contain NULLs&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT counter,CASE WHEN counter IS null THEN (row_number() OVER (ORDER BY emp_short,trans_date) +(SELECT MAX(trmax.counter) FROM trans02 trmax ) + 10 ) ELSE counter END AS 'Calculated counter', emp_short,trans_date,debit,credit FROM trans02ORDER BY 'Calculated counter'&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Adding a link server&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="center"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;EXEC master.dbo.sp_addlinkedserver @server = N'SERVERNAME', @srvproduct=N'SQL Server'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Copying the table structure without copying the data from another table&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;SELECT * INTO NewTable FROM abc WHERE 1=2&lt;br /&gt;&lt;br /&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Renaming the table name and column name&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;EXEC sp_rename 'OldTableName', 'NewTableName'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;strong&gt;Renaming Column name Syntax&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;EXEC sp_rename @objname = 'TableName.OldColumnName', @newname = 'NewColumnName', @objtype = 'COLUMN'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;br /&gt;Example : XYZ and ZZZ and DEF are table namesexec sp_rename 'XYZ' , 'ZZZ' - Renaming XYZ table name to ZZZexec sp_rename 'DEF.[B]', 'GROUP' 'COLUMN' - Renaming Column B of table DEF to , GROUP&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;strong&gt;This script will gives row number for every table in database.&lt;br /&gt;&lt;/strong&gt;select OBJECT_NAME(object_id) TableName,st.row_countfrom sys.dm_db_partition_stats st where index_id&lt;2&gt; &lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Obtaining CLR Execution performance counter values.&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;SELECT object_name, counter_name, cntr_value, cntr_type&lt;br /&gt;FROM sys.dm_os_performance_counters&lt;br /&gt;WHERE counter_name LIKE '%CLR%'&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Query performance and time spent in SQL CLR.&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;SELECT (SELECT text FROM sys.dm_exec_sql_text(qs.sql_handle)) AS query_text, qs.*FROM sys.dm_exec_query_stats AS qs WHERE qs.total_clr_time &gt; 0 ORDER BY qs.total_clr_time desc&lt;br /&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Requests that are currently in SQL CLR&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;SELECT session_id, request_id, start_time, status, command, database_id,&lt;br /&gt;wait_type, wait_time, last_wait_type, wait_resource, cpu_time,&lt;br /&gt;total_elapsed_time, nest_level, executing_managed_code&lt;br /&gt;FROM sys.dm_exec_requests WHERE executing_managed_code = 1&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;SQL CLR Wait Statistics&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;SELECT ws.* FROM sys.dm_os_wait_stats AS wsWHERE ws.wait_type LIKE '%clr%'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;User-defined Types&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;User Defined Type Metadata&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Includes base assembly information &lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;SELECT st.[name] AS [Type Name] , st.max_length, st.[precision], st.scale, st.collation_name, st.is_nullable, sa.create_date, sa.[name] AS [Assembly Name], sa.permission_set_desc AS [Access]FROM sys.types AS st INNER JOIN sys.type_assembly_usages AS tau ON st.user_type_id = tau.user_type_id INNER JOIN sys.assemblies AS sa ON tau.assembly_id = sa.assembly_id&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;LIST CLR AGGREGATE FUNCTIONS&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;SELECT schema_name(so.schema_id) + N'.' + so.[name] AS [Name] , so.create_date, so.modify_date, sa.permission_set_desc AS [Access]FROM sys.objects AS so INNER JOIN sys.module_assembly_usages AS mau ON so.object_id = mau.object_id INNER JOIN sys.assemblies AS sa ON mau.assembly_id = sa.assembly_idWHERE so.type_desc = N'AGGREGATE_FUNCTION'&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;LIST CLR TABLE FUNCTIONS&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;SELECT schema_name(so.schema_id) + N'.' + so.[name] AS [Name], so.create_date, so.modify_date, sa.permission_set_desc AS [Access] FROM sys.objects AS so INNER JOIN sys.module_assembly_usages AS sau ON so.object_id = sau.object_id INNER JOIN sys.assemblies AS sa ON sau.assembly_id = sa.assembly_id WHERE so.type_desc = N'CLR_TABLE_VALUED_FUNCTION'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;LIST CLR FUNCTIONS&lt;/strong&gt;:&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;SELECT schema_name(so.schema_id) + N'.' + so.[name] AS [Name], so.create_date, so.modify_date, sa.permission_set_desc AS [Access] FROM sys.objects AS so INNER JOIN sys.module_assembly_usages AS sau ON so.object_id = sau.object_id INNER JOIN sys.assemblies AS sa ON sau.assembly_id = sa.assembly_id WHERE so.type_desc = N'CLR_SCALAR_FUNCTION'&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Substring function&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="center"&gt;Select SUBSTRING(COLA,5,10) as NAME,SUBSTRING(COLA,152,2 )as CUSTNAME from ABC&lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;------------------------------ &lt;/div&gt;&lt;div align="center"&gt; &lt;/div&gt;&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Getting all the rows in one column&lt;/strong&gt; &lt;/div&gt;&lt;div align="left"&gt;declare @res varchar(4000)&lt;/div&gt;&lt;div align="left"&gt;set @res =''&lt;/div&gt;&lt;div align="left"&gt;select @res = @res + A + ',' from testing &lt;/div&gt;&lt;div align="left"&gt;if @@rowcount &gt; 0 select substring(@res, 1, len(@res)-1)&lt;br /&gt;NOTE:Testing is the table name and 'A' is the column name&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;List of databases attached&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt; &lt;/div&gt;&lt;div align="left"&gt;SELECT dtb.name AS [Name] FROM master.dbo.sysdatabases AS dtb ORDER BY [Name] ASC &lt;/div&gt;&lt;div align="center"&gt; &lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Adding strings to the output&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;select (CHAR('39')+COLA+CHAR('39')++CHAR('44')) from ABC&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="center"&gt;------------------------------&lt;/div&gt;&lt;div align="center"&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Generating a script using the existing table structure&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt; &lt;/div&gt;&lt;div align="center"&gt;SELECT CASE WHEN colid = 1 THEN 'CREATE TABLE ' + O.name + ' (' ELSE '' END+ C.name + ' ' + CASE C.xtype WHEN 167 THEN 'varchar(' + CONVERT(varchar(20), C.length) + ') 'WHEN 61 THEN 'datetime'--   ...ELSE 'UnknownType_' + CONVERT(varchar(20), C.xtype)END + ' '+ CASE WHEN C.isnullable = 1THEN 'NULL' ELSE 'NOT NULL' END+ CASE WHEN colid =(SELECT MAX(colid) FROM dbo.syscolumns C2 WHERE C2.id = O.id)  THEN ')'  ELSE ','  ENDFROM dbo.sysobjects O JOIN dbo.syscolumns C  ON C.id = O.id WHERE     O.name= 'info' AND O.type = 'U'ORDER BY colid&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-637092882668486654?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/637092882668486654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=637092882668486654' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/637092882668486654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/637092882668486654'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/05/t-sql-snippets-codestweaks.html' title='T-SQL Snippets, Codes,Tweaks'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-1819315112117978476</id><published>2009-04-24T16:59:00.000-07:00</published><updated>2009-04-24T17:09:05.586-07:00</updated><title type='text'>SSAS - SQL Server 2005 Analysis Services</title><content type='html'>&lt;strong&gt;Analysis Services&lt;/strong&gt;                  &lt;ul&gt;&lt;li&gt;&lt;a href="http://www.accelebrate.com/sql_training/ssas_tutorial.htm#understanding"&gt; Understanding Analysis Services&lt;/a&gt;&lt;/li&gt;&lt;li&gt; &lt;a href="http://www.accelebrate.com/sql_training/ssas_tutorial.htm#BIDS"&gt;Introducing BIDS&lt;/a&gt;&lt;/li&gt;&lt;li&gt; &lt;a href="http://www.accelebrate.com/sql_training/ssas_tutorial.htm#creating_datacube"&gt;Creating a Data Cube&lt;/a&gt;&lt;/li&gt;&lt;li&gt; &lt;a href="http://www.accelebrate.com/sql_training/ssas_tutorial.htm#exploring_datacube"&gt;Exploring a Data Cube&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;         &lt;p&gt;Files needed:&lt;/p&gt;         &lt;ul&gt;&lt;li&gt;AdventureWorksCube1.zip&lt;/li&gt;&lt;li&gt; AdventureWorksCube2.zip&lt;/li&gt;&lt;/ul&gt;         &lt;p&gt;So far in this course you’ve focused on getting data into a SQL Server database and then later getting the same data out of the database. You’ve seen how to create tables, insert data, and use SQL statements, views, and stored procedures to retrieve the data. This pattern of activity, where individual actions deal with small pieces of the database, is sometimes called &lt;i&gt;online transaction processing&lt;/i&gt;, or OLTP.&lt;/p&gt;         &lt;p&gt;But there’s another use for databases, especially large databases. Suppose you run an online book store and have sales records for 50 million book sales. Maybe books on introductory biology show a strong spike in sales every September. That’s a fact that you could use to your advantage in ordering stock, if only you knew about it. &lt;/p&gt;         &lt;p&gt;Searching for patterns like this and summarizing them is called &lt;i&gt;online analytical processing&lt;/i&gt;, or OLAP. Microsoft SQL Server 2005 includes a separate program called Microsoft SQL Server 2005 Analysis Services to perform OLAP analysis. In this chapter you’ll learn the basics of setting up and using Analysis Services.&lt;/p&gt;         &lt;h1&gt;&lt;a name="understanding"&gt;&lt;/a&gt;SSAS Tutorial: Understanding Analysis Services&lt;/h1&gt;         &lt;p&gt;The basic idea of OLAP is fairly simple. Let’s think about that book ordering data for a moment. Suppose you want to know how many people ordered a particular book during each month of the year. You could write a fairly simple query to get the information you want. The catch is that it might take a long time for SQL Server to churn through that many rows of data.&lt;/p&gt;         &lt;p&gt;And what if the data was not all in a single SQL Server table, but scattered around in various databases throughout your organization? The customer info, for example, might be in an Oracle database, and supplier information in a legacy xBase database. SQL Server can handle distributed heterogeneous queries, but they’re slower.&lt;/p&gt;         &lt;p&gt;What if, after seeing the monthly numbers, you wanted to drill down to weekly or daily numbers? That would be even more time -consuming and require writing even more queries.&lt;/p&gt;         &lt;p&gt;This is where OLAP comes in. The basic idea is to trade off increased storage space now for speed of querying later. OLAP does this by precalculating and storing aggregates. When you identify the data that you want to store in an OLAP database, Analysis Services analyzes it in advance and figures out those daily, weekly, and monthly numbers and stores them away (and stores many other aggregations at the same time). This takes up plenty of disk space, but it means that when you want to explore the data you can do so quickly.&lt;/p&gt;         &lt;p&gt;Later in the chapter, you’ll see how you can use Analysis Services to extract summary information from your data. First, though, you need to familiarize yourself with a new vocabulary. The basic concepts of OLAP include:&lt;/p&gt;         &lt;ul&gt;&lt;li&gt; Cube&lt;/li&gt;&lt;li&gt; Dimension table&lt;/li&gt;&lt;li&gt; Dimension&lt;/li&gt;&lt;li&gt; Level&lt;/li&gt;&lt;li&gt; Fact table&lt;/li&gt;&lt;li&gt; Measure&lt;/li&gt;&lt;li&gt; Schema&lt;/li&gt;&lt;/ul&gt;         &lt;p&gt;&lt;strong&gt;Cube&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;The basic unit of storage and analysis in Analysis Services is the &lt;i&gt;cube&lt;/i&gt;. A cube is a collection of data that’s been aggregated to allow queries to return data quickly. For example, a cube of order data might be aggregated by time period and by title, making the cube fast when you ask questions concerning orders by week or orders by title.&lt;/p&gt;         &lt;p&gt;Cubes are ordered into &lt;i&gt;dimensions&lt;/i&gt; and &lt;i&gt;measures&lt;/i&gt;. Dimensions come from &lt;i&gt;dimension tables&lt;/i&gt;, while measures come from &lt;i&gt;fact tables&lt;/i&gt;.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Dimension table&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;A &lt;i&gt;dimension table&lt;/i&gt; contains hierarchical data by which you’d like to summarize. Examples would be an Orders table, that you might group by year, month, week, and day of receipt, or a Books table that you might want to group by genre and title.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Dimension&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;Each cube has one or more &lt;i&gt;dimensions&lt;/i&gt;, each based on one or more dimension tables. A dimension represents a category for analyzing business data: time or category in the examples above. Typically, a dimension has a natural hierarchy so that lower results can be "rolled up" into higher results. For example, in a geographical level you might have city totals aggregated into state totals, or state totals into country totals. &lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Level&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;Each type of summary that can be retrieved from a single dimension is called a &lt;i&gt;level&lt;/i&gt;. For example, you can speak of a week level or a month level in a time dimension.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Fact table&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;A &lt;i&gt;fact table&lt;/i&gt; contains the basic information that you wish to summarize. This might be order detail information, payroll records, drug effectiveness information, or anything else that’s amenable to summing and averaging. Any table that you’ve used with a Sum or Avg function in a totals query is a good bet to be a fact table.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Measure&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;Every cube will contain one or more &lt;i&gt;measures&lt;/i&gt;, each based on a column in a fact table that you’d like to analyze. In the cube of book order information, for example, the measures would be things such as unit sales and profit.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Schema&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;Fact tables and dimension tables are related, which is hardly surprising, given that you use the dimension tables to group information from the fact table.  The relations within a cube form a &lt;i&gt;schema&lt;/i&gt;. There are two basic OLAP schemas: star and snowflake. In a &lt;i&gt;star schema&lt;/i&gt;, every dimension table is related directly to the fact table. In a &lt;i&gt;snowflake schema&lt;/i&gt;, some dimension tables are related indirectly to the fact table. For example, if your cube includes OrderDetails as a fact table, with Customers and Orders as dimension tables, and Customers is related to Orders, which in turn is related to OrderDetails, then you’re dealing with a snowflake schema.&lt;/p&gt;         &lt;table align="center" border="1" cellpadding="5" cellspacing="5"&gt;             &lt;tbody&gt;&lt;tr&gt;               &lt;td valign="top" width="494"&gt;&lt;p&gt;There are additional schema types besides the star and snowflake schemas, including parent-child schemas and data-mining schemas. However, the star and snowflake schemas are the most common types in normal cubes.&lt;/p&gt;                  &lt;/td&gt;             &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;         &lt;h1&gt;&lt;a name="BIDS" id="BIDS"&gt;&lt;/a&gt;SSAS Tutorial: Introducing Business&lt;br /&gt;&lt;/h1&gt;&lt;h1&gt;Intelligence Development Studio&lt;/h1&gt;         &lt;p&gt;Business Intelligence Development Studio (BIDS) is a new tool in SQL Server 2005 that you can use for analyzing SQL Server data in various ways. You can build three different types of solutions with BIDS:&lt;/p&gt;         &lt;ul&gt;&lt;li&gt; Analysis Services projects&lt;/li&gt;&lt;li&gt; Integration Services projects &lt;/li&gt;&lt;li&gt; Reporting Services projects &lt;/li&gt;&lt;/ul&gt;         &lt;p&gt;To launch Business Intelligence Development Studio, select Microsoft SQL Server 2005 &gt; SQL Server Business Intelligence Development Studio from the Programs menu. BIDS shares the Visual Studio shell, so if you have Visual Studio installed on your computer, this menu item will launch Visual Studio complete with all of the Visual Studio project types (such as Visual Basic and C# projects). &lt;/p&gt;         &lt;h1&gt;&lt;a name="creating_datacube" id="creating_datacube"&gt;&lt;/a&gt;SSAS Tutorial: Creating a Data Cube&lt;/h1&gt;         &lt;p&gt;To build a new data cube using BIDS, you need to perform these steps:&lt;/p&gt;         &lt;ul&gt;&lt;li&gt;Create a new Analysis Services project&lt;/li&gt;&lt;li&gt; Define a data source&lt;/li&gt;&lt;li&gt; Define a data source view&lt;/li&gt;&lt;li&gt; Invoke the Cube Wizard&lt;/li&gt;&lt;/ul&gt;         &lt;p&gt;We’ll look at each of these steps in turn.&lt;/p&gt;         &lt;table align="center" border="1" cellpadding="5" cellspacing="5"&gt;             &lt;tbody&gt;&lt;tr&gt;               &lt;td valign="top" width="494"&gt;&lt;p&gt;You’ll need to have the AdventureWorksDW sample database installed to complete the examples in this chapter. This database is one of the samples that’s available with SQL Server.&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;         &lt;p&gt;&lt;strong&gt;Creating a New Analysis Services Project&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To create a new Analysis Services project, you use the New Project dialog box in BIDS. This is very similar to creating any other type of new project in Visual Studio.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Try It!&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To create a new Analysis Services project, follow these steps:&lt;/p&gt;         &lt;ol&gt;&lt;li&gt;Select Microsoft SQL Server 2005 &gt; SQL Server Business Intelligence Development Studio from the Programs menu to launch Business Intelligence Development Studio.&lt;/li&gt;&lt;li&gt; Select File &gt; New &gt; Project.&lt;/li&gt;&lt;li&gt; In the New Project dialog box, select the Business Intelligence Projects project type.&lt;/li&gt;&lt;li&gt; Select the Analysis Services Project template.&lt;/li&gt;&lt;li&gt; Name the new project AdventureWorksCube1 and select a convenient location to save it.&lt;/li&gt;&lt;li&gt; Click OK to create the new project.&lt;/li&gt;&lt;/ol&gt;         &lt;p&gt;Figure 15-1 shows the Solution Explorer window of the new project, ready to be populated with objects.&lt;/p&gt;         &lt;p align="center"&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image006.jpg" alt="Figure 15-1: New Analysis Services project" width="256" height="229" /&gt;&lt;/p&gt;         &lt;p class="blacksmall" align="center"&gt;Figure 15-1: New Analysis Services project&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Defining a Data Source&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To define a data source, you’ll use the Data Source Wizard. You can launch this wizard by right-clicking on the Data Sources folder in your new Analysis Services project. The wizard will walk you through the process of defining a data source for your cube, including choosing a connection and specifying security credentials to be used to connect to the data source.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Try It!&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To define a data source for the new cube, follow these steps:&lt;/p&gt;         &lt;ol&gt;&lt;li&gt;Right-click on the Data Sources folder in Solution Explorer and select New Data Source.&lt;/li&gt;&lt;li&gt; Read the first page of the Data Source Wizard and click Next.&lt;/li&gt;&lt;li&gt;You can base a data source on a new or an existing connection. Because you don’t have any existing connections, click New.&lt;/li&gt;&lt;li&gt; In the Connection Manager dialog box, select the server containing your analysis services sample database from the Server Name combo box.&lt;/li&gt;&lt;li&gt; Fill in your authentication information.&lt;/li&gt;&lt;li&gt; Select the Native OLE DB\SQL Native Client provider (this is the default provider).&lt;/li&gt;&lt;li&gt; Select the AdventureWorksDW database. Figure 15-2 shows the filled-in Connection Manager dialog box.&lt;/li&gt;&lt;br /&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image008.jpg" alt="Figure 15-2: Setting up a connection" width="517" height="535" /&gt;&lt;br /&gt;&lt;span class="blacksmall"&gt;&lt;center&gt;        &lt;br /&gt;        Figure 15-2: Setting up a connection        &lt;br /&gt;     &lt;br /&gt;      &lt;/center&gt;&lt;/span&gt;&lt;li&gt;Click OK to dismiss the Connection Manager dialog box.&lt;/li&gt;&lt;li&gt;Click Next.&lt;/li&gt;&lt;li&gt; Select Default impersonation information to use the credentials you just supplied for the connection and click Next.&lt;/li&gt;&lt;li&gt;Accept the default data source name and click Finish.&lt;/li&gt;&lt;/ol&gt;         &lt;p&gt;&lt;strong&gt;Defining a Data Source View&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;A data source view is a persistent set of tables from a data source that supply the data for a particular cube. BIDS also includes a wizard for creating data source views, which you can invoke by right-clicking on the Data Source Views folder in Solution Explorer.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Try It!&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To create a new data source view, follow these steps:&lt;/p&gt;         &lt;ol&gt;&lt;li&gt;Right-click on the Data Source Views folder in Solution Explorer and select New Data Source View.&lt;/li&gt;&lt;li&gt;Read the first page of the Data Source View Wizard and click Next.&lt;/li&gt;&lt;li&gt; Select the Adventure Works DW data source and click Next. Note that you could also launch the Data Source Wizard from here by clicking New Data Source.&lt;/li&gt;&lt;li&gt; Select the dbo.FactFinance table in the Available Objects list and click the &gt; button to move it to the Included Object list. This will be the fact table in the new cube.&lt;/li&gt;&lt;li&gt; Click the Add Related Tables button to automatically add all of the tables that are directly related to the dbo.FactFinance table. These will be the dimension tables for the new cube. Figure 15-3 shows the wizard with all of the tables selected.&lt;/li&gt;&lt;br /&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image010.jpg" alt="Figure 15-3: Selecting tables for the data source view" width="500" height="442" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="blacksmall"&gt;         &lt;center&gt;Figure 15-3: Selecting tables for the data source view&lt;br /&gt;     &lt;br /&gt;      &lt;/center&gt;&lt;/span&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt;Name the new view Finance and click Finish. BIDS will automatically display the schema of the new data source view, as shown in Figure 15-4.&lt;/li&gt;&lt;/ol&gt;         &lt;p align="center"&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image012.jpg" alt="Figure 15-4: The Finance data source view" style="border: 1px solid rgb(255, 204, 153);" width="600" height="580" /&gt;&lt;/p&gt;         &lt;p class="blacksmall" align="center"&gt;Figure 15-4: The Finance data source view&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Invoking the Cube Wizard&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;As you can probably guess at this point, you invoke the Cube Wizard by right-clicking on the Cubes folder in Solution Explorer. The Cube Wizard interactively explores the structure of your data source view to identify the dimensions, levels, and measures in your cube.&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Try It!&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To create the new cube, follow these steps:&lt;/p&gt;         &lt;ol&gt;&lt;li&gt; Right-click on the Cubes folder in Solution Explorer and select New Cube.&lt;/li&gt;&lt;li&gt; Read the first page of the Cube Wizard and click Next.&lt;/li&gt;&lt;li&gt; Select the option to build the cube using a data source.&lt;/li&gt;&lt;li&gt; Check the Auto Build checkbox.&lt;/li&gt;&lt;li&gt; Select the option to create attributes and hierarchies.&lt;/li&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt; Select the Finance data source view and click Next.&lt;/li&gt;&lt;li&gt; Wait for the Cube Wizard to analyze the data and then click Next.&lt;/li&gt;&lt;li&gt; The Wizard will get most of the analysis right, but you can fine-tune it a bit. Select DimTime in the Time Dimension combo box. Uncheck the Fact checkbox on the line for the dbo.DimTime table. This will allow you to analyze this dimension using standard time periods.&lt;/li&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt; On the Select Time Periods page, use the combo boxes to match time property names to time columns according to Table 15-1.&lt;br /&gt;       &lt;br /&gt;        &lt;/li&gt;&lt;table border="1"&gt;             &lt;tbody&gt;&lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;&lt;strong&gt;Time Property Name&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;&lt;strong&gt;Time Column&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Year&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;CalendarYear&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Quarter&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;CalendarQuarter&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Month&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;MonthNumberOfYear&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Day of Week&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;DayNumberOfWeek&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Day of Month&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;DayNumberOfMonth&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Day of Year&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;DayNumberOfYear&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Week of Year&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;WeekNumberOfYear&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Fiscal Quarter&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;FiscalQuarter&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;             &lt;tr&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;Fiscal Year&lt;/p&gt;&lt;/td&gt;               &lt;td valign="top" width="307"&gt;&lt;p&gt;FiscalYear&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;&lt;p class="blacksmall" align="center"&gt;Table 15-1: Time columns for Finance cube&lt;/p&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt;Accept the default measures and click Next.&lt;/li&gt;&lt;li&gt; Wait for the Cube Wizard to detect hierarchies and then click Next.&lt;/li&gt;&lt;li&gt; Accept the default dimension structure and click Next.&lt;/li&gt;&lt;li&gt; Name the new cube FinanceCube and click Finish.&lt;/li&gt;&lt;/ol&gt;         &lt;p&gt;&lt;strong&gt;Deploying and Processing a Cube&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;At this point, you’ve defined the structure of the new cube - but there’s still more work to be done. You still need to deploy this structure to an Analysis Services server and then process the cube to create the aggregates that make querying fast and easy.&lt;/p&gt;         &lt;p&gt;To deploy the cube you just created, select Build &gt; Deploy AdventureWorksCube1. This will deploy the cube to your local Analysis Server, and also process the cube, building the aggregates for you. BIDS will open the Deployment Progress window, as shown in Figure 15-5, to keep you informed during deployment and processing.&lt;/p&gt;         &lt;p align="center"&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image014.jpg" alt="Figure 15-5: Deploying a cube" width="256" height="477" /&gt;&lt;/p&gt;         &lt;p class="blacksmall" align="center"&gt;Figure 15-5: Deploying a cube&lt;/p&gt;         &lt;table align="center" border="1" cellpadding="5" cellspacing="5"&gt;             &lt;tbody&gt;&lt;tr&gt;               &lt;td valign="top" width="490"&gt;&lt;p&gt;One of the tradeoffs of cubes is that SQL Server does not attempt to keep your OLAP cube data synchronized with the OLTP data that serves as its source. As you add, remove, and update rows in the underlying OLTP database, the cube will get out of date. To update the cube, you can select Cube &gt; Process in BIDS.  You can also automate cube updates using SQL Server Integration Services, which you’ll learn about in &lt;a href="http://www.accelebrate.com/sql_training/ssis_tutorial.htm"&gt;Chapter 16&lt;/a&gt;.&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;         &lt;h1&gt;&lt;a name="exploring_datacube" id="exploring_datacube"&gt;&lt;/a&gt;SSAS Tutorial: Exploring a Data Cube&lt;/h1&gt;         &lt;p&gt;At last you’re ready to see what all the work was for. BIDS includes a built-in Cube Browser that lets you interactively explore the data in any cube that has been deployed and processed. To open the Cube Browser, right-click on the cube in Solution Explorer and select Browse. Figure 15-6 shows the default state of the Cube Browser after it’s just been opened.&lt;/p&gt;         &lt;p&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image019.jpg" alt="Figure 15-6: The cube browser in BIDS" width="599" height="515" /&gt;&lt;/p&gt;         &lt;p class="blacksmall" align="center"&gt;Figure 15-6: The cube browser in BIDS&lt;/p&gt;         &lt;p&gt;The Cube Browser is a drag-and-drop environment. If you’ve worked with pivot tables in Microsoft Excel, you should have no trouble using the Cube browser. The pane to the left includes all of the measures and dimensions in your cube, and the pane to the right gives you drop targets for these measures and dimensions. Among other operations, you can:&lt;/p&gt;         &lt;ul&gt;&lt;li&gt;Drop a measure in the Totals/Detail area to see the aggregated data for that measure.&lt;/li&gt;&lt;li&gt;Drop a dimension or level in the Row Fields area to summarize by that level or dimension on rows.&lt;/li&gt;&lt;li&gt; Drop a dimension or level in the Column Fields area to summarize by that level or dimension on columns&lt;/li&gt;&lt;li&gt;Drop a dimension or level in the Filter Fields area to enable filtering by members of that dimension or level.&lt;/li&gt;&lt;li&gt; Use the controls at the top of the report area to select additional filtering expressions.&lt;/li&gt;&lt;/ul&gt;         &lt;table align="center" border="1" cellpadding="5" cellspacing="5"&gt;             &lt;tbody&gt;&lt;tr&gt;               &lt;td valign="top" width="494"&gt;&lt;p&gt;In fact, if you’ve worked with pivot tables in Excel, you’ll find that the Cube Browser works exactly the same, because it uses the Microsoft Office PivotTable 11.0 control as its basis.&lt;/p&gt;&lt;/td&gt;             &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;         &lt;p&gt;&lt;strong&gt;Try It!&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To see the data in the cube you just created, follow these steps:&lt;/p&gt;         &lt;ol&gt;&lt;li&gt; Right-click on the cube in Solution Explorer and select Browse.&lt;/li&gt;&lt;li&gt; Expand the Measures node in the metadata panel (the area at the left of the user interface).&lt;/li&gt;&lt;li&gt; Expand the Fact Finance node.&lt;/li&gt;&lt;li&gt; Drag the Amount measure and drop it on the Totals/Detail area.&lt;/li&gt;&lt;li&gt; Expand the Dim Account node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the Account Description property and drop it on the Row Fields area.&lt;/li&gt;&lt;li&gt; Expand the Dim Time node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the Calendar Year-Calendar Quarter-Month Number of Year hierarchy and drop it on the Column Fields area.&lt;/li&gt;&lt;li&gt; Click the + sign next to year 2001 and then the + sign next to quarter 3.&lt;/li&gt;&lt;li&gt; Expand the Dim Scenario node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the Scenario Name property and drop it on the Filter Fields area.&lt;/li&gt;&lt;li&gt; Click the dropdown arrow next to scenario name. Uncheck all of the checkboxes except for the one next to the Budget name.&lt;/li&gt;&lt;/ol&gt;         &lt;p&gt;Figure 15-7 shows the result. The Cube Browser displays month-by-month budgets by account for the third quarter of 2001. Although you could have written queries to extract this information from the original source data, it’s much easier to let Analysis Services do the heavy lifting for you.&lt;/p&gt;         &lt;p align="center"&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image024.jpg" alt="Figure 15-7: Exploring cube data in the cube browser" width="599" height="515" /&gt;&lt;/p&gt;         &lt;p class="blacksmall" align="center"&gt;Figure 15-7: Exploring cube data in the cube browser&lt;/p&gt;         &lt;b&gt;&lt;br /&gt;      &lt;/b&gt;         &lt;h1&gt;SSAS Tutorial: Exercises&lt;/h1&gt;         &lt;p&gt;Create a data cube, based on the data in the AdventureWorksDW sample database, to answer the following question: what were the internet sales by country and product name for married customers only?&lt;/p&gt;         &lt;p&gt;&lt;strong&gt;Solutions to Exercises&lt;/strong&gt;&lt;/p&gt;         &lt;p&gt;To create the cube, follow these steps:&lt;/p&gt;         &lt;ol&gt;&lt;li&gt; Select Microsoft SQL Server 2005 &gt; SQL Server Business Intelligence Development Studio from the Programs menu to launch Business Intelligence Development Studio.&lt;/li&gt;&lt;li&gt; Select File &gt; New &gt; Project.&lt;/li&gt;&lt;li&gt; In the New Project dialog box, select the Business Intelligence Projects project type.&lt;/li&gt;&lt;li&gt; Select the Analysis Services Project template.&lt;/li&gt;&lt;li&gt; Name the new project AdventureWorksCube2 and select a convenient location to save it.&lt;/li&gt;&lt;li&gt; Click OK to create the new project.&lt;/li&gt;&lt;li&gt; Right-click on the Data Sources folder in Solution Explorer and select New Data Source.&lt;/li&gt;&lt;li&gt; Read the first page of the Data Source Wizard and click Next.&lt;/li&gt;&lt;li&gt; Select the existing connection to the AdventureWorksDW database and click Next.&lt;/li&gt;&lt;li&gt; Select Default and click Next.&lt;/li&gt;&lt;li&gt; Accept the default data source name and click Finish.&lt;/li&gt;&lt;li&gt; Right-click on the Data Source Views folder in Solution Explorer and select New Data Source View.&lt;/li&gt;&lt;li&gt; Read the first page of the Data Source View Wizard and click Next.&lt;/li&gt;&lt;li&gt; Select the Adventure Works DW data source and click Next. &lt;/li&gt;&lt;li&gt; Select the dbo.FactInternetSales table in the Available Objects list and click the &gt; button to move it to the Included Object list. &lt;/li&gt;&lt;li&gt; Click the Add Related Tables button to automatically add all of the tables that are directly related to the dbo.FactInternetSales table. &lt;/li&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt; Name the new view InternetSales and click Finish. &lt;/li&gt;&lt;li&gt; Right-click on the Cubes folder in Solution Explorer and select New Cube.&lt;/li&gt;&lt;li&gt; Read the first page of the Cube Wizard and click Next.&lt;/li&gt;&lt;li&gt; Select the option to build the cube using a data source.&lt;/li&gt;&lt;li&gt; Check the Auto Build checkbox.&lt;/li&gt;&lt;li&gt; Select the option to create attributes and hierarchies.&lt;/li&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt; Select the InternetSales data source view and click Next.&lt;/li&gt;&lt;li&gt; Wait for the Cube Wizard to analyze the data and then click Next.&lt;/li&gt;&lt;li&gt; Click Next.&lt;/li&gt;&lt;li&gt; Accept the default measures and click Next.&lt;/li&gt;&lt;li&gt; Wait for the Cube Wizard to detect hierarchies and then click Next.&lt;/li&gt;&lt;li&gt; Accept the default dimension structure and click Next.&lt;/li&gt;&lt;li&gt; Name the new cube InternetSalesCube and click Finish.&lt;/li&gt;&lt;li&gt; Select Build &gt; Deploy AdventureWorksCube2. &lt;/li&gt;&lt;li&gt; Right-click on the cube in Solution Explorer and select Browse.&lt;/li&gt;&lt;li&gt; Expand the Measures node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the Order Quantity and Sales Amount measures and drop it on the Totals/Detail area.&lt;/li&gt;&lt;li&gt; Expand the Dim Sales Territory node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the Sales Territory Country property and drop it on the Row Fields area.&lt;/li&gt;&lt;li&gt; Expand the Dim Product node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the English Product Name property and drop it on the Column Fields area.&lt;/li&gt;&lt;li&gt; Expand the Dim Customer node in the metadata panel.&lt;/li&gt;&lt;li&gt; Drag the Marital Status property and drop it on the Filter Fields area.&lt;/li&gt;&lt;li&gt; Click the dropdown arrow next to Marital Status. Uncheck the S checkbox.&lt;/li&gt;&lt;/ol&gt;         &lt;p&gt;Figure 15-8 shows the finished cube.&lt;/p&gt;         &lt;p align="center"&gt;&lt;img src="http://www.accelebrate.com/sql_training/SSAS_tutorial_files/image026.jpg" alt="Figure 15-8: The AdventureWorksCube2 cube" width="599" height="515" /&gt;&lt;/p&gt;         &lt;p class="blacksmall" align="center"&gt;Figure 15-8: The AdventureWorksCube2 cube&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-1819315112117978476?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.accelebrate.com/sql_training/ssas_tutorial.htm' title='SSAS - SQL Server 2005 Analysis Services'/><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/1819315112117978476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=1819315112117978476' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/1819315112117978476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/1819315112117978476'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/04/ssas-sql-server-2005-analysis-services.html' title='SSAS - SQL Server 2005 Analysis Services'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8286117907522840211</id><published>2009-03-11T16:29:00.000-07:00</published><updated>2009-04-15T18:18:15.298-07:00</updated><title type='text'>Cursor Optimization Tips</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;    Try to avoid using SQL Server cursors, whenever possible.&lt;br /&gt;&lt;/div&gt;      SQL Server cursors can results in some performance degradation in comparison with select statements. Try to use correlated subquery or derived tables, if you need to perform row-by-row operations.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    Do not forget to close SQL Server cursor when its result set is not needed.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     To close SQL Server cursor, you can use CLOSE {cursor_name} command. This command releases the cursor result set and frees any cursor locks held on the rows on which the cursor is positioned.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;Do not forget to deallocate SQL Server cursor when the data structures comprising the cursor are not needed.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     To deallocate SQL Server cursor, you can use DEALLOCATE {cursor_name} command. This command removes a cursor reference and releases the data structures comprising the cursor.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;     Try to reduce the number of records to process in the cursor.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     To reduce the cursor result set, use the WHERE clause in the cursor's select statement. It can increase cursor performance and reduce SQL Server overhead.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    Try to reduce the number of columns to process in the cursor.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     Include in the cursor's select statement only necessary columns. It will reduce the cursor result set. So, the cursor will use fewer resources. It can increase cursor performance and reduce SQL Server overhead.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    Use READ ONLY cursors, whenever possible, instead of updatable cursors.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     Because using cursors can reduce concurrency and lead to unnecessary locking, try to use READ ONLY cursors, if you do not need to update cursor result set.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    Try avoid using insensitive, static and keyset cursors, whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     These types of cursor produce the largest amount of overhead on SQL Server, because they cause a temporary table to be created in TEMPDB, which results in some performance degradation.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    Use FAST_FORWARD cursors, whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     The FAST_FORWARD cursors produce the least amount of overhead on SQL Server, because there are read-only cursors and can only be scrolled from the first to the last row. Use FAST_FORWARD cursor if you do not need to update cursor result set and the FETCH NEXT will be the only used fetch option.&lt;br /&gt;&lt;br /&gt;     *****&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    Use FORWARD_ONLY cursors, if you need updatable cursor and the FETCH NEXT will be the only used fetch option.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     If you need read-only cursor and the FETCH NEXT will be the only used fetch option, try to use FAST_FORWARD cursor instead of FORWARD_ONLY cursor. By the way, if one of the FAST_FORWARD or FORWARD_ONLY is specified the other cannot be specified.&lt;br /&gt;&lt;br /&gt;     *****&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8286117907522840211?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8286117907522840211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8286117907522840211' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8286117907522840211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8286117907522840211'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/03/cursor-optimization-tips.html' title='Cursor Optimization Tips'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-6249323182092525624</id><published>2009-03-11T16:12:00.000-07:00</published><updated>2009-03-11T16:18:14.225-07:00</updated><title type='text'>Bulk Copy Optimization Tips</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;    Use nonlogged bulk copy whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;      The nonlogged bulk copy is much faster than logged one, but to use it you must provide all the following conditions:&lt;br /&gt;&lt;div style="text-align: left;"&gt;      1. The database option 'select into/bulkcopy' is set to true.&lt;br /&gt;      2. The target table is not being replicated.&lt;br /&gt;      3. The TABLOCK hint is specified.&lt;br /&gt;      4. The target table has no indexes, or if the table has indexes, it is empty when the bulk copy starts.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;br /&gt;    &lt;span style="font-weight: bold;"&gt;Use native mode bulk copy whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      This can improve performance in comparison with the character mode.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;    Try to use BULK INSERT command instead of bcp or DTS to load data into SQL Server.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      The BULK INSERT command is much faster than bcp or the data pump to perform text file import operations, however, the BULK INSERT statement cannot bulk copy data from SQL Server to a data file.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;    &lt;span style="font-weight: bold;"&gt;Use the bcp utility instead of DTS when you need to export data from the SQL Server table into a text file.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;      The bcp utility is much faster than DTS, so try to use it whenever possible.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;    Specify the number of the first and the last row to bulk copy, if you need to bulk copy not all the rows from the specified data file.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      This can results in good performance benefits, because the total amount of data copied will be less.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;    Specify the number of rows per batch of data copied, if the transaction log was filled before the bulk copy is complete.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      Because each batch is copied to the server as one transaction, SQL Server commits or rolls back the transaction for every batch. When you bulk copy large data files, the transaction log can be filled before the bulk copy is complete. In this case, enlarge the transaction log, allow it to grow automatically or specify the number of rows per batch of data copied.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;    &lt;span style="font-weight: bold;"&gt;Try to increase the packet_size option.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      The packet_size option specifies the number of bytes, per network packet, sent to and from the server. The packet_size can be from 4096 to 65535 bytes with the default of 4096. Increased packet size can enhance performance of bulk copy operations. Try to set the packet_size option to 8192 bytes and continue monitoring.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;   Use the ORDER hint, if the clustered index exists on the table and the data file is sorted according to the clustered index.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      This can significantly improve performance of the bulk copy operation, because SQL Server will load data in the clustered index order without any reorders operations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;    If you create a new table and bulk copy data into it, try to bulk load data first and only after that create any indexes.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      This can significantly improve performance of the bulk copy operation, because data will be loaded into SQL Server table without any index pages creation during the bulk copy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;    &lt;span style="font-weight: bold;"&gt;If you load data into an empty table with the existing nonclustered indexes, try to drop the nonclustered indexes, bulk load data and only after that re-create the nonclustered indexes.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      This can significantly improve performance of the bulk copy operation, because data will be loaded into SQL Server table without any index pages creation during the bulk copy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;    &lt;span style="font-weight: bold;"&gt;If you load data into a nonempty table with the existing clustered and/or nonclustered indexes, and the amount of data added is large, it can be faster to drop all indexes on the table, perform the bulk copy operation, and then re-create the indexes after the data is loaded.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      Check the time needed to load data with dropping/re-creating indexes and without dropping/re-creating indexes on your test server before run bulk copy operation on the production server.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-weight: bold; text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    If your SQL Server box has multiple CPUs, try to divide loaded data into two or more sources and run multiple instances of BCP on separate clients to load data in parallel.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      Because SQL Server allows data to be bulk copied into a single table from multiple clients in parallel using the bcp utility or BULK INSERT statement, try to use parallel data loads whenever possible. To bulk copy data into SQL Server in parallel, you must provide all the following conditions:&lt;br /&gt;&lt;div style="text-align: left;"&gt;      1. The database option 'select into/bulkcopy' is set to true.&lt;br /&gt;      2. The TABLOCK hint is specified.&lt;br /&gt;      3. The target table does not have any indexes.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;    Specify the TABLOCK hint, if you bulk copy data into an empty table from a single client.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;      This can improve performance of the bulk copy operation, because this causes a table-level lock to be taken for the duration of the bulk copy operation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;      *****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;     Try to avoid using CHECK_CONSTRAINTS and FIRE_TRIGGERS hints.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     Using these hints can significantly degrade performance of the bulk copy operation, because for each row loaded the constraints and insert triggers defined on the destination table will be executed.&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-6249323182092525624?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/6249323182092525624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=6249323182092525624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/6249323182092525624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/6249323182092525624'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/03/bulk-copy-optimization-tips.html' title='Bulk Copy Optimization Tips'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-917906358156333056</id><published>2009-03-11T15:54:00.000-07:00</published><updated>2009-03-11T16:08:50.335-07:00</updated><title type='text'>Optimization for designing tables</title><content type='html'>&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Normalize your tables to the third normal form.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;A table is in third normal form (3NF) if it is in second normal form (2NF) and if it does not contain transitive dependencies. In most cases, you should normalize your tables to the third normal form. The normalization is used to reduce the total amount of redundant data in the database. The less data there is, the less work SQL Server has to perform, speeding its performance.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;*****&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Consider the denormalization of your tables from the forth or fifth normal forms to the third normal form.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Normalization to the forth and fifth normal forms can result in some performance degradation, especially when you need to perform many joins against several tables. It may be necessary to denormalize your tables to prevent performance degradation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Consider horizontal partitioning of the very large tables into the current and the archives versions.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The less space used, the smaller the table, the less work SQL Server has to perform to evaluate your queries. For example, if you need to query only data for the current year in your daily work, and you need all the data only once per month for the monthly report, you can create two tables: one with the current year's data and one with the old data.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Create the table's columns as narrow as possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;This can reduce the table's size and improve performance of your queries as well as some maintenance tasks (such as backup, restore and so on).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Try to reduce the number of columns in a table.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The fewer the number of columns in a table, the less space the table will use, since more rows will fit on a single data page, and less I/O overhead will be required to access the table's data.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Try to use constraints instead of triggers, rules, and defaults whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Constraints are much more efficient than triggers and can boost performance. Constraints are more consistent and reliable in comparison to triggers, rules and defaults, because you can make errors when you write your own code to perform the same actions as the constraints.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;If you need to store integer data from 0 through 255, use tinyint data type.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The columns with tinyint data type use only one byte to store their values, in comparison with two bytes, four bytes and eight bytes used to store the columns with smallint, int and bigint data types accordingly. For example, if you design tables for a small company with 5-7 departments, you can create the departments table with the DepartmentID tinyint column to store the unique number of each department.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;If you need to store integer data from -32,768 through 32,767, use smallint data type.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The columns with smallint data type use only two bytes to store their values, in comparison with four bytes and eight bytes used to store the columns with int and bigint data types respectively. For example, if you design tables for a company with several hundred employees, you can create an employee table with the EmployeeID smallint column to store the unique number of each employee.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;If you need to store integer data from -2,147,483,648 through 2,147,483,647, use int data type.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The columns with int data type use only four bytes to store their values, in comparison with eight bytes used to store the columns with bigint data types. For example, to design tables for a library with more than 32,767 books, create a books table with a BookID int column to store the unique number of each book.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Use smallmoney data type instead of money data type, if you need to store monetary data values from 214,748.3648 through 214,748.3647.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The columns with smallmoney data type use only four bytes to store their values, in comparison with eight bytes used to store the columns with money data types. For example, if you need to store the monthly employee payments, it might be possible to use a column with the smallmoney data type instead of money data type.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Use smalldatetime data type instead of datetime data type, if you need to store the date and time data from January 1, 1900 through June 6, 2079, with accuracy to the minute.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The columns with smalldatetime data type use only four bytes to store their values, in comparison with eight bytes used to store the columns with datetime data types. For example, if you need to store the employee's hire date, you can use column with the smalldatetime data type instead of datetime data type.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Use varchar/nvarchar columns instead of text/ntext columns whenever possible.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;Because SQL Server stores text/ntext columns on the Text/Image pages separately from the other data, stored on the Data pages, it can take more time to get the text/ntext values.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Use char/varchar columns instead of nchar/nvarchar if you do not need to store unicode data.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The char/varchar value uses only one byte to store one character, the nchar/nvarchar value uses two bytes to store one character, so the char/varchar columns use two times less space to store data in comparison with nchar/nvarchar columns.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Consider setting the 'text in row' SQL Server 2000 table's option.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The text, ntext, and image values are stored on the Text/Image pages, by default. This option specifies that small text, ntext, and image values will be placed on the Data pages with other data values in a data row. This can increase the speed of read and write operations and reduce the amount of space used to store small text, ntext, and image data values. You can set the 'text in row' table option by using the sp_tableoption stored procedure.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;If you work with SQL Server 2000, use cascading referential integrity constraints instead of triggers whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;For example, if you need to make cascading deletes or updates, specify the ON DELETE or ON UPDATE clause in the REFERENCES clause of the CREATE TABLE or ALTER TABLE statements. The cascading referential integrity constraints are much more efficient than triggers and can boost performance.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-917906358156333056?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/917906358156333056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=917906358156333056' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/917906358156333056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/917906358156333056'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/03/optimization-for-designing-tables.html' title='Optimization for designing tables'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8440583442504100046</id><published>2009-03-11T15:45:00.000-07:00</published><updated>2009-03-11T15:52:40.580-07:00</updated><title type='text'>Transact-SQL Optimization Tips</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt; Try to restrict the queries result set by using the WHERE clause.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;This can results in good performance benefits, because SQL Server will return to client only particular rows, not all rows from the table(s). This can reduce network traffic and boost the overall performance of the query.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt; Try to restrict the queries result set by returning only the particular columns from the table, not all table's columns.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;This can results in good performance benefits, because SQL Server will return to client only particular columns, not all table's columns. This can reduce network traffic and boost the overall performance of the query.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;Use views and stored procedures instead of heavy-duty queries.&lt;br /&gt;&lt;/div&gt;This can reduce network traffic, because your client will send to server only stored procedure or view name (perhaps with some parameters) instead of large heavy-duty queries text. This can be used to facilitate permission management also, because you can restrict user access to table columns they should not see.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center; font-weight: bold;"&gt;Try to avoid using SQL Server cursors, whenever possible.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;SQL Server cursors can result in some performance degradation in comparison with select statements. Try to use correlated subquery or derived tables, if you need to perform row-by-row operations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt; If you need to return the total table's row count, you can use alternative way instead of SELECT COUNT(*) statement.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Because SELECT COUNT(*) statement make a full table scan to return the total table's row count, it can take very many time for the large table. There is another way to determine the total row count in a table. You can use sysindexes system table, in this case. There is ROWS column in the sysindexes table. This column contains the total row count for each table in your database. So, you can use the following select statement instead of SELECT COUNT(*): SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid &lt; style="text-align: center; font-weight: bold;"&gt;*****&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Try to use constraints instead of triggers, whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Constraints are much more efficient than triggers and can boost performance. So, you should use constraints instead of triggers, whenever possible.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Use table variables instead of temporary tables.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Table variables require less locking and logging resources than temporary tables, so table variables should be used whenever possible. The table variables are available in SQL Server 2000 only.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Try to avoid the HAVING clause, whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The HAVING clause is used to restrict the result set returned by the GROUP BY clause. When you use GROUP BY with the HAVING clause, the GROUP BY clause divides the rows into sets of grouped rows and aggregates their values, and then the HAVING clause eliminates undesired aggregated groups. In many cases, you can write your select statement so, that it will contain only WHERE and GROUP BY clauses without HAVING clause. This can improve the performance of your query.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Try to avoid using the DISTINCT clause, whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Because using the DISTINCT clause will result in some performance degradation, you should use this clause only when it is necessary.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Include SET NOCOUNT ON statement into your stored procedures to stop the message indicating the number of rows affected by a T-SQL statement.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;This can reduce network traffic, because your client will not receive the message indicating the number of rows affected by a T-SQL statement.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt; Use the select statements with TOP keyword or the SET ROWCOUNT statement, if you need to return only the first n rows.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;This can improve performance of your queries, because the smaller result set will be returned. This can also reduce the traffic between the server and the clients.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt; &lt;span style="font-weight: bold;"&gt;Use the FAST number_rows table hint if you need to quickly return 'number_rows' rows.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;You can quickly get the n rows and can work with them, when the query continues execution and produces its full result set.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Try to use UNION ALL statement instead of UNION, whenever possible.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;The UNION ALL statement is much faster than UNION, because UNION ALL statement does not look for duplicate rows, and UNION statement does look for duplicate rows, whether or not they exist.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Do not use optimizer hints in your queries.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Because SQL Server query optimizer is very clever, it is very unlikely that you can optimize your query by using optimizer hints, more often, this will hurt performance.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;*****&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8440583442504100046?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8440583442504100046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8440583442504100046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8440583442504100046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8440583442504100046'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/03/transact-sql-optimization-tips.html' title='Transact-SQL Optimization Tips'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-539149935921570292</id><published>2009-03-04T19:57:00.001-08:00</published><updated>2009-03-04T19:57:47.440-08:00</updated><title type='text'>MS SQL Server Shortcut keys</title><content type='html'>&lt;p&gt;&lt;!----&gt;&lt;/p&gt;   &lt;div id="ctl00_rs1_mainContentContainer_cpe47537" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47537_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47537');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47537_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Menu Activation Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47537_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle0"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the SQL Server Management Studio menu bar&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Activate the menu for a tool component&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+HYPHEN&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+HYPHEN&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the context menu&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F10&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F10&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;New File&lt;/strong&gt; dialog box to create a file&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+N&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;New Project&lt;/strong&gt; dialog box to create a new project&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+N&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+N&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Open File&lt;/strong&gt; dialog box to open an existing file&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+O&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+INS&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Open Project&lt;/strong&gt; dialog box to open an existing project&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+O&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Add New Item&lt;/strong&gt; dialog box to add a new file to the current project&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+A&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Add Existing Item&lt;/strong&gt; dialog box to add an existing file to the current project&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+SHIFT+A&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Query Designer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+Q&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+Q&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Close a menu or dialog box, canceling the action&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ESC&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ESC&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47538" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47538_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47538');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47538_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Windows Management and Toolbar Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47538_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle1"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Close the current MDI child window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F4&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Print&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+P&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+P&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Exit&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F4&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Toggle full screen mode&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Close the current tool window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ESC&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ESC&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Cycle through the next MDI child windows&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Cycle through the previous MDI child windows&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the current tool window toolbar&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the next tool window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the previously selected window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Opens a new query editor window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+O&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display Object Explorer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F8&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F8&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display Registered Servers&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+G&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display Template Explorer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+T&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+T&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display Solution Explorer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+L&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Summary Window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F7&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F7&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Properties Window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F4&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Toolbox&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+X&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+X&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Bookmarks Window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL+W&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Browser Window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+R&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+R&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Error List Window (Transact-SQL Editor only)&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CRTL+\, CTRL+E&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CRTL+\, CTRL+E&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47539" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47539_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47539');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47539_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Cursor Movement Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47539_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle2"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor left&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor right&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor up&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor down&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the beginning of the line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;HOME&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;HOME&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the end of the line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;END&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;END&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the beginning of the document&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+HOME&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+HOME&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the end of the document&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+END&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+END&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor up one screen&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;PAGE UP&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;PAGE UP&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor down one screen&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;PAGE DOWN&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;PAGE DOWN&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Moves the cursor one word to the right&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+&lt;/p&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+&lt;/p&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Moves the cursor one word to the left&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+&lt;/p&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+&lt;/p&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47540" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47540_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47540');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47540_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Text Selection Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47540_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle3"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select text from the cursor to the beginning of the document&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;HOME&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;HOME&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select text from the cursor to the end of the document&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+END&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+END&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select text from the cursor to the start of the current line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+HOME&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+HOME&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select text from the cursor to the end of the current line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+END&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+END&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select text down line by line starting from the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select text up line by line starting from the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor up one line, extending the selection&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+&lt;/p&gt;             &lt;p&gt;UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+&lt;/p&gt;             &lt;p&gt;UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Extend selection up one page&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE UP&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE UP&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Extend selection down one page&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE DOWN&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE DOWN&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select the entire current document&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+A&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+A&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select the word containing the cursor, or the closest word&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+W&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+W&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select the current location in the editor, back to the previous location in the editor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+=&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+=&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Extend the selection to the top of the current window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE UP&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE UP&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the last line in view, extending the selection&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE DOWN&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;PAGE DOWN&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Extend the selection one word to the right&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Extend the selection one word to the left&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the right one word, extending the selection&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+ALT+&lt;/p&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+ALT+&lt;/p&gt;             &lt;p&gt;RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move the cursor to the left one word, extending the selection&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+ALT+&lt;/p&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+ALT+&lt;/p&gt;             &lt;p&gt;LEFT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47541" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47541_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47541');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47541_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Bookmark Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47541_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle4"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Set or remove a bookmark at the current line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL+K&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F2&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Next bookmark&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL+N&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F2&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Previous bookmark&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL+P&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F2&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Clear bookmarks&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F2&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47542" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47542_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47542');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47542_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Tree Control Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47542_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle5"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Collapse tree nodes&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;- (on the numeric keypad)&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;- (on the numeric keypad)&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Expand all tree nodes&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;*  (on the numeric keypad)&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;* (on the numeric keypad)&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Scroll the tree control up in the window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Scroll the tree control down in the window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47543" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47543_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47543');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47543_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Code Editor Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47543_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle6"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;p&gt;All shortcuts are not implemented in all types of code editors.&lt;/p&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Toggle the full-screen display &lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Scroll text up one line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+UP ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Scroll text down one line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+&lt;/p&gt;             &lt;p&gt;DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+&lt;/p&gt;             &lt;p&gt;DOWN ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Reverse the last editing action&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+Z&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+Z&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Restore the previously undone edit&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+Z&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+Y&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;ALT+SHIFT+BACKSPACE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+Z&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+Y&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;ALT+SHIFT+BACK SPACE&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Insert the body of the specified file into the current window.&lt;/p&gt;             &lt;div class="alert"&gt;&lt;div class="mtps-row"&gt;&lt;span class="mtps-cell"&gt;               The window name is not changed to match the specified file.&lt;span&gt;&lt;!----&gt;&lt;/span&gt;             &lt;/span&gt;&lt;/div&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;&lt;!--src=[../local/note.gif]--&gt;&lt;img alt="ms174205.note(en-us,SQL.100).gif" src="http://i.msdn.microsoft.com/ms174205.note%28en-us,SQL.100%29.gif" /&gt;Note: &lt;/th&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;!----&gt;&lt;/p&gt;&lt;/div&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+P&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Save the selected item&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+S&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+S&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Save all&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+S&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+S&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Close&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F4&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Print&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+P&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+P&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Exit&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F4&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Delete all text in the current file&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+DEL&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+DEL&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Go To Line&lt;/strong&gt; dialog box&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+G&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+G&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Increase line indent&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Decrease line indent&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Make the selected text upper case&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+U&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+U&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Make the selected text lower case&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+L&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Make the selected text a comment&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL+C&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+C&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Uncomment the selected text&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K, CTRL + U&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+R&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Open a new query with current connection&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+Q&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+N&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Open database in Object Explorer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F8&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F8&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Specify values for template parameters&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+M&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+M&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Execute the selected portion of the query editor or the entire query editor if nothing is selected&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+E&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;ALT+X&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+E&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;ALT+X&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Parse the selected portion of the query editor or the entire query editor if nothing is selected&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F5&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F5&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the estimated execution plan&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+L&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Cancel the executing query&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+BREAK&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+BREAK&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Include actual execution plan in the query output&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+M&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+K&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Open the &lt;strong&gt;Query Option&lt;/strong&gt; dialog box&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+O&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Output results in a grid&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+D&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+D&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Output results in text format&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+T&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+T&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Output results to a file&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Show or hide the query results pane&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+R&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+R&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Toggle between query and results pane&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the next active window in Management Studio &lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Auto hide all&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Windows&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+W&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Open SQL Server Profiler&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+P&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+P&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47544" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47544_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47544');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47544_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Text Manipulation in Code Editor Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47544_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle7"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Insert a new line&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ENTER or SHIFT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ENTER or SHIFT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Swap the characters on either side of the cursor (Does not apply to the SQL Editor.)&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+T&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Delete on character to the right of the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;DELETE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;DELETE&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Delete one character to the left of the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;BACKSPACE&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;BACKSPACE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;BACKSPACE&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;SHIFT+&lt;/p&gt;             &lt;p&gt;BACKSPACE&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Insert the number of spaces configured for the editor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Insert a blank line above the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Insert a blank line below the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+&lt;/p&gt;             &lt;p&gt;ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Change the selected text to lowercase&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+L&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Change the selected text to uppercase&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+U&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+U&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Toggle between insertion mode and overtype mode&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;INSERT&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;INSERT&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move selected lines to the left on tab stop&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Delete the word to the right of the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+DELETE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+DELETE&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Delete the word to the left of the cursor&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+BACKSPACE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+BACKSPACE&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Transpose the words on either side of the cursor (Does not apply to the SQL Editor.)&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+T&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+T&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47545" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47545_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47545');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47545_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Transact-SQL Debugger Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47545_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle8"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Start or continue debugging&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F5&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Stop debugging&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F5&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Step into&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F11&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Step over&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F10&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Step out&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F11&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Implement the &lt;strong&gt;Run To Cursor&lt;/strong&gt; command&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F10&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;QuickWatch&lt;/strong&gt; dialog box&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+Q&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Toggle breakpoint&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F9&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Delete all breakpoints&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F9&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Breakpoints&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+B&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Break all&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+BREAK&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Watch 1&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+W, 1&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Watch 2&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+W, 2&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Watch 3&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+W, 3&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Watch 4&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+W, 4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Autos&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+V, A&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Locals&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+V, L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Immediate&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+I&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Call Stack&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+C&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Threads&lt;/strong&gt; window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+H&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47546" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47546_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47546');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47546_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Microsoft IntelliSense Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47546_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle9"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;List members&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SPACE&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+J&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+J&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Complete word&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+RIGHT ARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Parameter information&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+SPACE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Jump between syntax pairs&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+]&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47547" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47547_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47547');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47547_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Document Window and Browser Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47547_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle10"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Toggle full-screen mode&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+ALT+ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the next pane of a split pane view of a document&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the previous document in the editor or designer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F6&lt;/p&gt;             &lt;p&gt;CTRL+SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F6&lt;/p&gt;             &lt;p&gt;CTRL+SHIFT+TAB&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the previous pane of a document in split pane view&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the Browser Window&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+R&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+R&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Back, display the previous page in the viewing history&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+LEFTARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+LEFTARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Forward, display the next page in the viewing history&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+RIGHTARROW&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+RIGHTARROW&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47548" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47548_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47548');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47548_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Solution Explorer Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47548_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle11"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display Solution Explorer&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+L&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;New File&lt;/strong&gt; dialog box to create a new file&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+N&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+INS&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;New Project&lt;/strong&gt; dialog box to create a new project&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+N&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+N&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Open File&lt;/strong&gt; dialog box to open an existing file&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+O&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;No equivalent&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47549" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47549_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47549');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47549_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Help and Books Online Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47549_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle12"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Help&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F1&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F1&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Help on "How Do I"&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F1&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F1&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Books Online Contents&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F1&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F1&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Books Online Index&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F2&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F2&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Help Search&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F3&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F3&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Dynamic Help&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F4&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F4&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Help Favorites&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+ALT+F&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47550" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47550_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47550');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47550_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Search Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47550_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle13"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Find&lt;/strong&gt; dialog box&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Replace&lt;/strong&gt; dialog box&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+H&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+H&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Start incremental search. Type the characters to search for or press CTRL+I to search for characters from the previous search&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+I&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+B&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Find the next occurrence of the previous search text&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F3&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F3&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Find the previous occurrence of the search text&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F3&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;SHIFT+F3&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Find the next occurrence of the currently selected text&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F3&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+F3&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Find the previous occurrence of the currently selected text&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F3&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F3&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Display the &lt;strong&gt;Replace in Files&lt;/strong&gt; dialog box&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+H&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+H&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Reverse incremental search so it starts at the bottom of the file and searches to the top&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+I&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+I&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select or clear the &lt;strong&gt;Search up &lt;/strong&gt;option in &lt;strong&gt;Find and Replace&lt;/strong&gt;&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, B&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, B&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Stop the &lt;strong&gt;Find in Files &lt;/strong&gt;search&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, S&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, S&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Select or clear the &lt;strong&gt;Find whole word&lt;/strong&gt; option in &lt;strong&gt;Find and Replace&lt;/strong&gt;&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, W&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, W&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Selects or clears the &lt;strong&gt;Wildcard &lt;/strong&gt;option in &lt;strong&gt;Find and Replace&lt;/strong&gt;&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, P&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+F3, P&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47551" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47551_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47551');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47551_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Cut and Paste Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47551_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle14"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Cut (delete the currently selected item and place it to the Clipboard)&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+X&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;SHIFT+DELETE&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+X&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;SHIFT+DELETE&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Copy to the Clipboard&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+C&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+INSERT&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+C&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;CTRL+INSERT&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Paste from the Clipboard at the insertion point&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+V&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;SHIFT+INSERT&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+V&lt;/p&gt;             &lt;p&gt;or&lt;/p&gt;             &lt;p&gt;SHIFT+INSERT&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47552" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47552_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47552');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47552_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Log Viewer Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47552_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle15"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Refresh&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move between the &lt;strong&gt;Select logs &lt;/strong&gt;pane and the &lt;strong&gt;Log file summary &lt;/strong&gt;pane&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Move to the &lt;strong&gt;Log file summary&lt;/strong&gt; pane&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+S&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ALT+S&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Load a new log&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+L&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+L&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Export a log&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+E&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+E&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Filter a log&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Search in a log&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+S&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+S&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47553" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47553_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47553');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47553_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Activity Monitor Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47553_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle16"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Refresh&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Filter the monitor display&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;CTRL+SHIFT+F&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47554" class="MTPS_CollapsibleRegion"&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47554_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47554');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47554_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Replication Monitor Keyboard Shortcuts    &lt;/div&gt;&lt;div id="ctl00_rs1_mainContentContainer_cpe47554_c" class="MTPS_CollapsibleSection" style="display: block;"&gt;     &lt;a id="sectionToggle17"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Refresh&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F5&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Open a detail window from a grid&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ENTER&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;ENTER&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;         &lt;/div&gt;   &lt;/div&gt;    &lt;div id="ctl00_rs1_mainContentContainer_cpe47555_h" class="CollapseRegionLink" onclick="applyClick('ctl00_rs1_mainContentContainer_cpe47555');"&gt;     &lt;img id="ctl00_rs1_mainContentContainer_cpe47555_i" class="LibC_o" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" style="border-width: 0px; vertical-align: middle;" /&gt; Replication Conflict Viewer Keyboard Shortcuts    &lt;/div&gt;     &lt;a id="sectionToggle18"&gt;&lt;!----&gt;&lt;/a&gt;       &lt;h3 class="subHeading"&gt;&lt;!----&gt;&lt;/h3&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;               Action             &lt;/th&gt;&lt;th&gt;               Standard             &lt;/th&gt;&lt;th&gt;               SQL Server 2000             &lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Define filter&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F6&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Apply filter&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F7&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F7&lt;/p&gt;           &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;             &lt;p&gt;Show all columns&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F8&lt;/p&gt;           &lt;/td&gt;&lt;td&gt;             &lt;p&gt;F8&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-539149935921570292?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/539149935921570292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=539149935921570292' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/539149935921570292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/539149935921570292'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/03/ms-sql-server-shortcut-keys.html' title='MS SQL Server Shortcut keys'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-1950816189151938302</id><published>2009-03-04T19:53:00.000-08:00</published><updated>2009-03-04T19:55:29.860-08:00</updated><title type='text'>Sysobjects Information</title><content type='html'>Use Sysobjects in SQL Server to Find Useful Database Information&lt;br /&gt;&lt;br /&gt;SQL Server sysobjects Table contains one row for each object created within a database. In other words, it has a row for every constraint, default, log, rule, stored procedure, and so on in the database. Therefore, this table can be used to retrieve information about the database. We can use xtype column in sysobjects table to get useful database information. This column specifies the type for the row entry in sysobjects. &lt;p&gt; For example, you can find all the user tables in a database by using this query: &lt;/p&gt;&lt;pre&gt;&lt;span style="font-size:180%;"&gt;&lt;code&gt; select * from sysobjects where xtype='U'&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;   Similarly, you can find all the stored procedures in a database by using this query: &lt;pre&gt;&lt;code&gt; select * from sysobjects where xtype='P'&lt;/code&gt;&lt;/pre&gt;   This is the list of all possible values for this column (xtype):  &lt;ul&gt;&lt;li&gt;C = CHECK constraint&lt;br /&gt;&lt;/li&gt;&lt;li&gt;D = Default or DEFAULT constraint&lt;br /&gt;&lt;/li&gt;&lt;li&gt;F = FOREIGN KEY constraint&lt;br /&gt;&lt;/li&gt;&lt;li&gt;L = Log&lt;br /&gt;&lt;/li&gt;&lt;li&gt;P = Stored procedure&lt;br /&gt;&lt;/li&gt;&lt;li&gt;PK = PRIMARY KEY constraint (type is K)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;RF = Replication filter stored procedure&lt;br /&gt;&lt;/li&gt;&lt;li&gt;S = System table&lt;br /&gt;&lt;/li&gt;&lt;li&gt;TR = Trigger&lt;br /&gt;&lt;/li&gt;&lt;li&gt;U = User table&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UQ = UNIQUE constraint (type is K)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;V = View&lt;br /&gt;&lt;/li&gt;&lt;li&gt;X = Extended stored procedure  &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-1950816189151938302?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/1950816189151938302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=1950816189151938302' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/1950816189151938302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/1950816189151938302'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/03/sysobjects-information.html' title='Sysobjects Information'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8036214485995065501</id><published>2009-02-09T19:10:00.000-08:00</published><updated>2009-03-07T16:32:07.802-08:00</updated><title type='text'>Stored procedure which were created in last 7days</title><content type='html'>Following script will provide name of all the stored procedure which were created in last 7 days, they may or may not be modified after that.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SELECT name&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;FROM sys.objects&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;WHERE type = 'P'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;AND DATEDIFF(D,modify_date, GETDATE()) &lt; 7&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8036214485995065501?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8036214485995065501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8036214485995065501' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8036214485995065501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8036214485995065501'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/02/stored-procedure-which-were-created-in.html' title='Stored procedure which were created in last 7days'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-1336597369971836399</id><published>2009-02-09T19:08:00.000-08:00</published><updated>2009-03-07T16:33:02.568-08:00</updated><title type='text'>To get the row count in a faster way</title><content type='html'>To get the row count in a faster way , the conventional way would be very slow.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SELECT rows FROM sysindexes &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;WHERE id = OBJECT_ID('TABLEA') AND indid &lt; 2&lt;br /&gt;&lt;br /&gt;TABLEA : Is the name of the table&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-1336597369971836399?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/1336597369971836399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=1336597369971836399' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/1336597369971836399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/1336597369971836399'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/02/to-get-row-count-in-faster-way.html' title='To get the row count in a faster way'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-8930499176224783552</id><published>2009-02-09T19:04:00.000-08:00</published><updated>2009-02-09T19:30:28.644-08:00</updated><title type='text'>Unmatching records between two tables</title><content type='html'>&lt;span style="font-weight: bold;"&gt;SELECT SID FROM TABLEA T1 WHERE NOT EXISTS (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SELECT * FROM TABLEB T2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;WHERE (T1.SID=T2.SID))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(or)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(select TABLEA.SID from TABLEA) EXCEPT &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(select TABLEB.SID from TABLEB)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-8930499176224783552?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/8930499176224783552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=8930499176224783552' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8930499176224783552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/8930499176224783552'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/02/unmatching-records-between-two-tables.html' title='Unmatching records between two tables'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-407331644712571142</id><published>2009-02-09T19:01:00.000-08:00</published><updated>2009-02-09T19:31:02.367-08:00</updated><title type='text'>Exporting the output into a text or csv file</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Syntax&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;C:\&gt;sqlcmd -S \\Server_pathname -i C:\script.sql  -o C:\test.txt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here Script.sql is a sql script in which the desired script is written and the related output is exported into test.txt file at the following location.&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-407331644712571142?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/407331644712571142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=407331644712571142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/407331644712571142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/407331644712571142'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/02/exporting-output-into-text-or-csv-file.html' title='Exporting the output into a text or csv file'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8567031383628107211.post-6024315360773844092</id><published>2009-02-09T18:57:00.000-08:00</published><updated>2009-02-09T19:35:21.587-08:00</updated><title type='text'>Taking a backup or creating a duplicate table</title><content type='html'>Taking a backup of a table&lt;br /&gt;&lt;br /&gt;Here it creates the table name TEST1 from TEST and copies the content accordingly&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SELECT SID,CLASS,DEPT,DATE,SALARY,NAME INTO TEST1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;FROM TEST&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here it copies the whole table by creating a table name along with the field names&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SELECT * FROM TEST1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SELECT * INTO TEST1 FROM TEST&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;form action="http://www.google.com/cse" id="cse-search-box"&gt;
  &lt;div&gt;
    &lt;input type="hidden" name="cx" value="partner-pub-3206956697067718:iytleq-3mvg" /&gt;
    &lt;input type="hidden" name="ie" value="ISO-8859-1" /&gt;
    &lt;input type="text" name="q" size="31" /&gt;
    &lt;input type="submit" name="sa" value="Search" /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en"&gt;&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8567031383628107211-6024315360773844092?l=sqlbasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sqlbasic.blogspot.com/feeds/6024315360773844092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8567031383628107211&amp;postID=6024315360773844092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/6024315360773844092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8567031383628107211/posts/default/6024315360773844092'/><link rel='alternate' type='text/html' href='http://sqlbasic.blogspot.com/2009/02/taking-backup-or-creating-duplicate.html' title='Taking a backup or creating a duplicate table'/><author><name>MSSQLSERVER</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></
