General discussion of SQL Topics; aimed for the novice-intermediate level Microsoft SQL Server User. Currently focuses on using SQL Server 2005.

Showing posts with label EXECUTE. Show all posts
Showing posts with label EXECUTE. Show all posts

Thursday, October 23, 2008

TSQL Code: Compare Tables of Databases on Separate Servers

NOTE: This script was originally developed to compare table row counts, but with the below mentioned modifications this could be helpful if you have a database that is shipped to another server and often times needs to be ETL into the other database and you are worried there may be records that aren't getting transferred properly (or at all).

The other day I came across a question on how to compare the tables in one database to the tables in another database, this was in concerns to a migration project. This person had a database that existed on an older server running SQL 2000 and they chose to migrate their database to a new server running SQL Server 2005. They had wanted to be able to somehow be able to visually display a comparison of the two databases to prove the conversion was successful, and also to display the comparisons of the tables. Results meeting above requirements are shown in Figure 1.

AW_Compare_All 
Figure 1 (results of running sp_CompareTables_All)

In response to this I had started to develop a TSQL script that created a stored procedure that would allow you to run it from the current database and specify the location of the original database. The script would then collect the tables and count the records within each table for both databases. It will display the table names on the outside (left and right) of the results, and the record counts will be next to each other on the inside (next to their table names); which will allow for a very simple and pleasing visual comparison. I wanted, and did, avoid using cursors or other techniques that will potentially bog down the system resources (such as the stored proc 'sp_MSForEachDB' and 'sp_MSForEachTable').

Now, this is a rough draft that I had thrown together and tested over a lunch period; so, there are some issues that can still be cleaned up on the script and it lacks the ability to detect if a table exists on one database, but not the other.

At the end of the script I'll also provide a quick comment that will allow you to change the results from displaying all tables and their row counts to display only the tables with mismatched row counts (which may be useful if you want to use this script as a method to troubleshoot databases that tend to not migrate all records).

The first problem faced is how to best access the server with the original database; while there are many options I chose to use the built-in stored procedure "sp_addlinkedserver". This procedure seems to be simple to implement and allows for seamless integration into TSQL code. Testing for this script was performed on the AdventureWorks database (developed for SQL 2005) on both test systems. The 'originating' database was on a SQL 2005 instance (although testing was briefly performed on SQL 2000 and SQL 2008 to validate compatibility). The 'originating' server is called TestServer35, the database is on an instance called Dev05; the database for both instances is called AdventureWorks2005. This information becomes important when using the sp_addlinkedserver command. I used the following TSQL code:

EXEC sp_addlinkedserver   
   
@server='TestServer35-5', 
   
@srvproduct='',
   
@catalog='AdventureWorks2005',
   
@provider='SQLNCLI', 
   
@datasrc='Server35\Dev05'
 

As you can see, the linked server is referenced as TestServer35-5. We will use this reference, in a four-part identifier (Server.Catalog.Schema.Table). The next obstacle is to obtain a listing of tables and their row counts. I used a script I had modified last year to perform this since this script will run both on SQL 2005 and SQL 2000 (you can view my script on SQLServerCentral.com's Script section at: http://www.sqlservercentral.com/scripts/Administration/61766/). I then take the results of this and store them into a temporary table; I also do this for the new database (on local server where this stored proc is running at).

Then comes the simple part of joining the two temp tables into a final temp table. I chose this route because I wanted to have the two database in separate temp tables in the event I want to work with that data, which I will be working with the data in my update to determine if a table is missing from one of the databases.

Here is the TSQL code I used (remember if you want to use this you will need to change the linked server information to the correct information; as well as to create this stored proc in the appropriate database):

--Change the database name to the appropriate databse
USE [AdventureWorks2005];
GO

CREATE PROCEDURE sp_CompareTables_all
 
AS
 
 
CREATE TABLE #tblNew
( tblName varchar(50), CountRows int )

INSERT INTO #tblNew
( tblName, CountRows)
SELECT o.name AS "Table Name", i.rowcnt AS "Row Count"
FROM sysobjects o, sysindexes i
WHERE i.id = o.id
AND indid IN(0,1)
AND xtype = 'u'
AND o.name <> 'sysdiagrams'
ORDER BY o.name

CREATE TABLE #tblOLD
( tblName varchar(50), CountRows int )

INSERT INTO #tblOLD
( tblName, CountRows)
SELECT lo.name AS "Table Name", li.rowcnt AS "Row Count"
--********
--Replace TestServer35-5 and AdventureWorks2005 below with your appropriate values
--********
FROM [TestServer35-5].[AdventureWorks2005].[dbo].[sysobjects] lo, 
   
[TestServer35-5].[AdventureWorks2005].[dbo].[sysindexes] li
WHERE li.id = lo.id
AND indid IN(0,1)
AND xtype = 'u'
AND lo.name <> 'sysdiagrams'
ORDER BY lo.name

CREATE TABLE #tblDiff
( OldTable varchar(50), OldRowCount int, NewRowCount int, NewTableName varchar(50))

INSERT INTO #tblDiff
( OldTable, OldRowCount, NewRowCount, NewTableName )
SELECT ol.tblName, ol.CountRows, nw.CountRows, nw.tblName
From    #tblNew nw
JOIN #tblOLD ol
ON (ol.tblName = nw.tblName AND ol.CountRows = nw.CountRows)
        
SELECT * FROM #tblDiff
        
DROP TABLE #tblNEW
DROP TABLE #tblOLD
DROP TABLE #tblDiff

 

You simply execute the code with the following TSQL:

EXECUTE sp_CompareTables_All
 

The results of this script are shown in Figure 1 (above).

Now, this is great if you want to have a list that you can go through yourself to verify each table matches in row counts. But, what if that database has 1000 or more tables? What if you are just, simply put, lazy? Why not utilize SQL Server to process this information for you?

Well, I sure enough did just that. With a very small modification to this script you can easily have it only display any tables that don't match up in record counts.

All you have to do is change the INSERT INTO #tblDiff block's "ON" statement to join if the CountRows are NOT equal. The following is the modified block of code; the remaining stored procedure remains the same:

ON (ol.tblName = nw.tblName AND ol.CountRows <> nw.CountRows)
 

I did also rename the stored procedure from "sp_CompareTables_All" to "sp_CompareTables_Diff", but this is optional for your own ability to clarify which stored proc is being used.

To get some results I had made a few modifications to the AdventureWorks2005 database. I had added a couple of rows to a table, and removed some rows from two tables. The results of the stored proc showing only the different tables are shown in Figure 2.

AW_Compare_Diff
Figure 2 (results of running sp_CompareTables_Diff)

As you can see the ability to change this script to show all tables or only different tables is very simple. Even setting up this script is simple, where the hardest part of the whole thing is adding a linked server (which is fairly simple also).

In a future post I'll revisit this script and include the ability to display tables that exist on one database, but not in the other. Be sure to check back for this update.

Until next time...Happy Coding!!

Wednesday, February 20, 2008

Getting Started – Transact-SQL (T-SQL)

Overview:

This blog is aimed to help you get started using T-SQL. T-SQL is a syntax used in SQL Server; it generally composes of the majority work that is performed in the SQL database to get the data, store the data and/or work with the data. There are various other aspects of SQL Server that are used to perform many tasks that will be covered in other blogs; you'll find that in fact many of the tools used to setup new databases, new users, and other operations/tasks within SQL Server are nothing more than a nice Graphical User Interface (GUI) based on T-SQL commands.

What is T-SQL?

T-SQL, as already mentioned, is the syntax you will use to directly interact with the data stored within your database. T-SQL is typically entered via a GUI tool or application. A typical Database Administrator (DBA) might use Microsoft's SQL Server Management Studio (SSMS) or Enterprise Manager (EM) to enter T-SQL statements. A typical Database Programmer (DBP) might use a programming language such as Visual Basic or C# to enter T-SQL statements.

A common T-SQL statement used, almost in every instance of obtaining data information, is the "SELECT" statement. This statement can be a simple one or very complex. A typical usage may be:

    SELECT * FROM table1

This example would select all data from all columns from a table called "table1". This would be the simplest of all possible examples; but you aren't limited to only this single use. You can create complex SELECT statements that can calculate multiple fields and return the results, could join multiple tables, you could even join tables (or columns) from other databases!

How Do I use T-SQL?

T-SQL is used by entering a line of text within the chosen editor and then executing the command(s) within the SQL Server environment. A DBA may use SSMS to directly enter the commands within the SQL Server environment, or he/she may create a series of commands stored within a file (this is commonly referred to as a 'script') that can later be executed, or he/she may create a stored procedure that holds these commands within the SQL Server environment that can be later called by utilizing the "EXECUTE" keyword.

The important thing to know isn't how to use T-SQL; it's how to find the information to learn how to do what you want with T-SQL. I could spend this whole blog, and many more, on just how to use the SELECT statement; I could spend a lifetime blogging on how to use every T-SQL command there is within SQL Server (and before I even could get through half those commands and new version of SQL Server would appear causing us to restart the learning process!). As the famous saying goes: "Give a person a fish and they eat for a day; teach the person to fish and they eat for the rest of their lives". SQL Server is no different. So, I'm going to concentrate on how to find the information you need.

Where do I find the information I need?

This is actually quite simple to answer…the internet! But, if you want really detailed information that provides you with ALL of the information on how to use ANY (and all) T-SQL commands there is only one place you can go. NO, not this blog…you'd go straight to the horse's mouth; MSDN website. In particular you go to: Transact-SQL Reference (this URL is listed in the "Additional References" section at the end of this blog). This is the pillar to the T-SQL commands; everything starts there! When you first go there you are welcomed with a small page telling you what Transact-SQL is and how it is used; but, that's not the great part yet. The great part is (at the time of this blog) that to the left is a pane (navigation listing) that will list ALL of the T-SQL commands. You can even access other SQL Server reference information from here!

You'll also find many other additional resources on the internet. Microsoft contains a section called "Community" this will provide links to their forums, newsgroups and other websites; I highly recommend reviewing this section and discovering what is contained within these links. Outside of Microsoft there are many, many, hundreds of thousands of websites that cover SQL Server, T-SQL and/or anything to do with databases.

My favorite sites can be found in the "Resources" section of the main page of my blog; this doesn't mean I endorse or agree with these sites…I find that I frequent these sites on an almost daily basis. This listing may change and you are welcome to check back periodically. I also welcome any other suggestions of websites that you may find you can't live without..Please leave a comment to this posting and I'll be sure to make it available to all of the readers.

What books, training or other materials do you suggest?

Well, that is very objectionable. There seems to be no one book that covers all topics; most books targeted at beginner/intermediate users will focus on most popular areas of SQL Server and a good book will make you aware of other areas that exist but are not covered by that book. In regards to T-SQL in particular, I'd recommend for the beginning user to get a book such as SAMS 'Teach yourself Microsoft SQL Server T-SQL in 10 minutes'; this covers the most commonly used T-SQL commands and leads you progressively with each lesson.

I, personally, enjoy the Microsoft Press series for detailed information if I know a particular subject I want to learn about. I also have found that SAMS has other titles that cover a large spectrum of topics and are usually worth looking into.

It all comes down to taste, objective and personal preference. I still, without any doubt, always recommend keeping Books Online handy and using the MSDN website; you'll find most of the answers right there already; the answers you don't find can usually be asked (and receive quick responses) in the forums within the MSDN website.

Conclusion:

There is no single source of reference or answer for SQL Server; you will find that Microsoft has gone to great lengths to provide you with the knowledge and means to gain the knowledge to use SQL Server. If you find that Microsoft doesn't offer what you need then there are many other sites readily available to provide you with that information. Learning is everything!

Additional References

Transact-SQL Reference: http://msdn2.microsoft.com/en-us/library/ms189826.aspx