For example, in your company, there are two teams to manage the front end and back end. Back end team should able to create obejcts and manage database. Front end team should have only access to read and write the records and not allow to create/alter sql objects. To achieve this, you can do either by create login with permissions or by means of server role. It would be easy for you to manage the login with server role with permission set.
Showing posts with label SQL Server. Show all posts
Showing posts with label SQL Server. Show all posts
Saturday, November 17, 2012
How to create user defined Server Role to manage permissions easily in SQL Server 2012
Until SQL 2008 R2, you don't have option to create user defined server role. In SQL Server 2012, you can create a server role with permissions. It would help easily to manage the login with limited permissions.
Labels:
SQL Server,
SQL Server 2012
Tuesday, December 06, 2011
Recovery Models in SQL Server
Here we are going to discuss about database recovery model in SQL Server.
Recovery Models:
1. Simple
2. Bulk Logged
3. Full
Simple Recovery Model:
a)All the operations are not logged in Log file.
b)Log file size won't grow much.
c)Suitable for LOCAL and STAGE Environment.
d)Can't recover the database to certain point in time state.
Bulk Logged Recovery Model:
a)Only minimal information logged in log file during BULK operation. So, its also called as "Minimal Logging"
b)Log File won't grow much during bulk operation.
c)Suitable during bulk operation, migration.
d)Can't recover the bulk operation data.
Full Recovery Model:
a)All the operation logged in log file.
b)Log file size grow rapidly depends upon transactions.
c)Suitable for PRODUCTION environment.
c)Can recover the database to certain point in time (if we followed proper backup plan).
Here is script to switch to different recovery model.
Recovery Models:
1. Simple
2. Bulk Logged
3. Full
Simple Recovery Model:
a)All the operations are not logged in Log file.
b)Log file size won't grow much.
c)Suitable for LOCAL and STAGE Environment.
d)Can't recover the database to certain point in time state.
Bulk Logged Recovery Model:
a)Only minimal information logged in log file during BULK operation. So, its also called as "Minimal Logging"
b)Log File won't grow much during bulk operation.
c)Suitable during bulk operation, migration.
d)Can't recover the bulk operation data.
Full Recovery Model:
a)All the operation logged in log file.
b)Log file size grow rapidly depends upon transactions.
c)Suitable for PRODUCTION environment.
c)Can recover the database to certain point in time (if we followed proper backup plan).
Here is script to switch to different recovery model.
ALTER DATABASE testdb SET RECOVERY SIMPLE
GO
ALTER DATABASE testdb SET RECOVERY BULK_LOGGED
GO
ALTER DATABASE testdb SET RECOVERY FULL
GO
Labels:
SQL Server,
SQL Server 2008,
SQL Server 2012
Thursday, December 01, 2011
Rebuilding and Reorganizing Indexes based on Fragmentation in SQL Server
Why we have to Rebuild and Reorganize the indexes?
As the time passes, data pages are scattered/fragmented and not in order due to insert, update and delete operation. So, its better the rebuild / reorganize the indexes to improve the query performance. Otherwise, query response would be slow because its would take more time to collect the data's which is scattered.
Rebuilding Indexes:
1. Its nothing but dropping and creating the indexes.
2. More CPU resources need.
3. Deadlock would happen while rebuilding the indexes.
Reorganizing Indexes:
1. Rearranging the leaf pages in correct order.
2. Less CPU resources need.
3. Deadlock possibility is very less.
When to use REORGANIZE and REBUILD?
Generally if fragmentation percentage for each index is from 5 - 30 percent, reorganize the index. if fragmentation percentage is more than 30 percent, its better to REBUILD the index.
SQL Script to REORGANIZE and REBUILD each index in each table:
As the time passes, data pages are scattered/fragmented and not in order due to insert, update and delete operation. So, its better the rebuild / reorganize the indexes to improve the query performance. Otherwise, query response would be slow because its would take more time to collect the data's which is scattered.
Rebuilding Indexes:
1. Its nothing but dropping and creating the indexes.
2. More CPU resources need.
3. Deadlock would happen while rebuilding the indexes.
Reorganizing Indexes:
1. Rearranging the leaf pages in correct order.
2. Less CPU resources need.
3. Deadlock possibility is very less.
When to use REORGANIZE and REBUILD?
Generally if fragmentation percentage for each index is from 5 - 30 percent, reorganize the index. if fragmentation percentage is more than 30 percent, its better to REBUILD the index.
SQL Script to REORGANIZE and REBUILD each index in each table:
DECLARE @ReOrgLowPercent INT,
@ReOrgHighPercent INT,
@TableName VARCHAR(200)
SET @ReOrgLowPercent = 5
SET @ReOrgHighPercent = 30
DECLARE @IndexTable TABLE ( AlterStatement VARCHAR(4000) )
DECLARE C CURSOR
FOR SELECT name
FROM sys.tables
OPEN C
FETCH NEXT FROM C INTO @TableName
WHILE ( @@FETCH_STATUS = 0 )
BEGIN
--PRINT @TableName
INSERT INTO @IndexTable ( AlterStatement )
SELECT CASE when avg_fragmentation_in_percent between @ReOrgLowPercent and @ReOrgHighPercent
then 'ALTER INDEX ' + i.name + ' ON ' + t.name
+ ' REORGANIZE;'
when avg_fragmentation_in_percent > @ReOrgHighPercent
then 'ALTER INDEX ' + i.name + ' ON ' + t.name
+ ' REBUILD WITH(ONLINE=ON);' --- enterpise version obly
END
FROM sys.dm_db_index_physical_stats(DB_ID(),
OBJECT_ID(@TableName),
NULL, NULL, NULL) AS a
JOIN sys.indexes AS i ON a.object_id = i.object_id
AND a.index_id = i.index_id
JOIN sys.tables AS t ON t.object_id = i.object_id
FETCH NEXT FROM C INTO @TableName
END
CLOSE C
DEALLOCATE C
SELECT AlterStatement
FROM @IndexTable
WHERE
AlterStatement IS NOT NULL
Labels:
SQL Server,
SQL Server 2008
Friday, November 25, 2011
SQL Server 2012 - Improved Version of EXECUTE keyword
In Previous version of SQL Server 2005/2008, if you execute the SELECT Stored Procedure using EXECUTE keyword, it will return all the records as it is. if you want to edit the column name and data type of result set, you have to modify the stored procedure respectively.
But in SQL Server 2012, improved version of EXECUTE keyword allows to modify the result set with changing the column name and data type without modifying the stored procedure.
To explore this features, execute the following script to create a table, insert the record and creating the stored procedure.
In SQL Server 2005/2008:
RESULT:

In SQL Server 2012:
Here i am changing the column "id" into "CustomerId" and also changing the data type of firstname from VARCHAR(50) to VARCHAR(4). Since i reduced the length of FirstName to 4, it shows truncated firstname value.
RESULT:
But in SQL Server 2012, improved version of EXECUTE keyword allows to modify the result set with changing the column name and data type without modifying the stored procedure.
To explore this features, execute the following script to create a table, insert the record and creating the stored procedure.
CREATE TABLE Customers
(
ID INT IDENTITY(1,1),
FirstName VARCHAR(50),
LastName VARCHAR(50),
DOB DATE
)
GO
INSERT INTO Customers (FirstName, LastName, DOB)
SELECT 'Ayyanar', 'Jayabalan', '08/12/1982'
UNION ALL
SELECT 'Greg', 'Damico', '08/12/1970'
GO
CREATE PROCEDURE Customers_SelectAll
AS
BEGIN
SELECT
ID,
FirstName,
Lastname,
DOB
FROM dbo.Customers
END
GO
In SQL Server 2005/2008:
-- SQL 2005/2008
EXECUTE Customers_SelectAll
RESULT:

In SQL Server 2012:
Here i am changing the column "id" into "CustomerId" and also changing the data type of firstname from VARCHAR(50) to VARCHAR(4). Since i reduced the length of FirstName to 4, it shows truncated firstname value.
-- SQL 2012
EXEC Customers_SelectAll
WITH RESULT SETS
(
(
CustomerID SMALLINT,
FirstName VARCHAR(4),
Lastname VARCHAR(20),
DateOfBirth DATE
)
);
RESULT:
Labels:
SQL Server,
SQL Server 2012
SQL Server 2012 - Throwing Exception using THROW in TRY CATCH BLOCK instead of using RAISERROR
In SQL Server 2005/2008, if you want to throw an error again in catch block of TRY CATCH statement, you have to use RAISERROR with ERROR_MESSAGE(), ERROR_SEVERITY().
In SQL Server 2005/2008:
SQL Server 2012:
Just, you can use THROW keyword to throw the complete error information.
if you execute the above statement, you will receive an error like below.
In SQL Server 2005/2008:
-- EXCEPTION HANDLING in SQL Server 2005/2008
BEGIN TRY
DECLARE @VALUE INT
SET @VALUE = 1 / 0
END TRY
BEGIN CATCH
DECLARE @Message nvarchar(4000), @Severity int
SELECT @Message = ERROR_MESSAGE(), @Severity = ERROR_SEVERITY()
RAISERROR ( @Message, @Severity, 1 )
END CATCH
SQL Server 2012:
Just, you can use THROW keyword to throw the complete error information.
-- EXCEPTION HANDLING using THROW in SQL Server 2012
BEGIN TRY
DECLARE @VALUE INT
SET @VALUE = 1/0
END TRY
BEGIN CATCH
THROW
END CATCH
if you execute the above statement, you will receive an error like below.
Msg 8134, Level 16, State 1, Line 5
Divide by zero error encountered.
Labels:
SQL Server,
SQL Server 2012
Custom Paging in SQL Server 2012 - Using OFFSET
In SQL Server 2005/2008, if you have want to implement the custom paging for ASP.Net GridView or any other controls, you have use either COMMON TABLE EXPRESSIONS with ROW_NUMBER() or just ROW_NUMBER() keyword.
CUSTOM PAGING IN SQL SERVER 2005/2008:
CUSTOM PAGING IN SQL SERVER 2012 using OFFSET:
In SQL Server 2012, by using the OFFSET feature, we can implement the custom paging easily without having too many SQL statements.
Just you have to specify starting row id and page size like below.
Here is the complete T-SQL statement for custom paging.
CUSTOM PAGING IN SQL SERVER 2005/2008:
-- CUSTOM PAGING IN SQL SERVER 2005
USE AdventureWorks
DECLARE @PageIndex SMALLINT, @PageSize SMALLINT, @StartRowId INT, @EndRowId INT
SET @PageIndex = 1
SET @PageSize = 10
SET @StartRowId = ( (@PageIndex - 1) * @PageSize) + 1
SET @EndRowId = (@StartRowId + @PageSize) - 1
SELECT *
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY EmployeeId) AS RowId, *
FROM HumanResources.Employee) AS TT
WHERE RowId >= @StartRowId and RowId <= @EndRowId
CUSTOM PAGING IN SQL SERVER 2012 using OFFSET:
In SQL Server 2012, by using the OFFSET feature, we can implement the custom paging easily without having too many SQL statements.
Just you have to specify starting row id and page size like below.
OFFSET <Offset> ROWS
FETCH NEXT <PageSize> ROWS ONLY;
Here is the complete T-SQL statement for custom paging.
-- CUSTOM PAGING IN SQL SERVER 2012 RC0
DECLARE @PageIndex SMALLINT, @PageSize SMALLINT, @Offset INT
SET @PageIndex = 1
SET @PageSize = 10
SET @Offset = ( (@PageIndex - 1) * @PageSize)
SELECT *
FROM HumanResources.Employee
ORDER BY EmployeeId
OFFSET @Offset ROWS
FETCH NEXT @PageSize ROWS ONLY;
Labels:
SQL Server,
SQL Server 2012
Tuesday, November 22, 2011
SQL Server 2012 Features - Sequence Number
Today,i have installed to explore the features of SQL Server 2012. First feature which i am going to discuss is "Sequence Number". You can generate sequence number like identity column. In Previous release, if you want to generate a sequence id before inserting into the table, you have to create a seperate physical table with identity column. Before inserting record into table, we have to insert a row in custom sequence table and get the latest value.
But in SQL Server 2012, you no need to insert record in any physical custom table to retrieve the number in sequence. Just you have to create sequence object which binds to schema.
Here are the steps to create Sequence object using SQL Server Management Studio.
1. Create a New Sequence:

2. Specify the NAME, MIN, MAX, CYCLE and OTHER PROPERTIES:

3. Once you entered the values for sequence object. You have to use following query to get NEXT sequence number using NEXT VALUE FOR keyword.
RESULT:
If you execute above query, you will get the value as 1. Next time, if you executing same query, you will get the value as 2. Same way, you would get the number in sequential for every execution.
4. With CYCLE OPTION:
if you execute the above query, you would get values like below.
if sequence value reaches maximum value, it will start again with start value if you enabled the CYCLE option. Otherwise, it will throw an error like below;
But in SQL Server 2012, you no need to insert record in any physical custom table to retrieve the number in sequence. Just you have to create sequence object which binds to schema.
Here are the steps to create Sequence object using SQL Server Management Studio.
1. Create a New Sequence:

2. Specify the NAME, MIN, MAX, CYCLE and OTHER PROPERTIES:

3. Once you entered the values for sequence object. You have to use following query to get NEXT sequence number using NEXT VALUE FOR keyword.
select NEXT VALUE FOR dbo.GlobalSequence;
RESULT:
1
If you execute above query, you will get the value as 1. Next time, if you executing same query, you will get the value as 2. Same way, you would get the number in sequential for every execution.
4. With CYCLE OPTION:
select NEXT VALUE FOR dbo.GlobalSequence;
select NEXT VALUE FOR dbo.GlobalSequence;
select NEXT VALUE FOR dbo.GlobalSequence;
select NEXT VALUE FOR dbo.GlobalSequence;
select NEXT VALUE FOR dbo.GlobalSequence;
select NEXT VALUE FOR dbo.GlobalSequence;
if you execute the above query, you would get values like below.
1
2
3
4
5
1
if sequence value reaches maximum value, it will start again with start value if you enabled the CYCLE option. Otherwise, it will throw an error like below;
The sequence object 'GlobalSequence' has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.
Labels:
SQL Server,
SQL Server 2012
Tuesday, October 25, 2011
SQL SERVER – SHRINK Log File using SHRINKFILE
if you want to shrink the log file, you would use SHRINKFILE command like.
DBCC SHRINKFILE(TestDBLog, 1)
GO
But in some cases (like production database), if you shrink log file by using above command, you won't get expected result. So, if you want to shrink log file to minimum size, take backup (*.bak) of entire database with SIMPLE recovery mode and then run the shrink file command.
Here is the code to backup the database and shrink the log file
BACKUP DATABASE [TestDb] TO DISK = N'C:\TestDb.bak'
GO
DBCC SHRINKFILE(TestDBLog, 1)
GO
DBCC SHRINKFILE(TestDBLog, 1)
GO
But in some cases (like production database), if you shrink log file by using above command, you won't get expected result. So, if you want to shrink log file to minimum size, take backup (*.bak) of entire database with SIMPLE recovery mode and then run the shrink file command.
Here is the code to backup the database and shrink the log file
BACKUP DATABASE [TestDb] TO DISK = N'C:\TestDb.bak'
GO
DBCC SHRINKFILE(TestDBLog, 1)
GO
Labels:
SQL Server,
SQL Server 2008,
Tips and Tricks
Thursday, December 27, 2007
Caching Sql Parameters in C#.Net
Here I am going to discuss about how to cache the sql parameters.
Suppose if you want to add records to the table, either you use Direct-SQL and Stored Procedure. Stored Procedure is compiled one so it’s faster than Direct-SQL.
If you are using stored procedure, you call the stored procedure from the client side either by EXEC Or Parameterized call.
Parameterized call reuse the existing execution plan instead of creating the new execution plan every time when you call using EXEC.
So, Parameterized call is more efficient than EXEC.
If you are using Parameterized call, you have to create the array of Sql Parameters to pass the parameter value. You have to create the array of parameters every time when you call the stored procedure.
If you are calling 100 times, 100 times you have to create the array of parameters.
Cache:
Instead of creating the parameters every time, you can the cache the array of sql parameters in the first call. In next call, you can get the Clone of Sql Parameters from Cache. And then assign the values to the clone sql parameter.
Microsoft released the Enterprise Library having the parameter caching mechanism.
Here I am going to discuss the parameter caching is similar to that in a simple way.
Parameter Cache Code:
public class ParameterCache
{
private static Hashtable paramCache = Hashtable.Synchronized(new Hashtable());
// Create and return a copy of the IDataParameter array.
private static IDataParameter[] CloneParameters(IDataParameter[] originalParameters)
{
IDataParameter[] clonedParameters = new IDataParameter[originalParameters.Length];
for (int i = 0, j = originalParameters.Length; i < j; i++)
{
clonedParameters[i] = (IDataParameter)((ICloneable)originalParameters[i]).Clone();
}
return clonedParameters;
}
// Empties all items from the cache
public static void Clear()
{
paramCache.Clear();
}
// Add a parameter array to the cache for the command.
public static void AddParameterSetToCache(string connectionString, string storedProcedure, IDataParameter[] parameters)
{
string key = CreateHashKey(connectionString, storedProcedure);
paramCache[key] = parameters;
}
// Gets a parameter array from the cache for the command. Returns null if no parameters are found.
public static IDataParameter[] GetCachedParameterSet(string connectionString, string storedProcedure)
{
string key = CreateHashKey(connectionString, storedProcedure);
IDataParameter[] cachedParameters = (IDataParameter[])(paramCache[key]);
return CloneParameters(cachedParameters);
}
// Gets if a given stored procedure on a specific connection string has a cached parameter set
public static bool IsParameterSetCached(string connectionString, string storedProcedure)
{
string hashKey = CreateHashKey(connectionString, storedProcedure);
return paramCache[hashKey] != null;
}
// create the hash key based on connectionstring and stored procedure name
private static string CreateHashKey(string connectionString, string storedProcedure)
{
return connectionString + ":" + storedProcedure;
}
}
The above shared class is for caching and accessing the cached parameters.
HashTable – Used to store the array of parameters based on hash key. It is used as a cache.
CreateHashKey – Caching the Sql parameters based on hash key formed from connectionstring and stored procedure name.
AddParameterSetToCache – Cache the parameters in HashTable based on connectionstring and stored procedure name.
CloneParameters – Get the clone of cached parameters.
GetCachedParameterSet – Get the parameters from the HashTable(Cache) based on HashKey.
IsParameterSetCached – Used to check whether parameters already cached based on hashkey.
Clear – Clear the HashTable(Cache)
Customer Class:
public class Customer
{
#region C# 3.0 Automatic Properties
public long CustomerID
{
get;
set;
}
public string Name
{
get;
set;
}
#endregion
}
How to use ParameterCache shared class:
//Add the Customer Information to Customer Table
public void AddCustomer(Customer cust, string connectionString)
{
SqlConnection conn = null;
SqlCommand cmd = null;
SqlParameter[] param = null;
string spName = "AddCustomer";
try
{
conn = new SqlConnection(connectionString);
cmd = new SqlCommand(spName, conn);
cmd.CommandType = CommandType.StoredProcedure;
param = GetParameters(cust, connectionString, spName);
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (conn != null && conn.State == ConnectionState.Open)
conn.Close();
if (cmd != null)
cmd.Dispose();
param = null;
}
}
The above method is to add the records to the customer table. For that you have to prepare the parameters for stored procedure. GetParameters() method used to prepare the parameters.
// Prepare the Sql Parameters for Adding Customer
// Get the Clone parameters if already cached based on connectionstring and store procedure name
// Otherwise create the new Sql parameter array and then add to cache for next time use.
private SqlParameter[] GetParameters(Customer cust, string connectionString, string storeProcedure)
{
SqlParameter[] param = null;
if (ParameterCache.IsParameterSetCached(connectionString, storeProcedure))
{
param = (SqlParameter[])ParameterCache.GetCachedParameterSet(connectionString, storeProcedure);
param[0].Value = cust.CustomerID;
param[1].Value = cust.Name;
}
else
{
param = new SqlParameter[2];
param[0] = new SqlParameter("@CustomerID", SqlDbType.BigInt, 8);
param[0].Value = cust.CustomerID;
param[1] = new SqlParameter("@Name", SqlDbType.VarChar, 50);
param[1].Value = cust.Name;
ParameterCache.AddParameterSetToCache(connectionString, storeProcedure, param);
}
return param;
}
The above method is for returning array of sql parameters. First it checks the cache, if already exists then get the parameters from the cache. And then assign the values of clone sql parameters.
If not exists, create the new array of sql parameters and add prepared parameters into cache for next time use.
Only first time call, it takes some time to cache the parameters. Next call onwards prepare the sql parameters faster.
Conclusion:
You can get better performance on caching the sql parameters if you are calling the stored procedure frequently.
Suppose if you want to add records to the table, either you use Direct-SQL and Stored Procedure. Stored Procedure is compiled one so it’s faster than Direct-SQL.
If you are using stored procedure, you call the stored procedure from the client side either by EXEC Or Parameterized call.
Parameterized call reuse the existing execution plan instead of creating the new execution plan every time when you call using EXEC.
So, Parameterized call is more efficient than EXEC.
If you are using Parameterized call, you have to create the array of Sql Parameters to pass the parameter value. You have to create the array of parameters every time when you call the stored procedure.
If you are calling 100 times, 100 times you have to create the array of parameters.
Cache:
Instead of creating the parameters every time, you can the cache the array of sql parameters in the first call. In next call, you can get the Clone of Sql Parameters from Cache. And then assign the values to the clone sql parameter.
Microsoft released the Enterprise Library having the parameter caching mechanism.
Here I am going to discuss the parameter caching is similar to that in a simple way.
Parameter Cache Code:
public class ParameterCache
{
private static Hashtable paramCache = Hashtable.Synchronized(new Hashtable());
// Create and return a copy of the IDataParameter array.
private static IDataParameter[] CloneParameters(IDataParameter[] originalParameters)
{
IDataParameter[] clonedParameters = new IDataParameter[originalParameters.Length];
for (int i = 0, j = originalParameters.Length; i < j; i++)
{
clonedParameters[i] = (IDataParameter)((ICloneable)originalParameters[i]).Clone();
}
return clonedParameters;
}
// Empties all items from the cache
public static void Clear()
{
paramCache.Clear();
}
// Add a parameter array to the cache for the command.
public static void AddParameterSetToCache(string connectionString, string storedProcedure, IDataParameter[] parameters)
{
string key = CreateHashKey(connectionString, storedProcedure);
paramCache[key] = parameters;
}
// Gets a parameter array from the cache for the command. Returns null if no parameters are found.
public static IDataParameter[] GetCachedParameterSet(string connectionString, string storedProcedure)
{
string key = CreateHashKey(connectionString, storedProcedure);
IDataParameter[] cachedParameters = (IDataParameter[])(paramCache[key]);
return CloneParameters(cachedParameters);
}
// Gets if a given stored procedure on a specific connection string has a cached parameter set
public static bool IsParameterSetCached(string connectionString, string storedProcedure)
{
string hashKey = CreateHashKey(connectionString, storedProcedure);
return paramCache[hashKey] != null;
}
// create the hash key based on connectionstring and stored procedure name
private static string CreateHashKey(string connectionString, string storedProcedure)
{
return connectionString + ":" + storedProcedure;
}
}
The above shared class is for caching and accessing the cached parameters.
HashTable – Used to store the array of parameters based on hash key. It is used as a cache.
CreateHashKey – Caching the Sql parameters based on hash key formed from connectionstring and stored procedure name.
AddParameterSetToCache – Cache the parameters in HashTable based on connectionstring and stored procedure name.
CloneParameters – Get the clone of cached parameters.
GetCachedParameterSet – Get the parameters from the HashTable(Cache) based on HashKey.
IsParameterSetCached – Used to check whether parameters already cached based on hashkey.
Clear – Clear the HashTable(Cache)
Customer Class:
public class Customer
{
#region C# 3.0 Automatic Properties
public long CustomerID
{
get;
set;
}
public string Name
{
get;
set;
}
#endregion
}
How to use ParameterCache shared class:
//Add the Customer Information to Customer Table
public void AddCustomer(Customer cust, string connectionString)
{
SqlConnection conn = null;
SqlCommand cmd = null;
SqlParameter[] param = null;
string spName = "AddCustomer";
try
{
conn = new SqlConnection(connectionString);
cmd = new SqlCommand(spName, conn);
cmd.CommandType = CommandType.StoredProcedure;
param = GetParameters(cust, connectionString, spName);
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (conn != null && conn.State == ConnectionState.Open)
conn.Close();
if (cmd != null)
cmd.Dispose();
param = null;
}
}
The above method is to add the records to the customer table. For that you have to prepare the parameters for stored procedure. GetParameters() method used to prepare the parameters.
// Prepare the Sql Parameters for Adding Customer
// Get the Clone parameters if already cached based on connectionstring and store procedure name
// Otherwise create the new Sql parameter array and then add to cache for next time use.
private SqlParameter[] GetParameters(Customer cust, string connectionString, string storeProcedure)
{
SqlParameter[] param = null;
if (ParameterCache.IsParameterSetCached(connectionString, storeProcedure))
{
param = (SqlParameter[])ParameterCache.GetCachedParameterSet(connectionString, storeProcedure);
param[0].Value = cust.CustomerID;
param[1].Value = cust.Name;
}
else
{
param = new SqlParameter[2];
param[0] = new SqlParameter("@CustomerID", SqlDbType.BigInt, 8);
param[0].Value = cust.CustomerID;
param[1] = new SqlParameter("@Name", SqlDbType.VarChar, 50);
param[1].Value = cust.Name;
ParameterCache.AddParameterSetToCache(connectionString, storeProcedure, param);
}
return param;
}
The above method is for returning array of sql parameters. First it checks the cache, if already exists then get the parameters from the cache. And then assign the values of clone sql parameters.
If not exists, create the new array of sql parameters and add prepared parameters into cache for next time use.
Only first time call, it takes some time to cache the parameters. Next call onwards prepare the sql parameters faster.
Conclusion:
You can get better performance on caching the sql parameters if you are calling the stored procedure frequently.
Labels:
C# 3.0,
C#.Net,
Dotnet,
Performance,
SQL Server
Friday, November 23, 2007
Performance difference between EXEC and sp_executesql
I presumed that you already know about the execution plan. Sometimes we may come to situation to use Dynamic SQL instead of direct T-SQL.
If we are using Direct T-SQL (not dynamic) in stored procedure, SQL Server reused execution plan from the cache. i.e. SQL Server will not compile the Stored Procedure again.
If we are using dynamic sql in stored procedure, SQL Server may not use the execution plan. It will recreate the execution plan every time with different string of SQL.
So, we have to think about the performance while using dynamic sql.
To execute the dynamic SQL in stored procedure, we have to use the following way.
1. EXEC (Non- parameterized)
2. sp_executesql (Parameterized)
There will be performance difference between above two.
Execution plan will not be created until you execute the dynamic sql. If you execute the dynamic sql using EXEC, execution plan will be created for every execution even values only changing. If you use sp_executesql, SQL Server Optimizer will try to use same execution plan. Because dynamic sql string will be the same, values only going to change. So it will be treated as Stored Procedure having input parameters.
Use the following query to test,
CREATE TABLE [dbo].[Item]
(
ID INT
)
GO
INSERT INTO [dbo].[Item](ID) VALUES (1)
INSERT INTO [dbo].[Item](ID) VALUES (2)
GO
DBCC FREEPROCCACHE
DECLARE @ItemID INT
DECLARE @Query NVARCHAR(200)
SET @Query = 'SELECT * FROM [dbo].[Item] WHERE ID = '
SET @ItemID = 1
EXEC( @Query + @ItemID)
SET @ItemID = 2
EXEC( @Query + @ItemID)
SET @Query = 'SELECT * FROM [dbo].[Item] WHERE ID = @ID'
SET @ItemID = 1
EXEC sp_executesql @Query, N'@ID INT', @ID = @ItemID
SET @ItemID = 2
EXEC sp_executesql @Query, N'@ID INT', @ID = @ItemID
To view the execution plan, use the following query.
SELECT usecounts, sql FROM sys.syscacheobjects
Results:
UseCounts SQL
1 SELECT * FROM [dbo].[Item] WHERE ID = 1
2 (@ID INT)SELECT * FROM [dbo].[Item] WHERE ID = @ID
1 SELECT usecounts, sql FROM sys.syscacheobjects
1 SELECT * FROM [dbo].[Item] WHERE ID = 2
From the results, executed the dynamic sql using sp_executesql uses same execution plan. EXEC create the execution plan every time.
Conclusion:
Always try to use sp_executesql to execute the dynamic sql to improve the performance.
If we are using Direct T-SQL (not dynamic) in stored procedure, SQL Server reused execution plan from the cache. i.e. SQL Server will not compile the Stored Procedure again.
If we are using dynamic sql in stored procedure, SQL Server may not use the execution plan. It will recreate the execution plan every time with different string of SQL.
So, we have to think about the performance while using dynamic sql.
To execute the dynamic SQL in stored procedure, we have to use the following way.
1. EXEC (Non- parameterized)
2. sp_executesql (Parameterized)
There will be performance difference between above two.
Execution plan will not be created until you execute the dynamic sql. If you execute the dynamic sql using EXEC, execution plan will be created for every execution even values only changing. If you use sp_executesql, SQL Server Optimizer will try to use same execution plan. Because dynamic sql string will be the same, values only going to change. So it will be treated as Stored Procedure having input parameters.
Use the following query to test,
CREATE TABLE [dbo].[Item]
(
ID INT
)
GO
INSERT INTO [dbo].[Item](ID) VALUES (1)
INSERT INTO [dbo].[Item](ID) VALUES (2)
GO
DBCC FREEPROCCACHE
DECLARE @ItemID INT
DECLARE @Query NVARCHAR(200)
SET @Query = 'SELECT * FROM [dbo].[Item] WHERE ID = '
SET @ItemID = 1
EXEC( @Query + @ItemID)
SET @ItemID = 2
EXEC( @Query + @ItemID)
SET @Query = 'SELECT * FROM [dbo].[Item] WHERE ID = @ID'
SET @ItemID = 1
EXEC sp_executesql @Query, N'@ID INT', @ID = @ItemID
SET @ItemID = 2
EXEC sp_executesql @Query, N'@ID INT', @ID = @ItemID
To view the execution plan, use the following query.
SELECT usecounts, sql FROM sys.syscacheobjects
Results:
UseCounts SQL
1 SELECT * FROM [dbo].[Item] WHERE ID = 1
2 (@ID INT)SELECT * FROM [dbo].[Item] WHERE ID = @ID
1 SELECT usecounts, sql FROM sys.syscacheobjects
1 SELECT * FROM [dbo].[Item] WHERE ID = 2
From the results, executed the dynamic sql using sp_executesql uses same execution plan. EXEC create the execution plan every time.
Conclusion:
Always try to use sp_executesql to execute the dynamic sql to improve the performance.
Labels:
Performance,
SQL Server,
Stored Procedure
Tuesday, October 09, 2007
Avoiding Global temporary table problems between databases
Global temp tables are used to store values that can be used across the stored procedures in particular application run. it will disappears when application is stopped.
Global temp tables are created by following query.
CREATE TABLE [dbo].[##Temp] (ID INT)
if global temp tables are created and used
by single instance only, problem(creating 2 temp table with same name) will not occur. The problem will occur when another instance creating same temp table at same time. This problem will occur on same database or another database with same name of temp table creation.
To avoid this confliction, we will use GUID with temp table name. But this method is more constlier and difficult to handle. Because temp table name is so lengthy.
EXEC ( 'CREATE TABLE [dbo].[##Temp' + CONVERT(VARCHAR, NEWID()) + ' ] (ID INT)' )
Otherwise we can use identity value of some table with temp table name.
EXEC ( 'CREATE TABLE [dbo].[##Temp' + @ID + ' ] (ID INT)' )
The above method will solve the problem even multiple instances running on same database. Because each instance will create unique identity value and using that id with temp table name.
Again problem will occur between different databases creating the same temp table with same identity value. This problem will occur when the multiple instance running on different databases at the same time. Because each instance trying to create temp table with same name.
To avoid confliction between different databases, use DB_ID() or DB_NAME() with temp table name.
EXEC ( 'CREATE TABLE [dbo].[##Temp' + CONVERT(VARCHAR, DB_ID()) + @ID + ' ] (ID INT)' )
EXEC ( 'CREATE TABLE [dbo].[##Temp' + CONVERT(VARCHAR, DB_NAME()) + @ID + ' ] (ID INT)' )
Because DB_ID() or DB_NAME() will be unique to each database.
Global temp tables are created by following query.
CREATE TABLE [dbo].[##Temp] (ID INT)
if global temp tables are created and used
by single instance only, problem(creating 2 temp table with same name) will not occur. The problem will occur when another instance creating same temp table at same time. This problem will occur on same database or another database with same name of temp table creation.
To avoid this confliction, we will use GUID with temp table name. But this method is more constlier and difficult to handle. Because temp table name is so lengthy.
EXEC ( 'CREATE TABLE [dbo].[##Temp' + CONVERT(VARCHAR, NEWID()) + ' ] (ID INT)' )
Otherwise we can use identity value of some table with temp table name.
EXEC ( 'CREATE TABLE [dbo].[##Temp' + @ID + ' ] (ID INT)' )
The above method will solve the problem even multiple instances running on same database. Because each instance will create unique identity value and using that id with temp table name.
Again problem will occur between different databases creating the same temp table with same identity value. This problem will occur when the multiple instance running on different databases at the same time. Because each instance trying to create temp table with same name.
To avoid confliction between different databases, use DB_ID() or DB_NAME() with temp table name.
EXEC ( 'CREATE TABLE [dbo].[##Temp' + CONVERT(VARCHAR, DB_ID()) + @ID + ' ] (ID INT)' )
EXEC ( 'CREATE TABLE [dbo].[##Temp' + CONVERT(VARCHAR, DB_NAME()) + @ID + ' ] (ID INT)' )
Because DB_ID() or DB_NAME() will be unique to each database.
Labels:
SQL Server
Tuesday, September 04, 2007
Randomly selecting records from the Table - SQL Server
If you would like to retrieve the 10 records randomly, you have to use either RAND() or NEWID() function.
RAND():
------
SELECT TOP 10 EmployeeID, RAND() AS RNumber FROM dbo.Employee ORDER BY 2
NEWID():
--------
SELECT TOP 10 EmployeeID FROM dbo.Employee ORDER BY NEWID()
The above 2 methods of retrieving the records from the table have own mertis and demerits.
RAND() methods will give same sample of records in every run. so you have to come with own logic to produce different random number for every records.
NEWID() method give easy solution for the above problem. The idea behind this method is having of unique identifier for each rows. SQL Server maintain this for every rows.
There will be performance overhead problem in this approach when you are using this for TABLE having more records. Because its scans through whole table. you can avoid the full scan by limiting the records using WHERE condition.
SQL Server 2005.
---------------
SQL Server 2005 provides new option to get the records randonly. That new option is
TABLESAMPLE. This keyword is used with FROM clause. This approach could not read
through entire table. its just take the sample records instead of scanning entire
table.
TABLESAMPLE:
------------
SELECT EmployeeID FROM dbo.Employee TABLESAMPLE (50 ROWS)
SELECT EmployeeID FROM dbo.Employee TABLESAMPLE (50 PERCENT)
SELECT TOP 10 EmployeeID FROM dbo.Employee TABLESAMPLE (50 ROWS)
The above first query will not return 50 rows exactly.
First it will convert the ROWS into percent. And the select the records randomly.
Selection of random records based on DATA pages(8K) for that table instead of rows identifier. so it will not produce the expected result.
To get the expected result, we have to use the TOP clause in the select query. The TOP #(number) should be less than selection of records specified in the TABLESAMPLE.
Sometimes,Even this appraoch will not produce the expected result.so you have to use this approach carefully with your logic.
RAND():
------
SELECT TOP 10 EmployeeID, RAND() AS RNumber FROM dbo.Employee ORDER BY 2
NEWID():
--------
SELECT TOP 10 EmployeeID FROM dbo.Employee ORDER BY NEWID()
The above 2 methods of retrieving the records from the table have own mertis and demerits.
RAND() methods will give same sample of records in every run. so you have to come with own logic to produce different random number for every records.
NEWID() method give easy solution for the above problem. The idea behind this method is having of unique identifier for each rows. SQL Server maintain this for every rows.
There will be performance overhead problem in this approach when you are using this for TABLE having more records. Because its scans through whole table. you can avoid the full scan by limiting the records using WHERE condition.
SQL Server 2005.
---------------
SQL Server 2005 provides new option to get the records randonly. That new option is
TABLESAMPLE. This keyword is used with FROM clause. This approach could not read
through entire table. its just take the sample records instead of scanning entire
table.
TABLESAMPLE:
------------
SELECT EmployeeID FROM dbo.Employee TABLESAMPLE (50 ROWS)
SELECT EmployeeID FROM dbo.Employee TABLESAMPLE (50 PERCENT)
SELECT TOP 10 EmployeeID FROM dbo.Employee TABLESAMPLE (50 ROWS)
The above first query will not return 50 rows exactly.
First it will convert the ROWS into percent. And the select the records randomly.
Selection of random records based on DATA pages(8K) for that table instead of rows identifier. so it will not produce the expected result.
To get the expected result, we have to use the TOP clause in the select query. The TOP #(number) should be less than selection of records specified in the TABLESAMPLE.
Sometimes,Even this appraoch will not produce the expected result.so you have to use this approach carefully with your logic.
Labels:
SQL Server,
Tips and Tricks
Monday, July 09, 2007
OUTPUT Command in SQL Server 2005
The output parameter that can be used in stored procedures. This is about returning effected data on a table with a few feature in SQL Server 2005.
SQL Server 2000
A simple question for you. If you want to retrieve last inserted identity value what do you do? Obviously SCOPE_IDENTITY() or @@IDENTITY will be your answer. There is a small different between these too, which I am not going to discuss right now. Even though both will satisfy the current requirement, I will use SCOPE_IDENTITY(), which is the correct one.
CREATE TABLE TempTable
(
ID INT IDENTITY(1 , 1)
, Code VARCHAR(25)
, Name VARCHAR(50)
, Salary Numeric(10 , 2)
)
INSERT INTO TempTable ( Code , Name , Salary )
VALUES ( 'A001' , 'John' , 100 )
INSERT INTO TempTable ( Code , Name , Salary )
VALUES ( 'A002' , 'Ricky' , 200 )
SELECT SCOPE_IDENTITY() AS LastInsertID
However, this will only valid when you need the last inserted ID. A Problem arises when you need the last updated or deleted data. In SQL Server 2000, you don't have any other option other than writing a trigger or triggers to capture them via inserted and/or deleted tables.
more...
SQL Server 2000
A simple question for you. If you want to retrieve last inserted identity value what do you do? Obviously SCOPE_IDENTITY() or @@IDENTITY will be your answer. There is a small different between these too, which I am not going to discuss right now. Even though both will satisfy the current requirement, I will use SCOPE_IDENTITY(), which is the correct one.
CREATE TABLE TempTable
(
ID INT IDENTITY(1 , 1)
, Code VARCHAR(25)
, Name VARCHAR(50)
, Salary Numeric(10 , 2)
)
INSERT INTO TempTable ( Code , Name , Salary )
VALUES ( 'A001' , 'John' , 100 )
INSERT INTO TempTable ( Code , Name , Salary )
VALUES ( 'A002' , 'Ricky' , 200 )
SELECT SCOPE_IDENTITY() AS LastInsertID
However, this will only valid when you need the last inserted ID. A Problem arises when you need the last updated or deleted data. In SQL Server 2000, you don't have any other option other than writing a trigger or triggers to capture them via inserted and/or deleted tables.
more...
Labels:
SQL Server
Thursday, July 05, 2007
Features in Microsoft SQL Server 2008 CTP
Microsoft is making a series of announcements at Tech*Ed related to SQL Server 2008 -- previously codenamed "Katmai". I've got some details on some of the new features including the MERGE statement, Table Valued Parameters, Change Data Capture and the Declarative Management Framework. There should also be a download of the June CTP available inside Connect.
more...
Other Links:
Four Pillar
more...
Other Links:
Four Pillar
Labels:
SQL Server,
SQL Server 2008
Monday, June 18, 2007
Debugging SQL Server 2005 Stored Procedures in Visual Studio
With Microsoft SQL Server 2000 it was possible to debug stored procedures from directly within Query Analyzer (see Debugging a SQL Stored Procedure from inside SQL Server 2000 Query Analyzer for more information). With SQL Server 2005, however, this functionality was moved out of SQL Server Management Studio and into the Visual Studio IDE. Using this technique, it is possible to step into your stored procedures, one statement at a time, from within Visual Studio. It is also possible to set breakpoints within your stored procedures' statements and have these breakpoints hit when debugging your application more...
Labels:
Debugging,
SQL Server
Tuesday, June 05, 2007
New XML Capabilities in SQL Server 2005
Prior to SQL Server 2005, if developers wanted to convert XML data to relational data, they had to use combinations of the stored procedure sp_xml_preparedocument and the OPENXML function. While still valid, this methodology introduces some overhead. SQL 2005 provides native support for the XML data type, and new methods to directly parse and read the data more
Labels:
SQL Server,
XML
Wednesday, May 30, 2007
Passing a Table to A Stored Procedure in SQL Server 2005
In this article, he trying to present a solution to the above scenario by using XML as the format to pass a table to a stored procedure. The CALLER can transform the table (Query result) to an XML variable and pass to the stored procedure. The CALLEE can either convert the XML parameter back to a TABLE variable or directly use XQuery on the XML variable. more
Labels:
SQL Server,
Tips and Tricks
Monday, May 14, 2007
Enable CLR in SQL Server 2005
if you need to run CLR object in SQL Server 2005. you have to enable the CLR option.
I have used following command to enable the CLR features.
EXEC sp_configure 'show advanced options' , '1';
go
reconfigure;
go
EXEC sp_configure 'clr enabled' , '1'
go
reconfigure;
I have used following command to enable the CLR features.
EXEC sp_configure 'show advanced options' , '1';
go
reconfigure;
go
EXEC sp_configure 'clr enabled' , '1'
go
reconfigure;
Labels:
.Net,
SQL Server
Wednesday, April 04, 2007
SQL Server 2005 Reporting Services
Included with SQL Server 2005 is a group of interrelated applications, collectively known as SQL Server Reporting Service (SSRS). SSRS includes all the development and management pieces necessary to publish end user reports in HTML, PDF, Excel, and CSV formats. Originally released as a SQL 2000 separate add on that could be downloaded from the web, all the Reporting Server pieces are now bundled in SQL 2005. With Reporting Services built into SQL, expect to see product adoption rise quickly. Microsoft's accounting package, Solomon, will soon discontinue use of Crystal Reports in favor of SSR. more..
Labels:
SQL Server,
SSRS
Data partitioning in SQL Server 2005
Data partitioning, a new feature added to SQL Server 2005, provides a way to divide large tables and indexes into smaller parts. By doing so, it makes the life of a database administrator easier when doing backups, loading data, recovery and query processing.Data partitioning improves the performance, reduces contention and increases availability of data.A Table can be partitioned based on any column in the table. Microsoft defines that column as the partition key. more..
Labels:
SQL Server
Subscribe to:
Posts (Atom)
