Feeds:
Posts
Comments

Posts Tagged ‘SQL Server’

EXECUTE statement failed because its WITH RESULT SETS clause specified %d result set(s), but the statement only sent %d result set(s) at run time is one of the new error messages seen in SQL Server 2012. This error message is due to the invalid use of new feature EXEC WITH RESULT SETS.

Let’s discuss this in detail:
Message Number: 11536

Severity : 16

Error Message: EXECUTE statement failed because its WITH RESULT SETS clause specified %d result set(s), but the statement only sent %d result set(s) at run time.

Error Generation:

Let me create a sample stored procedure to generate this error.

Create Procedure UDP_Resultset
As
Select 'A' as [First Letter]
Select 'B' as [Second Letter]
GO
EXEC UDP_Resultset

exec resultset1.1

You can see that the above stored procedure is executed successfully and it has two result sets.
Lets try to execute it with WITH RESULT SETS clause.

EXEC UDP_Resultset
WITH RESULT SETS
(([1st Letter] varchar(50)
)
,([2nd Letter] varchar(50)
)
,([3rd Letter] varchar(50)
)
);
--OUTPUT
Msg 11536, Level 16, State 1, Line 1
EXECUTE statement failed because its WITH RESULT SETS clause specified 3 result set(s), but the statement only sent 2 result set(s) at run time.

Ooops…… I am unable to execute it properly. It returned the two result sets and the error message.

errormsg11536.1.1

Resolution:
Why this error ? Because, the above stored procedure returns two result sets but we defined WITH RESULT SETS clause for three result sets. Lets rewrite the script and define two result sets (The same number of result sets returned by stored procedure) to avoid this error.

EXEC UDP_Resultset
WITH RESULT SETS
(([1st Letter] varchar(50)
)
,([2nd Letter] varchar(50)
));
--OUTPUT

exec resultset1.3

Conclusion :
Remember, whenever you use any stored procedure WITH RESULT SETS clause, make sure you use exactly the same number of result set returned by stored procedure to avoid such errors.

Read Full Post »

How to calculate the number of days in a year ? Was a question I came across and began with my usual research for the solution. Given below are few methods.

Method 1 :
In this method, I calculated the no of days in a year using the days difference between 1 Jan of the current year and the next year.
Given below are the scripts.

--This method will work on SQL Server 2005 and above.
DECLARE @year AS INT
SET @year=2012
Select DATEDIFF(DAY,DATEADD(YEAR,@year-1900,0)
,DATEADD(YEAR,@year-1900+1,0)) AS [TOTAL NO OF DAYS]
GO
--This technique is same as above but using new datefromparts
--function introduced in SQL Server 2012.
--This technique will work in SQL Server 2012 and above.

DECLARE @Year INT =2012
SELECT DATEDIFF(DAY,DATEFROMPARTS(@Year,1,1)
, DATEFROMPARTS(@year+1,1,1)) AS [TOTAL NO OF DAYS]
GO

Method 2 :
In this method, I checked whether February had 28 days or 29. Obviously, if 29 days it means total no of days in a year is 366 else 365.
Given below are the scripts.

--This method will work on SQL Server 2005 and above.
DECLARE @year AS INT
SET @year=2012
SELECT (Case When Day(DATEADD(YEAR,@year-1900,0)+59)=29
Then 366 else 365 end) AS [TOTAL NO OF DAYS]
GO
--This technique is same as above but using new datefromparts and
--EOMONTH functions introduced in SQL Server 2012.
--This technique will work in SQL Server 2012 and above.
DECLARE @year AS INT
SET @year=2012
SELECT (Case When  DAY(EOMONTH(DATEFROMPARTS(@Year,2,1)))=29
Then 366 else 365 end) AS [TOTAL NO OF DAYS]

Method 3 :
In this method, I checked the day of last date of the year e.g 31st Dec 2012.

--This method will work on SQL server 2005 and above.
DECLARE @year AS INT
SET @year=2012
Select DATEPART(dy,(DATEADD(YEAR,@year-1899,0)-1))
AS [TOTAL NO OF DAYS]

--This technique is same as above but using new datefromparts
--functions introduced in SQL Server 2012.
--This technique will work in SQL Server 2012 and above.
DECLARE @year AS INT
SET @year=2012
Select DATEPART(dy,DATEFROMPARTS(@Year,12,31))
AS [TOTAL NO OF DAYS]

Conclusion :
We have multiple ways to calculate the number of days but I recommend to use the Method 3, as it has shortest way to calculate the number of days in a year.

Let me know if you have a better way to achieve it.

Read Full Post »

I have been using sys.dm_exec_requests for quite a long time and I have developed some tools to store certain request information using this dynamic management view. In the SQL Server 2012, sys.dm_exec_requests has a breaking change, which I realized once I deployed my tools in SQL Server 2012 and I was unsuccessful. Let me explain why and how did I fixed it.
Given below is the script taken from one of the tools that is developed using sys.dm_exec_requests.

Let me explain it step by step.
Step 1 :
Lets create a table (On SQL Server 2008 and 2012) to demonstrate it.

use tempdb
GO
CREATE TABLE [dbo].[dm_exec_requests_temp](
[session_id] [smallint] NOT NULL,
[status] [nvarchar](30) NOT NULL,
[blocking_session_id] [smallint] NULL,
[command] [nvarchar](16) NOT NULL,
[wait_type] [nvarchar](60) NULL,
[wait_time] [int] NOT NULL,
[wait_resource] [nvarchar](256) NOT NULL,
[transaction_id] [bigint] NOT NULL
) ON [PRIMARY]
GO
--OUTPUT

Command(s) completed successfully.

Step 2 :
Insert / Select records in the above temporary table in SQL Server 2005/2008.

Insert into dm_exec_requests_temp
SELECT session_id ,status ,blocking_session_id, command
,wait_type ,wait_time ,wait_resource
,transaction_id
FROM sys.dm_exec_requests
GO
Select * from dm_exec_requests_temp
--OUTPUT

sys.dm_exec_requests1.1

Step 3 :
Insert / Select records in the above temporary table in SQL Server 2012.

Insert into dm_exec_requests_temp
SELECT session_id ,status ,blocking_session_id, command
,wait_type ,wait_time ,wait_resource
,transaction_id
FROM sys.dm_exec_requests
GO
Select * from dm_exec_requests_temp
--OUTPUT

Msg 8152, Level 16, State 13, Line 1
String or binary data would be truncated.
The statement has been terminated.

Oooops……………
It generated an error.

Step 4:
The above script executed successfully in SQL Server 2005/2008 but failed in SQL Server 2012. The reason behind above error is sys.dm_exec_requests has a column namely command. In SQL Server 2005/2008 the data type of command column was nvarchar(16) but it has been changed to nvarchar(32) in SQL Server 2012. As you can see, I created the column command in temporary table with nvarchar(16) datatype.

Step 5:
To resolve above error, you need to change the data type of command column in temporary table (Step 1) from nvarchar(16) to nvarchar(32) and insert records again.

Alter table dbo.dm_exec_requests_temp Alter column [command] nvarchar(32)

Conclusion :
In SQL Server 2012, sys.dm_exec_requests has changed the data type of column “Command” from nvarchar(16) to nvarchar(32). Remember to implement this data type change effects to avoid such errors.

Reference : MSDN

Read Full Post »

There are various methods to find table across the database but I was keen on a solution to find a table across the database and if the table is not available in any database then the script must mention so.

Given below is the solution designed with the help of a sys.tables(system table).
Note : This solution is compatible with SQL SERVER 2005 and above.

Create Procedure Search_Table_Across_Databases_Proc
-- Script Name : Sp_Search_Table_Across_Databases
-- Script Type : Search Tables Across all SQL Server databases.
-- Developed By  : Muhammad Imran
-- Date Created: 25 Mar 2013
@TableName nvarchar(Max)
As
BEGIN
DECLARE @SQL nvarchar(MAX)     --Declare variable to store dynamic query result
DECLARE @DB_NAME nvarchar(200) --Declare variable to store Database name

SET @SQL=''

--Create table to store the result of each database
CREATE TABLE #SearchResult
(
[DB_Name] nvarchar(max),
[Table Name] nvarchar(max),
[Status] varchar(50)
)

--Declare cusrsor to loop across all databases
DECLARE DB_Cursor CURSOR FOR
--Pick the list of all database
SELECT QUOTENAME([name]) from sys.databases order by [name]

OPEN DB_Cursor
FETCH NEXT FROM DB_Cursor INTO @DB_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
--In this dynamic query, two select statements are built because
--one statement will check the unavailability and the
--second statement will check the availability of the
--tables in the database and insert the result in the #SearchResult table

SET @SQL= 'Insert into #SearchResult
SELECT ''' + @DB_NAME + ''' as [Database Name],'''',''Not Available''
from ' + @DB_NAME + '. sys.tables
Where [name] =''' + @TableName + ''' Having Count(*)=0
UNION ALL
SELECT ''' + @DB_NAME + ''' as [Database Name],[name],''Available''
from ' + @DB_NAME + '.sys.tables
Where [name] =''' + @TableName + ''' Group By [name]
Having Count(*)>0'

EXEC(@SQL)

FETCH NEXT FROM DB_Cursor INTO @DB_NAME
END
CLOSE DB_Cursor
DEALLOCATE DB_Cursor
--We can browse the table to view the results
Select * from #SearchResult Order by [DB_Name],[Table Name]
END
GO
--Syntax
--EXEC Search_Table_Across_Databases_Proc 'Table Name'
--Example
EXEC Search_Table_Across_Databases_Proc 'employee'
--OUTPUT

searchtables1.1-1

Read Full Post »

Backup and restore are two major parts of any DBA’s job and this part should be done efficiently. In order to do it efficiently, DBA’s should take backups in such a way that makes their life easier in case of any failure. But we need to remember that we have different types of backup (Full, Differential, Log) and at the time of failure we must use a correct path (Sequence) to restore all data successfully.

Before SQL Server 2012, DBA’s should manually control all these aspects for restore. But in SQL Server 2012, a solution came namely “Recovery Adviser”, which can show you the timeline graphically and advise you how to restore it efficiently and also you can define your own best possible path of restore as well.

Lets discuss Recovery Adviser step by step in detail.

Step 1 :
Lets create table and insert few records in it to test.

use test_db
Go
Create table test
(
[ID] int,
[Name] nvarchar(50)
)
Go
Insert into test Values(1,'Imran')

Step 2 :
Take a full backup of test_db database.

BACKUP DATABASE [Test_DB] TO DISK = N'G:\DBBackup\test_DB_Full'
WITH NOFORMAT, NOINIT, NAME = N'Test_DB-Full Database Backup'
, SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO

Step 3 :
Insert one more record and take a differential backup of test_db database.

use Test_DB
GO
insert into test values(2,'Bob')

 

BACKUP DATABASE [Test_DB] TO DISK = N'G:\DBBackup\test_DB_Differential'
WITH DIFFERENTIAL , NOFORMAT, NOINIT,
NAME = N'Test_DB-Differential Database Backup'
, SKIP, NOREWIND, NOUNLOAD, STATS = 10

Step 4 :
Insert one more record and take a transaction log backup of test_db database.

use Test_DB
GO
insert into test values(3,'John')

 

BACKUP LOG [Test_DB] TO DISK = N'G:\DBBackup\test_DB_Log'
WITH NOFORMAT, NOINIT, NAME = N'Test_DB-Transaction Log Backup'
, SKIP, NOREWIND, NOUNLOAD, STATS = 10

Step 5 :
We took three different types (Full, Differential, Transaction) of backup and now we can recover the database in case of any failure but how ? In earlier version we need to keep a track of backups as to which backup we took, at what time, in what sequence etc etc. But SQL Server 2012 “Recovery adviser”, absorbs all such worries and will handle it efficiently. Lets go to restore window to see what is inside this “Recovery adviser”.

In the restore screen, you can find a new button namely “Timeline” and the list of backups that we took earlier in the same sequence with lots of additional information that can help you recover your database.

DRA1.1

Step 6 :
Click on the timeline button and you will be more than impressed to view the new timeline (on the basis of Hour, Six Hour, Day, Week) of backup. In this screen you have two options to restore the backup.

  • Last backup taken
  • Specific date and time

From the first option, you can restore on the basis of last backup. But sometime if you need to recover any particular transaction, you can restore at any point of time from option 2 as well.
DRA1.3

DRA1.2

Conclusion :
Database recovery adviser is a very handy tool shipped with SQL Server 2012. It helps you to restore your backup at any point of time with the graphical representation such as when and what type of backup you took and how can you restore it efficiently in case of any failure. This will resolve a lot of backup handling issues, for example, to maintain a sequence and to restore in a best possible path as well.

Read Full Post »

The culture parameter ‘%.*ls’ provided in the function call is not supported is one of the new error messages shipped with SQL Server 2012. This error message is some how related to Culture & Format, a new string function shipped with SQL Server 2012 as well.

Let’s discuss this in detail:
Message Number: 9818

Severity : 16

Error Message: The culture parameter ‘%.*ls’ provided in the function call is not supported.

Error Generation:

Given below is the script that I tried to execute but it gave me this error.

SELECT FORMAT (Getdate() ,'dddd, MMMM dd, yyyy hh:mm:ss tt','e-US')
AS [English Culture]

Msg 9818, Level 16, State 1, Line 3
The culture parameter ‘e-US’ provided in the function call is not supported.
Ooopps…… I am unable to execute it.

errormsg9818.1.1

Resolution:
Sometimes, the error is either due to typo or lack of knowledge of exact name of the culture. Make sure whenever culture Info is being used, correct culture name is used.
Given below is the script that works fine because the exact culture name of “English – United States” is en-US NOT  e-US.

SELECT FORMAT (Getdate() ,'dddd, MMMM dd, yyyy hh:mm:ss tt','en-US')
AS [English Culture]
--OUTPUT

English Culture
———————————–
Friday, March 22, 2013 12:30:35 AM

(1 row(s) affected)

errormsg9818.1.2
Conclusion :

Remember, whenever you use culture name , make sure you are using exact/correct culture name.

Read Full Post »

I have been using exist() function for a long time. This is very handy when we need to check the existence of any data in the xml document. There is also a bug related to this function when it comes to NULL but this bug is fixed in SQL Server 2012.

Let me explain it with examples.
Example 1 :
Create the given below script in ealier version of SQL Server (2005 & 2008)

DECLARE @xmltest XML;
SET @xmltest = null;
SELECT COUNT(*) as [T_Count] WHERE @xmltest.exist('/raresql') = 0;
--OUTPUT

T_Count
———–
1

(1 row(s) affected)

Ooopps…… The expected result is 0 because ‘/raresql’ doesn’t exist in the @xmltest but it returned 1 .

Example 2 :
Lets create the same sample in SQL Server 2012 and view the output.

DECLARE @xmltest XML;
SET @xmltest = null;
SELECT COUNT(*) as [T_Count] WHERE @xmltest.exist('/raresql') = 0;
--OUTPUT

T_Count
———–
0

(1 row(s) affected)

The expected result is 0 because ‘/raresql’ doesn’t exist in the @xmltest and as expected the query returned 0 as well.

Conclusion :
The behavior issue with exist() function on xml datatype is fixed in SQL Server 2012. If the SQL Server is upgraded from earlier version to 2012 and if some scripting is added to correct this behavior in the earlier version, then these scripts should be removed.

Reference : MSDN

Read Full Post »

How to separate date and time from DateTime ? I came across this question many times in multiple blogs.

Given below are different methods to separate date and time from datetime which are compatible with different versions. Make sure you are using correct method in your SQL Server version.

Mehtod 1 :
This method will work under SQL Server 2000 and above.

Declare @Datetime as datetime
Set @Datetime =getdate()
Select @Datetime as [Datetime]
Select Convert(varchar(10),@Datetime,120) as [Date]
Select Convert(varchar(20),@Datetime,114) as [Time]
--OUTPUT

Datetime
———————–
2013-03-18 22:02:02.960

(1 row(s) affected)

Date
———-
2013-03-18

(1 row(s) affected)

Time
——————–
22:02:02:960

(1 row(s) affected)

Mehtod 2 :
This method will work under SQL Server 2008 and above.

Declare @Datetime as datetime
Set @Datetime =getdate()
Select @Datetime as [Datetime]

Select Convert(Date,@Datetime) as [Date]
Select Convert(Time,@Datetime) as [Time]
--OUTPUT

Datetime
———————–
2013-03-18 22:04:24.930

(1 row(s) affected)

Date
———-
2013-03-18

(1 row(s) affected)

Time
—————-
22:04:24.9300000

(1 row(s) affected)

Mehtod 3 :
This method will work in SQL Server 2012 and above.

Declare @Datetime as datetime
Set @Datetime =getdate()
Select @Datetime as [Datetime]

Select Format(@Datetime,'yyyy-mm-dd') as [Date]
Select Format(@Datetime,'hh:mm:ss tt') as [Time]
--OUTPUT

Datetime
———————–
2013-03-18 22:14:23.763

(1 row(s) affected)

Date
———————–
2013-14-18

(1 row(s) affected)

Time
———————–
10:14:23 PM

(1 row(s) affected)

Conclusion :
I have mentioned 3 different methods to separate date and time from datetime but if you have SQL Server 2008 and above, then I would recommend Method 2.The reason behind this recommendation is in Method 2 we just convert datetime into a date type and time type but in other methods we first convert datetime into date type and time type and then give a style as well.

Read Full Post »

sys.dm_os_sys_info is one of the handy dynamic management views when it comes to query about the miscellaneous information of computer, resources & consumption by SQL Server. sys.dm_os_sys_info is with SQL Server family since SQL Server 2005, but whenever there is a new version of SQL Server, it always brings modification / additional helpful information in this view. But this modification / addition may  break your code if you don’t consider these changes with respect to versions. To avoid any such errors, I have prepared a comparison sheet of different versions of sys.dm_os_sys_info along with the changes to make life far easier.

Given below is the screen image of the comparison sheet. (Also attached Excel file for version 2007 & above):

sys.dm_os_sys_info.1.1

Reference : MSDN

Read Full Post »

Performance plays a vital role in SQL server. The importance of performance increases with the rise in the data growth. In other words, increase in data growth is directly proportional to the increase in performance. In SQL Server, index plays an important role to increase the performance as well. In SQL server 2012, we got a boost in performance (a new type of index came) namely ColumnStore Index. It is one of the nicest database features introduced in SQL Server 2012 built on xVelocity technology which is used to optimize memory. Lets discuss its syntax , purpose, examples & performance.

Syntax:
CREATE [ NONCLUSTERED ] COLUMNSTORE INDEX index_name

ON ( column [ ,…n ] )

[ WITH ( [ ,…n ] ) ]

[ ON {

{ partition_scheme_name ( column_name ) }

| filegroup_name

| “default”

}

]

[ ; ]

::=
{
[database_name. [schema_name ] . | schema_name . ]
table_name
{

::=
{
DROP_EXISTING = { ON | OFF }
| MAXDOP = max_degree_of_parallelism
}

Purpose :

The purpose of ColumnStore Index is to increase the performance in comparison to the traditional Index. It is a number of times faster than traditional index. The reason behind its performance is the way it handles the index. In Tradition Index, it stores multiple rows in each page and it retrieves in the same way. In ColumnStore Index, it stores each column in separate page and it retrieves in the same way.
In simple words you can say Tradition Index is a Row store while ColumnStore Index is a Column store.

Graphical Representation:
Given below is the graphical representation of traditional index & ColumnStore Index and you can see how each technology keeps the data pages in a different manner.

columnstoreindex1.1

Let’s test the performance of ColumnStore index Step by Step.

Step 1 :
Create a sample table.

CREATE TABLE dbo.[PurchaseOrderDetail_Sample](
[PurchaseOrderID] [int] NOT NULL,
[PurchaseOrderDetailID] [int] NOT NULL,
[DueDate] [datetime] NOT NULL,
[OrderQty] [smallint] NOT NULL,
[ProductID] [int] NOT NULL,
[UnitPrice] [money] NOT NULL,
[LineTotal] numeric(18,2),
[ReceivedQty] [decimal](8, 2) NOT NULL,
[RejectedQty] [decimal](8, 2) NOT NULL,
[StockedQty] Numeric(18,2),
[ModifiedDate] [datetime] NOT NULL)

Step 2 :
Insert some data into table (PurchaseOrderDetail_Sample), because if table has few records you cannot measure the performance of columnstore index properly.

--This insertion is just to demonstrate,
--It is not recommended on production server.
Insert into dbo.[PurchaseOrderDetail_Sample]
Select * from [Purchasing].[PurchaseOrderDetail]
GO 100

Step 3 :
Next step is to create a Columnstore index in this table.

CREATE NONCLUSTERED COLUMNSTORE INDEX
[IX_PurchaseOrderDetail_Sample_ColumnStore]
ON [PurchaseOrderDetail_Sample]
(UnitPrice, OrderQty,ReceivedQty,ProductID)
GO

Step 4 :
Now, it is time to create a query using this table and view the performance. Remember this query has a ColumnStore Index.

SET STATISTICS TIME ON
SET STATISTICS IO ON
--This query will use columnstore index and will return the result set.
SELECT ProductID as [Product ID], AVG(UnitPrice) as [Average Unit Price]
,SUM(OrderQty) as [Purchase Order Qty], AVG(ReceivedQty) as [Received Qty]
FROM [dbo].[PurchaseOrderDetail_Sample]
GROUP BY ProductID
ORDER BY ProductID

go
--This query will ignore columnstore index and will return the result set.
SELECT ProductID as [Product ID], AVG(UnitPrice) as [Average Unit Price]
,SUM(OrderQty) as [Purchase Order Qty], AVG(ReceivedQty) as [Received Qty]
FROM [dbo].[PurchaseOrderDetail_Sample]
GROUP BY ProductID
ORDER BY ProductID
OPTION (IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX)

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

Step 5 :
Lets compare the result of IO & Time Statistics for both, with columnstore index and without columnstore index.

Type

Logical Reads

CPU Time

Elapsed Time

ColumnStore

34

47 ms

342 ms

Without ColumnStore

8345

1482 ms

1473 ms

ColumnStore1.2

Execution Plan comparison :

ColumnStore1.3

Index Scan comparison :
ColumnStore1.4

Conclusion :
I am quite impressed to see the performance of Columnstore index. It is very handy and recommended in a place where you are either facing performance issues with the query or dealing with data warehouse. However, Columnstore index has some limitations as well which I will post in my upcoming post.

Read Full Post »

« Newer Posts - Older Posts »