Tuesday, October 31, 2006

Copying Database Diagram from DB server to another ...

For some, working with Databases is fun and for others, it could possibly be a nightmare. Understanding the structure of a Database schema from the available documentation could spell doom for many developers.

A picture is worth a thousand words. This golden saying applies aptly to Databases! Yes, often, a pictorial representation of a Database conveys more meaning about the Database Schema than the SQL scripts generated or other documentation that may be available. One of the first thing developers wants to do when starting work on a new project is to understand the Database schema. Sometimes, understanding a complex database schema can be simplified largely by a relationship diagram.

The Database diagram tools in the SQL Server enable administrators and developers to create Database diagrams very easily. This article demonstrates an efficient way to move DB diagrams from one Database to another.

We are going to use two sample Databases for this purpose. They are named PlayDB and PlayDBMirror for sake of simplicity and clarity. Let us create some sample tables and one sample diagram called “sample1” in the Database PlayDB. The objective is to copy the diagrams from this database to PlayDBMirror. Let us see how this can be accomplished.

Note: It is not necessarily that you need to create a DB called PlayDB in your server. You can also work with Northwind or Pubs database. The bottom line is don’t use the production server to test these out.

Run through the steps from 1 to 8:

1. Create a new Database by right clicking on "Databases" in Enterprise Manager and name it as "PlayDBMirror".

2. Now right click on your source Database (for me it is "PlayDB")

3. Choose "All Task" >> "Export Data" and choose the source and destination DB.

4. In "Specify Table Copy or Query screen" choose the second option "Use a query to specify the data to transfer" and click next.

5. In the next screen type the following query "select * from dtproperties" (Note: this would try and push ALL records from source dtproperties to destination dtproperties)

6. In "Select Source Tables and Views" click on the "Results" under heading destination, and then manually change it to dtproperties.

7. In the next screen choose "Run Immediately" check box and click on Next.

8. That’s it click on "Finish" on the last screen.

Now, we have successfully copied all the database diagrams from PlayDB to PlayDBMirror. Let us suppose we have somehow modified the database diagrams and want to move them again. Running through the steps from 1 to 8 will accomplish the task and lo here is the catch. If you check the diagrams section in the destination database (PlayDBMirror), we see the diagram sample1 copied successfully.

The internals

What happens internally is that the diagrams are stored in a table called dtproperties.

Each diagram internally has 7 rows in “dtproperties” with unique “objectid”. They are listed below for the purpose of completion:

1. DtgSchemaOBJECT
2. DtgSchemaGUID
3. DtgSchemaNAME
4. DtgDSRefBYTES
5. DtgDSRefDATA
6. DtgSchemaBYTES
7. DtgSchemaDATA

Excuse me, did I say unique objected?! Now here is where you need to pay attention. If this Database is queried, you will find that there are 14 rows!! Which means there are two diagrams now! How strange? The records were appended to the table during the second copy operation and were not overwritten! Why? And guess what, all of them have the same object id. Which means, for one diagram, there are 14 rows in the table dtproperties. In other words, there are two unique object Ids.

Let us analyze and figure what would happen if two diagrams have the same ID.

1. Double click on any one of the diagrams
2. Make some changes to it, save and close it.
3. Open the other diagram the same changes would reflect there also. Similarly if you drop one diagram the other one would also get delete. Believe me!! Rarely it has thrown some errors also for me in this step. And I have been left with no other alternative than to delete both diagrams.

The solution using Query analyzer

To move all the existing diagrams, we do this:

Insert into dtproperties
(
objectid,
property,
value,
uvalue,
lvalue,
version
)
Select
objectid,
property,
value,
uvalue,
lvalue,
version
From
PlayDB..dtproperties
Where
value not in (select value from dtproperties)


This query when run from the Query analyzer of the target Database ensures that all the diagrams are copied to the target Database but ensures that if the target Database already has a diagram with the same name, it doesn’t get copied.

Let us try to copy selected diagrams from the source to the target Database.

First, to decide on the diagrams that you want to copy, run the query

Select objectid, property, value from playdb..dtproperties

In the output of this query look in the "property" column for "DtgSchemaNAME" value. The DtgSchemaNAME property would have the name of the diagram; use this in conjunction with the objectid column to locate the diagram you would like to transfer.

We should also check the dtproperties table of destination Database before transfer. Using the above query, check that the destination dtproperties does not already have the objectid, which you are going to transfer now. If it does, get the maximum id from the destination table and use it within your select statement. Use that max value in the below query to be 100% sure its unique within the dtproperties table in the destination Database. For the sake of discussion let us use an arbitrary number 100 as my objectid.

Insert into dtproperties --- this is the table in the destination db.
(
objectid,
property,
value,
uvalue,
lvalue,
version
)
Select
100, -- Object ID
property,
value,
uvalue,
lvalue,
version
From
PlayDB..dtproperties
Where
objectid = 1
--- Replace this number with the object ID of the diagram which you want to transfer

Conclusion

Backing up the source database and restoring it in the destination database can accomplish the same task. But the crux of the matter is copying specific diagrams from one Database to another. Happy programming!

Technorati tags: ,

Saturday, October 28, 2006

One another good ASP.NET FAQs

Check out syncfusion.com

It has 300+ ASP.NET related Frequently asked questions. It would be a good read.

Technorati tags:

Friday, October 27, 2006

Do you think I will make it?

Approximately 20-25 days back I came to know about Community-Credit site and I started participating in it actively. See the below screenshot to know where I stand.


FYI, Lorenzo Barbieri is maintaining his lead from day 1. For the past 10+ days I am maintaining the second position and just 4 days left to know who is the winner of this month. Do you think I can make it to the top?

Technorati tags:

Wednesday, October 25, 2006

Listing / Dropping ALL stored procedures from a database in SQL Server 2005

This was the question asked by a member here http://www.dotnetspider.com/qa/ViewQuestion.aspx?QuestionId=59232

Though I have answered there itself, thought I would document it here also for future reference.

I) List all Stored procedures in a database:

Select * from sys.procedures where [type] = 'P' and is_ms_shipped = 0 and [name] not like 'sp[_]%diagram%'

OR

Select * from sys.objects where type='p' and is_ms_shipped=0 and [name] not like 'sp[_]%diagram%'

Please note that I have added the 'NOT LIKE' part to get rid of stored procedures created during database installation.

II) Delete all [user created] Stored procedures in a database:

Select 'Drop Procedure ' + name from sys.procedures Where [type] = 'P' and is_ms_shipped = 0 and [name] not like 'sp[_]%diagram%'

This would list down all the user defined Stored procedure as 'Drop Procedure procedureName' in the result pane. Just copy-paste it into the query window and execute it once.

Technorati tags:

Sunday, October 22, 2006

Brief Theoretical Knowledge about Table Partitioning

1. Partitioning is fully depended on Filegroups.

2. Start table partitioning as early as possible. So that huge data movement can be avoided later.

3. A file would be grouped to one and only Filegroups. Actually Filegroups improves database maintenance, performance and Online restore.

4. For your information, default Filegroup is always “primary filegroup“. If at all you don’t believe me! Create a dummy table something like this,

Create Table Test
(
sno int
)
Go

Now in your SQL Mgmt Studio, right click on that table and check the properties yourself.

5. All “System Objects” have to belong to PRIMARY Filegroup.

6. It’s recommended, to have all “User Objects” created in another Filegroup.

7. In SQL Server 2000, any user object can’t belong to more than one Filegroup. But it’s possible now in SQL Server 2005. That is, a table data can be partitioned and stored into multiple Filegroups.

8. If you have two large tables, put them into different Filegroups. Filegroups are recommended being on two different “Physical” drives.

Physical drive (hard disk) – has a spindle which has “reads per second”, “writes per second” which in turn determines the performance. While joining these 2 tables, parallel retrieval happens based on their spindle speed (since it involves two different physical drives). So there would be a boost in performance.

9. Filegroups are database specific. That is, if you create a “Filegroup1” for Database1 it won’t be available for any other databases.

10. Tables and Indexes can reside on different Filegroups.

11. Partition can be created based on the “Partition key”. Typically it would be based on the
“Date” field.

12. People querying the table need not bother about fetching records from different partition. Because SQL Engine takes care of it internally.

13. You can create separate partition for storing historic data.

14. Maintenance plan needs to be created based on the Filegroup.

15. By the way, we can set Filegroup as Read-only also. Lookup tables or tables which don’t go to change at all needs to be placed in Read-only groups. So it’s enough if we backup this Filegroup once.

16. In SQL Server 2000, we need to “Restore” all Filegroups then only we can make the database online. In SQL Server 2005, once the Primary Filegroup is up we can bring the database online. So functionality wise grouping should be done in a Filegroup.

In the next post I would talk about the steps involved in creating a partition and the different types of operations in a partition.

Technorati tags: ,

Tuesday, October 17, 2006

Accessing a table in SQL Server 2005 (Schema related)

Recently in a discussion forum I came across this question "I have a small Doubt in SQL server. The database name is 'AdventureWorks' and the table name is 'Production.Culture'. What is the query to fetch records from that table."

The answer to this is :

Select cultureid, [name], modifiedDate from AdventureWorks.Production.Culture

There was another member of the forum who was saying that we need to only use the below query:

Select * from AdventureWorks.dbo.Production.Culture

Please note that he has mentioned two Schema names (dbo and Production) in a single query. This query wouldn't work and I thought I would explain the concept of "Schemas" in SQL Server 2005 to him.

In short,

a) Schema is similar to Namespaces in .NET
b) It helps in logical grouping of tables.
c) To view all existing schema in a database, for example within AdventureWorksDB ::

1. Open ur SQL Mgmt studio
2. Go to AdventureWorks DB and expand it
3. Expand the Tables

4. Now just observe what you see within that. There would be,

i) few tables which starts with "dbo.",
ii) few tables which starts with "Person."
iii) few tables which starts with "Production." etc.,

Those are all called as "Schema Names".

Other easier way to find this is to, navigate to the "Security" tab of the Database. There we will find a folder by name "Schema". Expand that to see all the Schema names related to that DB.

5. Now click on "New query" button and try this

--- This would work
Select * from person.address

6. Now try this

--- This wouldn't work
Select * from dbo.person.address

7. Just for your confirmation, navigate to someother database in ur query window. For example,
Use Master
Go

--- This would work
Select * from adventureworks.person.address

--- This would work
Select * from adventureworks.dbo.AWBuildVersion

--- This would FAIL
Select * from adventureworks.dbo.person.address

8) That said, by DEFAULT when we create any new table it would be assigned to "dbo." schema.

This you can verify by going to ur SQL Mgmt Studio again, navigate to any database of your choice and create a sample table. Now expand the "Tables" folder to see "dbo.YourTableName" (the table which you have created now).

So the bottomline is when accessing a table name in SQL Server 2005, it shld be done like this:

ServerName.DatabaseName.SchemaName.TableName


Please note that if we want we can create our own schema and then assign the tables to it. Also when a new user is being created we can assign the default schema to them. This merits a separate discussion by itself so would write on it sometime soon.

Technorati tags:

Monday, October 16, 2006

Find out the Second (2nd) Highest Salary ...

For past 15 days I am actively participating in the discussion forums of dotnetspider. Yesterday there was a question relating to SQL Server which seems to be asked in interviews very often. i.e., How to find out the 2nd highest salary of an employee?

Thought I would give out an sample for those who are yet to find an answer for this. For that purpose I have given a table structure with few sample records inserted to it.

-- Table Structure
Create table employee
(
[Name] varchar(20),
Sal int
)
Go

-- Populate Sample Records
Insert into employee values ('Vadivel', 80000)
Insert into employee values ('Vel', 70000)
Insert into employee values ('xxx', 40000)
Insert into employee values ('Sneha', 60000)

The Solution:

Select top 1 [Name], Sal from
(
Select Top 2 [Name], Sal from employee order by Sal Desc
) AS A1 Order by Sal


Technorati tags: , , ,

Saturday, October 14, 2006

Desi Search Engine ...

Guruji.com - India's local search engine! has been launched in Bangalore on 12th of this month. The site seems to be focused on Indian consumers. May be they wanna become Google of India!

I tried out few searches - the results and performance are really impressive. The search strings which i tried are as follows:

1. Pizza Adyar
2. Verizon Guindy

Quite a few of my search strings also failed. Its understandable as they are still in Beta! But I feel its definitely a good start.

Guys use it and share your experience ....

If you like to know more about the Investors, Management Team etc., check out this.

Extract from TechTree:

Gaurav Mishra, co-founder and coo, guruji.com explains, "90% of Internet search queries are local in nature, and guruji.com will deliver better search results than any other search engine in these instances. For example, if a user types a search "Pizza in Koramangala, Bangalore " or "Chinese restaurant Juhu, Mumbai" the user will be able to see local business listings as well as articles, reviews, blogs, or any other web references."

Extract from cyberabad.biz

Two Indian Institute of Technology (IIT) Delhi graduates have returned from the Silicon Valley to launch a home-grown search engine with loads of Indian content.

In a bid to offer an alternative search engine and wean away the growing community of Internet buffs from established search engines like Google and Yahoo! Anurag Dod and Gaurav Mishra have co-founded www.guruji.com with a $7-million (Rs.322 million) seed fund from Sequoia Capital India, a venture capital firm.

Technorati tags: , ,

Monday, October 09, 2006

Google I'm Feeling Lucky :)

From a fellow MVP (Harish Ranganathan) I came to know about this interesting fact.

Old News: If you search for "Failure" in Google and click on "I'm feeling lucky" button it would take you to President Bush's homepage :)

Latest News: Now, interestingly, if you search for the word "Search" in Google and click on "I'm feeling lucky" button, it goes to Windows Live Search Page.

Technorati tags: , ,

Saturday, October 07, 2006

Tip to prepare for interview -- Part II

This post is written having final year students in mind.

The first part of this series! is here. So if at all you haven't read it before, I suggest you have a look at it also.

Apart from your regular preparation for the final year exams and projects, it’s always better to do the following:

1. Spend time on group discussions
2. Work on Quantitative aptitude and reasoning questions again and again. Some of the famous authors in this topic are listed below for your easy reference.
a. George Summers
b. Shakuntala Devi
c. R.S. Agarwal
d. P.S. Agarwal
e. Barrons GRE

3. Spend time on websites to know more about Interviews. For example:
www.freshersworld.com

4. If you are informed by the company for an interview, collect data regarding the company (visit their website first without fail)

5. Prepare a write-up on your own vernacular. Try to translate it. Practice it in-front of your friends or your lectures or mirror and fine tune it.

6. Prepare a neat CV.

Interview

Telephonic:

1. Provide the contact number which is reachable. Be prepared before an hour. Keep the CV with you at the time of interview.

2. Attend the interview in a calm atmosphere. If you are not comfortable at particular juncture, please request them to call back after some specified time.

3. Start with a pleasant note. Say “Hi” with the name of the person after hearing the name or just say “Hi”.

4. During conversation, listen carefully and start answering accordingly. Understand the question properly, before answering. If you come across any confusion in the conversation, hold on and explain what you have understood from the question and then continue.

5. Your conversation should be free-flowing and confident.

6. Be specific in your conversation.

7. Before concluding feel free to ask your doubts, questions and end with a pleasant note.

8. Do not overdo :)

In Person

1. Be present at the interview venue before half an hour.
2. Present yourself with formals.
3. Have a copy of Your CV and other testimonials
4. Look confident and relaxed
5. Your conversation should be free-flowing and confident.
6. Be specific in your conversation.

Observation by the panel members

Broadly there are three categories:

1. Poor communication skills
2. Attitude issues. Like arrogant mannerism etc, Lethargic attitude.
3. Fake project / company details.

The first two things you need to work on and improve yourself. The third point is something which you need to avoid religiously.

Few standard questions which you can expect in any interviews are:

1. Tell me about yourself!
2. What are your strength and weakness?

3. Brief on the projects you last worked on OR Explain the project you created during your Final year.

Points normally observed are: What role the candidate has played, whether he/she is a team member, did he/she initiated it, is he/she well informed, is he/she able to quantify it.

4. Try to quantify you work.

Points to note:

1. Please be aware of when and tom whom to do your negotiations.

2. Avoid showing fake projects, companies in your CV. As most of the major companies are doing background verification of a candidate.

3. Don’t ever crib about your previous employee / manager / team member etc., This would give a bad impression about you.

After Joining

1. Be participative
2. Be proactive
3. Be a team player
4. Start documenting whatever you do.
5. Write simple and clear mail to your team leader and manager.
6. Understand the project you are in. If you don’t understand try to refer the documents related to the project.

I would be updating this post on a periodic basis. I welcome suggestions and points to be added here from all you guys!

Technorati tags: , ,

Friday, October 06, 2006

Finding the File Size of Attachment in Javascript

<html>
<head>
<title>Check the Size of a File -- Javascript</title>

<script language="JavaScript">
function CheckFileSize()
{
var objSize = new ActiveXObject("Scripting.FileSystemObject");
var strFileName = objSize.getFile(document.frmFileUpload.strFile.value);
var SizeOfFile = strFileName.size;
alert(SizeOfFile + " bytes");
}
</script>
</head>
<body>
<form name="frmFileUpload">
<input type="file" name="strFile">
<input type="button" name="btnSize" value="Show file size" onClick="CheckFileSize();">
</form>
</body>
</html>


The above code snippet will work only if ActiveX is supported @ the client end.

Monday, October 02, 2006

Paging in SQL Server 2000 and 2005?

Abstract

In this article I have discussed in detail about the easier way of paging records using SQL Server 2005. In the due course I have introduced the nuances of using TOP keyword and the cool enhancements added to it. Along with that I would show you how to use TOP command to do paging in SQL Server 2000, albeit at a performance loss, then show how the same result can be achieved with higher performance thanks to new features in SQL Server 2005.

Introduction

Databases products always attract me for many reasons. One simple reason is, .NET framework 1.0 was released and then in a short time its “version 1.1” has been released. If at all you are watching the market you would know by this time, few months back .NET Framework 2.0 has also been released. So what’s the point I am trying to make? The application layer or the front end layer changes very frequently and we need to be updating our self on a daily basis. That’s the pace of the technology either keep up or be left out :)

On the flip side, if we take SQL Server a version was released on 2000 then you had 5 years gap before another major version was released. This gives enough time to master a product and appreciate its advantages. Approximately 6 months back SQL Server 2005 was released (Previously it was code named as Yukon).

Paging is one of the very common features expected in any application. It can either be done at the “Application level” or at the “Database level”. In this article I am concentrating on “Database level Paging”.

Though paging can be done in SQL Server 2000 itself there are performance issues with it. Like, either we need to use Temporary Tables OR Dynamic queries in order to do paging in SQL Server 2000 which by itself is a drawback. I have shown the way I used to do paging in the past with fully functional stored procedure. Subsequently I have discussed about the way to avoid “Temporary tables and Dynamic queries” in the process of paging records in SQL Server 2005.

In short, I have shown the way to do paging using the following new features introduced in SQL Server 2005:

1. Enhancements to TOP keyword
2. Row_number() function
3. CTE – Common Table Expression

Enhancements to Top Keyword:

TOP keyword was very much available in the previous versions of SQL Server itself. If at all one needs to appreciate the enhancements they need to first understand the limitations of the TOP keyword in SQL Server 2000. So let me walk you all through it.

In T-SQL TOP keyword is used to limit the number of rows or list fixed number of rows from the top. For example,

// this would list top 5 records from the specified table.
Select Top 5 FieldName from TableName

What if I would know the Top “N” only during runtime? Is there a way to dynamically pass the number to the TOP keyword? The answer is Big NO.

The work around which people used to do is make use of “Set RowCount On” which accepts parameter / variable. The downside to it is, it affects every query in the current connection.

Example:
Set Rowcount @LimitRowsSelect fieldname from tablename
Set Rowcount 0


The last statement in the above example is used to return SQL Server to normal state. If that line is skipped all future code snippets would also return only @LimitRows records. Hope I have made the limitation clear to you. Now let’s start looking at the enhancement done to this keyword in SQL Server 2005.

1. Now “TOP” keyword accepts parameters
2. Now “TOP” keyword can be used in Update statements as well
3. Now a T-SQL query can be passed as a parameter to “TOP” keyword.

Database Design

For the rest of this article the queries which I write would be based on a user defined table called “Sales”. Let me give you the scripts for the same with some sample data to populate it. This would surely help you to test the code then and there for better understanding.

I refrained from writing my scripts around either Northwind or Pubs database because those databases, by default, don’t come along with SQL Server 2005. The work around is to download the scripts of those 2 database from Microsoft site but its size is 1.5 MB. Downloading it just for testing the scripts in this article would be asking for too much J that’s the reason I created a sample table and worked on it.

//table structure
Create table Sales
(
Sno int identity,
YearOfSales Int,
SalesQuarter Int,
Amount money
)
go

//test records to populate the sales table
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2004, 1, 100)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2004, 2, 200)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2004, 3, 300)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2004, 4, 400)
go

Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2005, 1, 500)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2005, 2, 600)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2005, 3, 700)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2005, 4, 800)
go

Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2006, 1, 900)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2006, 2, 1000)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2006, 3, 1100)
Insert into Sales (YearOfSales, SalesQuarter, Amount) Values (2006, 4, 1200)
go

Enhancements to TOP Keyword – Explained with code snippets

The below code snippet would work in both SQL Server 2000 and SQL Server 2005

/* TSQL stops processing when they have been affected by the specified no of rows */
Set RowCount 2

-- SalesQuarter of first two records would be set as 999
Begin Tran
Update Sales SET SalesQuarter = 999
If @@RowCount = 0
Begin
Print 'No Record found'
Set RowCount 0
End
Commit Tran

To list all the records again we need to set the RowCount as 0.

Set RowCount 0
Select * from Sales

The below code snippet would work only in SQL Server 2005.

As you could see Set Rowcount statement is not used at all. Instead we have made use of TOP keyword.

Begin Tran
Update TOP (2) Sales SET SalesQuarter = 999
If @@RowCount = 0
Begin
Print 'No Record found'
Set RowCount 0
End
Commit Tran

Passing parameters to the TOP keyword

One of the features which were missing in SQL Server 2000 was passing parameters to the TOP keyword. That is now possible in SQL Server 2005.

Declare @topValue Int
Set @topValue = 2
Select Top (@topValue) * from Sales

Even if you give decimal Values it takes only the integer part and ignores the decimal part. The below query would list the Top 3 records.

Declare @topValue Int
Set @topValue = 3.9
Select Top (@topValue) * from Sales


Listing Top n percentage of records from a table

Declare @topValue Int
Set @topValue = 25
Select TOP (@topValue) Percent * from Sales

Out of the entire stuff the coolest enhancement is we could now pass a query as a parameter to TOP keyword. The below code snippet helps us in finding out the top half of the existing records.
-- It would list 50% of the records
Select TOP (Select cast((Select Count(*)/2 from Sales ) as int)) * from Sales

Hope that you would have got the feel of what’s there in store as far as TOP keyword is concerned in SQL Server 2005.

In a nutshell, TOP keyword in SQL Server 2005 can be used for the following:
1. It can be used to specify numbers or percent of rows to be returned
2. It can be used along with Insert, Update and Delete statements
3. Now we can pass expressions to it.

Now, let me explain the way in which I used to do paging while working with SQL Server 2000.

Paging explained in SQL Server 2000

There are two ways; either we need to make use of Temporary tables or dynamic queries for doing paging in SQL Server 2000. In SQL Server 2000, the maximum length of dynamic SQL Statement is limited to the maximum size of an nvarchar field. That is, max can be 4000 characters. Since I want to keep the sample as simple as possible and as I am sure in this example we won't need more than 1000 characters I have declared @strQuery as nvarchar (1000).

Create Procedure dbo.testPaging_SalesTable
@intNumOfRecords int,
@intPageNum int
As

/*
Stored Procedure: dbo.testingPaging_SalesTable
Creation Date: 06/20/2006
Written by: Vadivel Mohanakrishnan

Purpose : Helps in paging records within Sales table by just passing two variables.

Testing :
Exec dbo.testPaging_SalesTable 5,1
Exec dbo.testPaging_SalesTable 5,2
*/

Declare @strQuery nvarchar(1000)
Declare @intTotal int
Set @intTotal = @intNumOfRecords * @intPageNum

Set @strQuery = 'Select TOP ' + Cast(@intNumOfRecords as Varchar(5)) + ' * From Sales'
Set @strQuery = @strQuery + ' Where Sno Not in (Select TOP ' + Cast(@intTotal as Varchar(5))
Set @strQuery = @strQuery + ' Sno From Sales Order By Sno ) '

--Lets execute the dynamically built query
Exec sp_executesql @strQuery

Go

If I execute the stored procedure as Exec dbo.testPaging_SalesTable 5, 0 it means give me 5 records for page 1. Similarly if pass parameters as 5, 1 then it means give me 5 records for page 2. Hope till this part it’s clear for you!

Normally dynamic queries are something which one would prefer to avoid for performance reasons. Discussion in this topic is totally out of context so let me move on to show you all the way to implemented paging in SQL Server 2005.

Paging explained in SQL Server 2005
In SQL Server 2005, a new function by name “Row_Number()” has been introduced. This function helps us in returning the running count of all the rows in the specified or current scope.
Method 1:

With the help of Row_Number() function we can get the running count of all the rows and by using the between clause we can filter the records as per our need.

With SQLPaging As
(
Select Row_number() Over (Order by Sno) as RunningNumber, YearOfSales, SalesQuarter, Amount
From Sales
)
Select * from SQLPaging
Where RunningNumber between 2 and 3


Here in this method I have introduced you to the new concept called “Common Table Expression” shortly called as CTE.

CTE is an expression that returns temporary named result set from a query. Find below a very basic explanation for the above code snippet.

1. In the WITH clause we need to defines the table(s) and column(s). In our case the name of the CTE is SQLPaging.
2. Within the WITH clause is where we need to write our query which would return the expected result set.
3. Outside of the WITH clause is where we write a SELECT statement that references the SQLPaging table.

If you look at the above syntax you can draw similarity with Views. The only difference is Views are permanent in the database as they are created as a database object; whereas CTE aren’t created as a database object.

Method 2:

This method is an extension of the above method. I would pass page size and page number as input and then with the help of Row_Number() function filter out data pertaining to that particular page.

Create Proc dbo.uspFetchPagedData
(
@pPageSize as int,
@pPageNum int
)
As

/*
Stored Procedure: dbo.testingPaging_AuthorsTable
Creation Date: 06/22/2006
Written by: Vadivel Mohanakrishnan

Purpose : Paging using Row_Number and CTE in SQL Server 2005.

Testing :
Exec dbo.uspFetchPagedData 5,1
Exec dbo.uspFetchPagedData 5,2

*/

With SQLPaging2
As
(
Select Top(@pPageSize * @pPageNum) Row_number() Over (Order by Sno) as RunningNumber,
YearOfSales, SalesQuarter, Amount
From Sales
)
Select * from SQLPaging2 where RunningNumber > ((@pPageNum - 1) * @pPageSize)


Now that the stored procedure is also completed you can go ahead and test it yourself. Moreover the logic in the above code is pretty straight forward and I haven’t done any rocket science here :)

Conclusion

Hope I have made the point across.Let me recap what I have discussed in this article. I have explained the way in which Paging was done in SQL Server 2000 and the way we could do the same in SQL Server 2005. In that due course I introduced you all to the enhancements made to TOP keyword and about the new CTE and Row_Number() function in SQL Server 2005.

Happy programming!

Technorati tags: , ,