Ramani Sandeep's Blog

DotNetting – Fast , Easy Way of Developing Applications

Archive for the ‘SQL Server’ Category

SET NOCOUNT

Posted by Ramani Sandeep on February 13, 2009

Stops the message that shows the count of the number of rows affected by a Transact-SQL statement or stored procedure from being returned as part of the result set.

syntax:

SET NOCOUNT { ON | OFF }

When SET NOCOUNT is ON, the count is not returned. When SET NOCOUNT is OFF, the count is returned.

The @@ROWCOUNT function is updated even when SET NOCOUNT is ON.

SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.

The setting specified by SET NOCOUNT is in effect at execute or run time and not at parse time.

The following example prevents the message about the number of rows affected from being displayed.

USE AdventureWorks;
GO
SET NOCOUNT OFF;
GO
– Display the count message.
SELECT TOP(5)LastName
FROM Person.Contact
WHERE LastName LIKE ‘A%’;
GO
– SET NOCOUNT to ON to no longer display the count message.
SET NOCOUNT ON;
GO
SELECT TOP(5) LastName
FROM Person.Contact
WHERE LastName LIKE ‘A%’;
GO
– Reset SET NOCOUNT to OFF
SET NOCOUNT OFF;
GO

Posted in SQL Server | Tagged: | Leave a Comment »

@@ROWCOUNT

Posted by Ramani Sandeep on February 13, 2009

Returns the number of rows affected by the last statement. If the number of rows is more than 2 billion, use ROWCOUNT_BIG.

Transact-SQL statements can set the value in @@ROWCOUNT in the following ways:

* Set @@ROWCOUNT to the number of rows affected or read. Rows may or may not be sent to the client.
* Preserve @@ROWCOUNT from the previous statement execution.
* Reset @@ROWCOUNT to 0 but do not return the value to the client.

Statements that make a simple assignment always set the @@ROWCOUNT value to 1. No rows are sent to the client. Examples of these statements are: SET @local_variable, RETURN, READTEXT, and select without query statements such as SELECT GETDATE() or SELECT ‘Generic Text’.

Statements that make an assignment in a query or use RETURN in a query set the @@ROWCOUNT value to the number of rows affected or read by the query, for example: SELECT @local_variable = c1 FROM t1.

Data manipulation language (DML) statements set the @@ROWCOUNT value to the number of rows affected by the query and return that value to the client. The DML statements may not send any rows to the client.

DECLARE CURSOR and FETCH set the @@ROWCOUNT value to 1.

EXECUTE statements preserve the previous @@ROWCOUNT.

Statements such as USE, SET <option>, DEALLOCATE CURSOR, CLOSE CURSOR, BEGIN TRANSACTION or COMMIT TRANSACTION reset the ROWCOUNT value to 0.

EXAMPLE :

The following example executes an UPDATE statement and uses @@ROWCOUNT to detect if any rows were changed.

USE AdventureWorks;
GO
UPDATE HumanResources.Employee
SET Title = N’Executive’
WHERE NationalIDNumber = 123456789
IF @@ROWCOUNT = 0
PRINT ‘Warning: No rows were updated’;
GO

Posted in SQL Server | Tagged: | Leave a Comment »

Recursive Queries in SQL Server 2005

Posted by Ramani Sandeep on January 26, 2009

One of the really killer features included in SQL Server 2005 was Common Table Expressions. One of the really nice uses for them is recursive queries. Imagine any kind of hierarchical set of date (org. chart, security which allows nested roles, parts/assemblies, etc.). You can use CTE’s to walk up or down these trees to build it’s result set. Let’s look at a simple example of this. I’m going to create a table named “ItemGroups” which is nothing more than a listing of items which have a PK, Title, Description, and foreign key to a parent it may be a child of.

CREATE TABLE [dbo].[ItemGroups](
[iid] [int] IDENTITY(1,1) NOT NULL,
[Title] [varchar](60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Description] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[fk_ItemGroups] [int] NULL,
CONSTRAINT [PK_ItemGroups] PRIMARY KEY CLUSTERED
(
[iid] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Then, I’m going to add some sample data to this table:

———————————————————————————————–
iid     Title                                       Description                     fk_ItemGroups
———————————————————————————————–
1       Root                                         This is the root                                            NULL
2       Child 1                                    This is a child of root                              1
3       Child 2                                  This is a child of root                               1
4       Grandchild 1                     This is a child of Child 1                        2
5       Grandchild 2                    This is a child of Child 2                       3
6       Great Grandchild 1      This is a child of Grandchild 1          4
———————————————————————————————-

If we draw this out as a “tree”, it would look something like this (note the modern looking ASCII art…)

  • Root
    • Child 1
      • Grandchild 1
        • Great Grandchild 1
    • Child 2
      • Grandchild 2

OK, great – let’s suppose we want to walk up or down this tree from a known starting point. How might we use a CTE to do that?
It might help to understand the basic format of a CTE:

WITH SomeTableName (List of resulting fields)
(
SELECT — Starting point or anchor of the query
UNION ALL
SELECT — Recursive portion of the query
)
SELECT — Final select from SomeTableName

We have the “WITH” portion which describes what our CTE cursor would look like (we can reference this in the recursive portion of the query and in the final SELECT). Then we have the first SELECT which selects the starting record(s) for the recursive portion of our query. It’s basically the starting point. The second SELECT pulls in matching records which are children or parents of the record in the anchor portion.

Let’s see what that would look like against our table, assuming we want to walk down the hierarchy – in this code, we’re going to be starting with the root node.

DECLARE @startNode int
SET @startNode = 1; -- Note the semicolon – it’s required for the commandimmediately before the CTE

WITH Items (iid, Title, Description, fk_ItemGroups) AS
(
	-- This is the ‘Anchor’ or starting point of the recursive query
		SELECT ig.iid,
			ig.Title,
			ig.Description,
			ig.fk_ItemGroups
		FROM ItemGroups ig
		WHERE ig.iid = @startNode
	UNION ALL -- This is the recursive portion of the query
		SELECT ig.iid,
			ig.Title,
			ig.Description,
			ig.fk_ItemGroups
		FROM ItemGroups ig
		INNER JOIN Items -- Note the reference to CTE table name
		ON ig.fk_ItemGroups = Items.iid
)
SELECT * FROM Items

If we run this, here’s our results (notice that the query automatically stops recursing when no more matches are found).

————————————————————————————————
iid     Title                                        Description                            fk_ItemGroups
————————————————————————————————
1       Root                                         This is the root                                           NULL
2       Child 1                                   This is a child of root                              1
3       Child 2                                  This is a child of root                              1
5       Grandchild 2                   This is a child of Child 2                        3
4       Grandchild 1                    This is a child of Child 1                         2
6       Great Grandchild 1      This is a child of Grandchild 1           4
———————————————————————————————–

If we change the starting node to 2 and rerun this, you’ll see we only get Child 1 and it’s children:

——————————————————————————————
2       Child 1                                  This is a child of root                                1
4       Grandchild 1                    This is a child of Child 1                          2
6       Great Grandchild 1      This is a child of Grandchild 1           4

—————————————————————————————–

And if we change it to start at Grandchild 1, we get:

—————————————————————————————
4       Grandchild 1                    This is a child of Child 1                       2
6       Great Grandchild 1      This is a child of Grandchild 1        4

—————————————————————————————

What if we’d like to walk “up” the hierarchy instead? That’s just as easy. In the recursive portion of the query, we need to change our join condition. The first query will return the record we want to start on (aliased as ‘Item’ in this example). To walk up the chain, our fk_ItemGroups will match our parents iid. So change the ON to: ” Items.fk_ItemGroups = ig.iid”.

Let’s rerun the last query:

——————————————————————————
4       Grandchild 1      This is a child of Child 1             2
2       Child 1                    This is a child of root                   1
1       Root                          This is the root                              NULL

——————————————————————————

It might be useful to know how many levels deep of recursion were required to retrieve a row. We can modify our query to include this info by adding a new column, “Level”. In our root query we set it to start at 0, and we increment it in the recursive portion of the query:

SET @startNode = 4; -- Note the semicolon – it’s required for the command immediately before the CTE

WITH Items (iid, Title, Description, fk_ItemGroups, [Level]) AS
(
	--This is the ‘Anchor’ or starting point of the recursive query
		SELECT ig.iid,
			ig.Title,
			ig.Description,
			ig.fk_ItemGroups,
			0 AS Level
		FROM ItemGroups ig
		WHERE ig.iid = @startNode
	UNION ALL --This is the recursive portion of the query
		SELECT ig.iid,
			ig.Title,
			ig.Description,
			ig.fk_ItemGroups,
			Items.Level + 1
		FROM ItemGroups ig
		INNER JOIN Items -- Note the reference to CTE table name
		ON Items.fk_ItemGroups = ig.iid
)
SELECT * FROM Items

———————————————————————————————–
iid     Title                          Description                     fk_ItemGroups      Level
———————————————————————————————–
4       Grandchild 1        This is a child of Child 1     2                                     0
2       Child 1                       This is a child of root          1                                       1
1       Root                            This is the root                        NULL                           2

——————————————————————————————–

I’ve mostly ignored the final SELECT * FROM Items, but in a “real” query you tend to use this portion of it to pull in all your detail from various supporting tables.In a few cases I’ve found that I’ve actually needed to walk up and down a hierarchy from a given starting point. I’ve ended up just creating two CTEs – one to walk up and one to walk down the hierarchy. I insert the results of each of them into a temp. variable, then pull the final results.< portion. anchor the in record of parents or children are which records matching pulls SELECT second The point. starting basically It?s query. our portion recursive for record(s) selects first have we Then SELECT). final and query this reference can (we like look would cursor CTE what describes ?WITH?>

DECLARE @curItems TABLE (iid int);

-- Walks up the hierarchy
WITH Items (iid]) AS
(
		--This is the ‘Anchor’ or starting point of the recursive query
		SELECT ig.iid
		FROM ItemGroups ig
		WHERE ig.iid = @startNode
	UNION ALL -- This is the recursive portion of the query
		SELECT ig.iid
		FROM ItemGroups ig
		INNER JOIN Items -- Note the reference to CTE table name
		ON Items.fk_ItemGroups = ig.iid
)

INSERT INTO @curItems (iid) (SELECT iid FROM Items);

-- Walks down the hierarchy
WITH Items (iid]) AS
(
		-- This is the ‘Anchor’ or starting point of the recursive query
		SELECT ig.iid
		FROM ItemGroups ig
		WHERE ig.iid = @startNode
	UNION ALL -- This is the recursive portion of the query
		SELECT ig.iid
		FROM ItemGroups ig
		INNER JOIN Items -- Note the reference to CTE table name
		ON ig.fk_ItemGroups = Items.iid
)

INSERT INTO @curItems (iid) (SELECT iid FROM Items)

-- Code which does final select here

DECLARE @curItems TABLE (iid int);

-- Walks up the hierarchy
WITH Items (iid]) AS
(
		-- This is the ‘Anchor’ or starting point of the recursive query
		SELECT ig.iid
		FROM ItemGroups ig
		WHERE ig.iid = @startNode
	UNION ALL -- This is the recursive portion of the query
		SELECT ig.iid
		FROM ItemGroups ig
		INNER JOIN Items -- Note the reference to CTE table name
		ON Items.fk_ItemGroups = ig.iid
)

INSERT INTO @curItems (iid) (SELECT iid FROM Items);

-- Walks down the hierarchy
WITH Items (iid]) AS
(
		-- This is the ‘Anchor’ or starting point of the recursive query
		SELECT ig.iid
		FROM ItemGroups ig
		WHERE ig.iid = @startNode
	UNION ALL -- This is the recursive portion of the query
		SELECT ig.iid
		FROM ItemGroups ig
		INNER JOIN Items -- Note the reference to CTE table name
		ON ig.fk_ItemGroups = Items.iid
)

INSERT INTO @curItems (iid) (SELECT iid FROM Items)

As you can see, it’s pretty simple to use CTE’s. The syntax looks a little weird at first but once you’ve written one or two queries it’s pretty straightforward.

Posted in SQL Server | Tagged: , , | 1 Comment »

Selecting Rows Randomly from a table

Posted by Ramani Sandeep on November 18, 2008

If you use Microsoft SQL Server 2000, you likely have run into the following problem: You want to select a random sampling of rows from a large table with lots of rows, but you are unsure of how to do so. Having a random sampling of rows can be useful when you want to make a smaller version of the table or if you want to troubleshoot a problem by seeing what kinds of rows are in the table.

To get a random sampling, you might be tempted to select the top n rows from the table. However, this sample is not random, and the first n rows are not necessarily representative of the whole table. Other solutions exist that involve adding columns to the tables; however, adding columns is not always possible or practical.

The standard way to grab random rows from a small table is to use a query such as the following:

SELECT TOP 10 Stud_ID , Stud_Name , Student_Marks_Total
FROM StudentDetails
ORDER BY NEWID()

The key here is the NEWID function, which generates a globally unique identifier (GUID) in memory for each row. By definition, the GUID is unique and fairly random; so, when you sort by that GUID with the ORDER BY clause, you get a random ordering of the rows in the table. Taking the top 10 percent (or whatever percentage you want) will give you a random sampling of the rows in the table.

Often, when questions about how to select random rows are asked in discussion groups, the NEWID query is proposed; it is simple and works very well for small tables. However, the NEWID query has a big drawback when you use it for large tables. The ORDER BY clause causes all of the rows in the table to be copied into the tempdb database, where they are sorted. This causes two problems:

–>The sorting operation usually has a high cost associated with it. Sorting can use a lot of disk I/O and can run for a long time.

–>In the worst-case scenario, tempdb can run out of space. In the best-case scenario, tempdb can take up a large amount of disk space that never will be reclaimed without a manual shrink command.

Posted in SQL Server | Tagged: , , | Leave a Comment »

Differences between COALESCE and ISNULL

Posted by Ramani Sandeep on November 14, 2008

I am trying to document the difference between some of the functions that are used for the same purpose and has some differences.

Lets see what are the relevant differences:

1. COALESCE is ANSI standard and ISNULL is T-SQL proprietary.

2. You can work with only one value at a time with ISNULL, but COALESCE can deal with multiple values. as in

SELECT ISNULL(NULL, ‘SomeValue’)
GO
SELECT COALESCE(NULL, NULL, NULL, ‘SomeValue’)
GO

3. With ISNULL, the Alternate value you specify is limited to the length of the first parameter. In case of COALESCE, you dont have such restrictions.
See the example below.

DECLARE @somestring CHAR(4)
SET @somestring = NULL

SELECT ISNULL(@somestring, ‘Roji Thomas’)
–Returns ‘Roji’

SELECT COALESCE(@somestring, ‘Roji Thomas’)
–Returns ‘Roji Thomas’

4. When using COALESCE All expressions must be of the same type or must be implicitly convertible to the same type. If you are not careful, this can give you incorrect results. See the examples below.

SELECT COALESCE(NULL, GetDate())
–Returns : 2004-07-26 13:47:15.937
–Correct

SELECT COALESCE(1, GetDate())
–Returns 1900-01-02 00:00:00.000
–Incorrect Value

SELECT COALESCE(1,’abcd’)
–Returns 1
SELECT COALESCE(‘abcd’,1)
–Returns Error
– Server: Msg 245, Level 16, State 1, Line 1
– Syntax error converting the varchar value ‘abcd’ to a column of data type int.

SELECT COALESCE(NULL,435,’abcd’, CURRENT_TIMESTAMP,’xyzzz’,435)
–Returns 1901-03-12 00:00:00.000
–Incorrect

SELECT COALESCE(NULL,GetDate(),9999999999)
–Returns : 2004-07-26 13:47:15.937
–Correct

SELECT COALESCE(NULL,9999999999, GetDate())
–Returs Error
– Server: Msg 8115, Level 16, State 2, Line 1
– Arithmetic overflow error converting expression to data type datetime.

5. Eventhough COALESCE is generally the preferred way, there are some performance consideration especially when you have a select statement as an arguument to COALESCE.

Posted in SQL Server | Tagged: , , , | 2 Comments »

How to retrieve the identity value when inserting a record into a Microsoft SQL Server table

Posted by Ramani Sandeep on October 20, 2008

A common requirement when inserting a record into a table that contains an identity column is to return the identity value of the newly inserted record. A common mistake is to use @@IDENTITY or IDENT_CURRENT, both of which could return an unexpected value under some circumstances. This document describes a technique to use SCOPE_IDENTITY which does not suffer the drawbacks of the other two methods.

Why @@IDENTITY and IDENT_CURRENT should not be used

Using @@IDENTITY after an insert will return the last-inserted identity value. However, this might be an unexpected value if, for example, the inserted record fires triggers to perform additional inserts. In this case, calling @@IDENTITY immediately after the statement will return the last identity value generated by the triggers.

Using IDENT_CURRENT after an insert will return the last-inserted identity value for a specified table. However, this might be an unexpected value if another insert on the table is performed between the time of the initial insert and the calling of IDENT_CURRENT.

How and why to use SCOPE_IDENTITY

Using SCOPE_IDENTITY avoids the drawbacks of using @@IDENTITY and IDENT_CURRENT.Note however that SCOPE_IDENTITY is only available with Microsoft SQL Server 2000 or later.The technique for using SCOPE_IDENTITY is to call it immediately after the INSERT statement within a stored procedure. The following example shows a stored procedure called InsertCases that uses this technique to return the identity value for the CaseID identity column of the inserted record. This example has two columns, in addition to the CaseID identity column, called CaseName and CaseDescription. Notice that the @CaseName and @CaseDescription are input parameters but the @CaseID parameter is an output parameter used to return the identity value on exit from the stored procedure.

CREATE PROCEDURE [dbo].[InsertCases]
    @CaseID int output,
    @CaseName nvarchar(255),
    @CaseDescription ntext 
AS
   SET NOCOUNT ON
  INSERT INTO [dbo].[Cases] ([CaseName],[CaseDescription])
          VALUES (@CaseName,@CaseDescription)

  SET @CaseID=SCOPE_IDENTITY()
  SET NOCOUNT OFF

The following example shows how to call the InsertCases stored procedure using the Microsoft .NET Framework. Notice that the @CaseID parameter is set as an output parameter by setting its Direction property to arameterDirection.Output which allows it to return the CaseID identity value after the stored procedure has been executed.

C#

 Command.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@CaseID”,System.Data.SqlDbType.Int));
 Command.ExecuteNonQuery();
 CaseID = System.Convert.ToInt32(Command.Parameters["@CaseID"].Value);

Conclusion

By using SCOPE_IDENTITY within a stored procedure, the identity value of the most recently inserted record can always be correctly obtained.

Posted in C# 2.0, SQL Server | Tagged: , , , , , | Leave a Comment »

Generate a unique number in Sql Server 2005

Posted by Ramani Sandeep on October 14, 2008

We often find ourselves in the need of generating unique numbers in our database applications.

Let us quickly take a tour of how to do that using Sql server 2005.

SQL Server contains the NEWID() function. This function creates a unique value of type uniqueidentifier. We can use this function in several ways to generate unique numbers to suit our requirements :

Generate GUID’s :

UniqueIndentifiers are also knows as GUID’s. To generate a GUID use :

SELECT NEWID() as GuidNo

generates FBF2D8E9-F8BE-4F0B-9D49-7CA7C2E3F22C on my machine

Generate only digits :

SELECT ABS(CAST(CAST(NEWID() AS VARBINARY(5)) AS Bigint)) as UniqueNo

generates 427357674589 on my machine

Generate fixed digit unique numbers :

At times, we may also need to generate fixed digit numbers. You can do that in the following manner :

SELECT REPLACE(STR(CAST(CAST(NEWID() AS binary(5)) AS bigint),13),0,0)

generates 470370453006 on my machine

Posted in SQL Server | Tagged: , , | 7 Comments »

SQL Server – Copy Table from 1 Database to another

Posted by Ramani Sandeep on October 3, 2008

—————————————————-
Method : 1
—————————————————-

USE PropertyIdea
GO
—-Create Table
CREATE TABLE Country (CountryID int, Country nvarchar(50),Code int)

—-INSERT INTO Country using SELECT
INSERT INTO Country (CountryID , Country ,Code)
SELECT CountryID , Country ,Code
FROM [Kunj.Corp].[dbo].[Country]

—-Verify that Data in Country
SELECT * FROM Country

—————————————————-
Method : 2
—————————————————-
USE PropertyIdea
GO

—-Create Table

CREATE TABLE Country (CountryID
int, Country nvarchar(50),Code int)

—INSERT INTO Country using SELECT

INSERT INTO Country (CountryID, Country ,Code)

SELECT CountryID , Country ,Code

FROM [Kunj.Corp].[dbo].[Country]

—-Verify that Data in Country

SELECT * FROM Country

Posted in SQL Server | Tagged: , | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.

Join 317 other followers