Feeds:
Posts
Comments

Archive for the ‘Solutions’ Category

“How to implement LIMIT in SQL Server?” (How to pick up certain rows after certain rows in SQL SERVER), I came across this question many times in multiple forums and the common solution is, to use common table expression and ROW_NUMBER. However, this is an old approach. A new approach has been introduced in SQL Server 2012 using OFFSET ROWS FETCH NEXT ROWS.

Let me create a sample script to explain both approaches.

USE AdventureWorks2012;
GO
Select
FirstName
,Jobtitle
From [HumanResources].[vEmployee]
Order By FirstName,Jobtitle
--OUTPUT

limitrows1.1

Lets discuss both approaches with examples :

Old Approach:
In this approach, we will pick 10 rows after row number 10 (meaning row number 11 till 20) from [HumanResources].[vEmployee]. Given below is the script.

--This script is compatible with SQL Server 2005 and above.
USE AdventureWorks2012;
GO
;With CTE_Employee_List As
(
Select ROW_NUMBER() Over
(Order By[FirstName],[JobTitle]) As [Row Number],
FirstName
,Jobtitle
From [HumanResources].[vEmployee]
)
Select FirstName,Jobtitle
From CTE_Employee_List
Where [Row Number] Between 11 And 20;
GO
--OUTPUT

limitrows1.2-1

New Approach:
In the new approach too, we will select 10 rows after row number 10 (meaning row number 11 till 20) from [HumanResources].[vEmployee] and the script goes as follows :

--This script is compatible with SQL Server 2012 and above.
USE AdventureWorks2012;
GO
Select
FirstName
,Jobtitle
From [HumanResources].[vEmployee]
Order By FirstName,Jobtitle
Offset 10 Rows
Fetch Next 50 Rows Only;
--OUTPUT

limitrows1.4

As we can see, the output is exactly same but a lot of other parameters are different that can impact the performance.
Given below is the summary of both approaches.

S.No

Type

Old Approach

New Approach

1

Common Table Expression

Yes (required)

N/A

2

ROW_NUMBER

Yes (required)

N/A

3

CPU time

15 ms

15 ms

4

Elapsed time

1387 ms

375 ms

5

Query Cost (relative to the batch)

53%

47%

Conclusion :
If you are using SQL Server 2012, I would recommend to use the new approach. It not only boosts the performance but reduce the line of code as well.

Read Full Post »

In my previous article, I wrote about  How to search a string value in all columns in the table and in all tables in a single database. Today we will search a string value in all columns in the table and in all tables in all databases.

Lets proceed step by step :

Step 1:
Prerequisite of Step 1 & Step 2 from previous article.

Step 2 :
Create the given below stored procedure to search the string in all columns in the table and in all tables in all databases.

CREATE PROCEDURE Find_Record_Across_Databases_Proc
@string VARCHAR(Max)
AS

DECLARE @sqlString varchar(Max)
DECLARE @Database_Name sysname

--Declare Cursor
DECLARE Database_Cursor CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR
SELECT [name] FROM sys.databases
WHERE NAME NOT IN ('master','tempdb','model','msdb') ORDER BY NAME

OPEN Database_Cursor

FETCH NEXT FROM Database_Cursor INTO @Database_Name
WHILE @@FETCH_STATUS = 0
BEGIN

EXEC UDP_Find_Record_Across_Tables
@Database_Name, NULL, NULL ,@string

FETCH NEXT FROM Database_Cursor INTO @Database_Name
END

CLOSE Database_Cursor
DEALLOCATE Database_Cursor

SELECT * FROM tempdb.dbo.result
GO

Example:
Once you created the above stored procedure. After that lets execute it to search a string in all columns of all tables and in all databases. Given below is a sample.

EXEC Find_Record_Across_Databases_Proc 'senior'

searchtables1.5

Read Full Post »

I really appreciate active participation of my blog readers. Yesterday, I received an inquiry from ‘Abhilash’ one of my blog readers, how to search a string value in all columns in the table and in all tables in a database.

Given below is the solution that will search a string value in all columns in the table and in all tables in a database.

Lets proceed it step by step.
Step 1:
Create given below table in tempdb database to consolidate all search result.

Use tempdb
GO
Create Table Result
(
[Sno] int identity(1,1),
[Database Name] sysname,
[Schema Name] sysname,
[Table Name] sysname,
[Column Name] sysname,
[Record Name] varchar(Max)
)

Step 2:
Create the given below stored procedure to search the string in all columns in the table and in all tables in a database.

--Create the store procedure to search a string across the tables.
Use AdventureWorks2012
GO
Create PROCEDURE Find_Record_Across_Tables_Proc
@Database sysname,
@Schema sysname,
@Table sysname,
@String VARCHAR(Max)

AS

DECLARE @SqlString varchar(Max)
DECLARE @Table_Schema sysname
DECLARE @Table_Name sysname
DECLARE @Column_Name sysname

--Declare Cursor
SET @SqlString = 'DECLARE String_cursor CURSOR FOR
Select TABLE_SCHEMA, TABLE_NAME ,COLUMN_NAME from
' + @Database +'.INFORMATION_SCHEMA.COLUMNS
Where DATA_TYPE IN (''text'',''ntext'',''varchar''
,''nvarchar'',''char'',''nchar'')'

--Filter schema name
IF @schema IS NOT NULL
Begin
SET @SqlString = @SqlString + ' And TABLE_SCHEMA=''' + @Schema + ''''
End
--Filter table name
IF @table IS NOT NULL
Begin
SET @SqlString = @SqlString + ' And TABLE_NAME=''' + @table + ''''
End

Print @SqlString
EXEC (@SqlString)

OPEN String_cursor

FETCH NEXT FROM String_cursor
INTO @Table_Schema, @Table_Name, @Column_Name

WHILE @@FETCH_STATUS = 0
BEGIN
SET @SqlString = 'IF EXISTS(SELECT ' + QUOTENAME(@Column_Name)
+ ' FROM ' + @Database + '.' + QUOTENAME(@Table_Schema)
+ '.' + QUOTENAME(@Table_Name)
+ ' WHERE ' + QUOTENAME(@Column_Name)
+ ' Like ''%' + @string + '%'')
Insert into tempdb.dbo.result
([Database Name],[Schema Name]
,[Table Name],[Column Name],[Record Name])
SELECT ''' + QUOTENAME(@Database) + ''','''
+ QUOTENAME(@Table_Schema) + ''','''
+ QUOTENAME(@Table_Name) + ''',''''
+ ''' + QUOTENAME(@Column_Name)
+ ''',' + QUOTENAME(@Column_Name)
+ ' FROM ' + @Database + '.'
+ QUOTENAME(@Table_Schema)
+ '.' + QUOTENAME(@Table_Name)
+ ' WHERE ' + QUOTENAME(@Column_Name)
+ ' Like ''%' + @string + '%'''
Print @SqlString
EXEC (@SqlString)

FETCH NEXT FROM String_cursor
INTO @Table_Schema, @Table_Name, @Column_Name

END
CLOSE String_cursor
DEALLOCATE String_cursor
GO

Step 3:
In the step 3, you can execute the above stored procedure with different parameters.
Given below are few examples of above stored procedure.

Example 1:
To search a string in all columns of all tables in a single database.

Use AdventureWorks2012
GO
Delete from tempdb.dbo.result
GO
EXEC Find_Record_Across_Tables_Proc
'AdventureWorks2012', NULL, NULL ,'Senior'
GO
Select * from tempdb.dbo.result
GO

search_string_in_all_tables1.0

Example 2:
To search a string in all columns of a single tables and in a single database.

Use AdventureWorks2012
GO
Delete from tempdb.dbo.result
GO
EXEC Find_Record_Across_Tables_Proc
'AdventureWorks2012', NULL, 'Employee' ,'Senior'
GO
Select * from tempdb.dbo.result
GO

search_string_in_all_tables1.2

Example 3:
To search a string in all columns of a single schema in a single table and in a single database.

Use AdventureWorks2012
GO
Delete from tempdb.dbo.result
GO
EXEC Find_Record_Across_Tables_Proc
'AdventureWorks2012', 'HumanResources', 'Employee' ,'Senior'
GO
Select * from tempdb.dbo.result
GO

search_string_in_all_tables1.1

Read Full Post »

If you are planning to convert varchar to float you should know that these two data types are not compatible with each other. In the earlier versions of SQL Server you had to use CASE, ISNUMERIC & CONVERT to convert varchar to float but in SQL Server 2012, you can do it with just one function TRY_CONVERT. Let me create a sample to explain it.

Use tempdb
GO
Create Table tbl_test
(
[Numbers] varchar(50)
)
GO
Insert into tbl_test values(12345.6789)
Insert into tbl_test values('AB12345')
Insert into tbl_test values(12.1)
Insert into tbl_test values(11.2345678)
GO

Given below are two different methods to convert varchar to float but these two methods are compatible with different versions of SQL Server.
Method 1 (For earlier versions of SQL Server):

--This script is compatible with SQL Server 2005 and above.
Use tempdb
GO
Select [Numbers],
(Case When Isnumeric([Numbers])=1 Then
Convert(float,[Numbers]) else NULL end) As [Varchar to Float]
from tbl_test
--OUTPUT

varchartofloat1.1
Method 2 (For SQL Server 2012):

--This script is compatible with SQL Server 2012 and above.
Use tempdb
GO
Select Try_convert(float,[Numbers]) as [Varchar to float]
from tbl_test
--OUTPUT

varchartofloat1.2 Cleaning :

use tempdb
GO
drop table tbl_test

Read Full Post »

How to get the Month Name from Date ? Have been questioned numerous times and we do have its solution via DATENAME function. However, today we will achieve the same solution using FORMAT function, introduced in SQL Server 2012 as well. Given below are the two methods that help in identifying the Month Name from Date in SQL Server 2005 & above as well as SQL Server 2012 & above.

Method 1 :
Script supported in SQL Server 2005 and above :

--This script will work in SQL Server 2005 and above
Declare @Datetime as datetime
Set @Datetime =getdate()

SELECT DATENAME(month, @Datetime) AS [Month Name]
--OR
SELECT DATENAME(mm, @Datetime) AS [Month Name]
--OR
SELECT DATENAME(m, @Datetime) AS [Month Name]
--OUTPUT

get month name from date1.1

Method 2 :
Script supported in SQL Server 2012 and above :

--This script will work in SQL Server 2012 and above
Declare @Datetime as datetime
Set @Datetime =getdate()
Select FORMAT(@Datetime,'MMMM') AS [Month Name]
--OUTPUT

Get month name from date-1
Have you come across any other method ? Do share.

Read Full Post »

A few days ago I was working on indexes on a development server.  Accidentally I dropped few indexes. Fortunately, since I normally take the database backup, I restored the backup and it recovered all indexes perfectly. What if I didn’t have the backup and I did it on production server, it would be just  BOOOOOM ;). However, I looked for a solution on the internet how to recover the dropped index without backup. But could not get the proper solution. So finally I decided to develop a solution which I would be sharing with you.

Note : It is recommended to take database backup on regular basis and recover any disaster from backup.

Lets create & drop one nonclustered index on a table to demonstrate it.

USE AdventureWorks2012
GO
CREATE NONCLUSTERED INDEX [IX_PurchaseOrderDetail_Sample]
ON [Purchasing].[PurchaseOrderDetail]
(
[OrderQty],
[ReceivedQty],
[RejectedQty],
[ProductID]
)
GO
DROP INDEX [IX_PurchaseOrderDetail_Sample]
ON [Purchasing].[PurchaseOrderDetail]

Lets recover it step by step :

Step 1:
In this step, you need to create the given below function in the database from where you need to do the recovery.

USE AdventureWorks2012
GO
CREATE FUNCTION [dbo].[UDF_Get_Index_Column_Name]
(@Object_id bigint,@Column_id bigint)
RETURNS varchar(Max)
AS
Begin
Declare @Column_Name as varchar(Max)
Select @Column_Name=[name] from sys.columns
where object_id =@Object_id And column_id =@Column_id
Return @Column_Name
End
GO

Step 2:
In this step, you need to create the given below stored procedure in the database from where you need to do the recovery.

CREATE PROCEDURE Recover_Dropped_Index_Proc
@Date_From DATETIME='1900/01/01',
@Date_To DATETIME ='9999/12/31'
AS

;With CTE AS (Select
Row_number() Over(Partition By A.[Transaction ID]
Order By [Transaction ID]) as [SNO]
,A.[Transaction ID]
,'CREATE ' +
(Case When Convert(int,Substring(A.[RowLog Contents 0],22,1)) =0
Then 'Heap'
When Convert(int,Substring(A.[RowLog Contents 0],22,1)) =1
Then 'Clustered'
When Convert(int,Substring(A.[RowLog Contents 0],22,1)) =2
Then 'Nonclustered'
When Convert(int,Substring(A.[RowLog Contents 0],22,1)) =3
Then 'XML'
When Convert(int,Substring(A.[RowLog Contents 0],22,1)) =4
Then 'Spatial'
When Convert(int,Substring(A.[RowLog Contents 0],22,1)) =6
Then 'Nonclustered columnstore'
end)
+ ' INDEX ' + Quotename(
Replace(Substring(
A.[RowLog Contents 0],47,LEN(A.[RowLog Contents 0])),0x00,0x))
+' ON ' + Sch.name +'.'
+ Object_Name(
Convert(varbinary,Reverse(Substring(A.[RowLog Contents 0],5,4))))
as [Command1]

, [dbo].[UDF_Get_Index_Column_Name] (
Convert(bigint,
Convert(varbinary,Reverse(Substring(A.[RowLog Contents 0],5,4))))
, Convert(bigint
, Convert(varbinary,Substring(A.[RowLog Contents 0],20,2))))
as [Column Name]

, Convert(int,Substring(A.[RowLog Contents 0],22,1)) as [Type]

, SUM(1) OVER(Partition By A.[Transaction ID]) as [Total Rows]

From sys.fn_dblog(NULL, NULL) As A
Inner Join sys.tables As tbl
On Object_Name(Convert
(varbinary,Reverse(Substring(A.[RowLog Contents 0],5,4))))=tbl.name
Inner Join sys.schemas As Sch On tbl.schema_id =sch.schema_id
Where A.AllocUnitName In ('sys.sysiscols.clst','sys.sysidxstats.clst')
And Context In ('LCX_MARK_AS_GHOST', 'LCX_HEAP')
And Operation in ('LOP_DELETE_ROWS')
And A.[TRANSACTION ID] In (SELECT DISTINCT [TRANSACTION ID]
FROM  sys.fn_dblog(NULL, NULL)
Where Context IN ('LCX_NULL') And Operation In ('LOP_BEGIN_XACT')
And [Transaction Name] Like '%DROP INDEX%'
And  CONVERT(NVARCHAR(11),[Begin Time]) Between @Date_From And @Date_To)
)
Select (Case When [type]=0 And [SNo] =2 And [SNO]<>[Total rows]
Then '(' + [Column Name] +','
When [type]=0 And [SNo] =2 And [SNO]=[Total rows]
Then '(' + [Column Name] +')'
When [type]=0 And [SNo] >2 And [SNO]<>[Total rows]
Then  [Column Name] + ','
When [type]=0 And [SNo] >2 And [SNO]=[Total rows]
Then  [Column Name] + ')'
else Command1 end) AS [Text] from CTE
GO

Step 3 :
In this step, you need to execute the above stored procedure to recover the dropped index. Given below is the syntax.
You must supply the correct recovery dates to the stored procedure to recover proper records.

USE AdventureWorks2012
GO
EXEC [Recover_Dropped_Index_Proc] '2013/04/01','9999/12/31'
--OUTPUT

recover_dropped_index1.1

Step 4 :
Just copy the above result set and paste in the query window and execute it using correct database and you will get your indexes back in your database.

Read Full Post »

Sometimes, you feel very handicapped when you need to convert some complex data types but due to compatibility, the built-in conversion functions such as Cast, Convert, Try_Cast, Try_Convert cannot aid conversion.

How to convert float to varchar is indeed an old topic. In this article, we will solve this issue via STR function and FORMAT function introduced in SQL Server 2012.

Given below are the two methods to convert float to varchar.

Method 1:
In this method, we will use STR function to convert float to varchar and thereafter LTRIM to trim the extra spaces left in it.

--This script is compatible with SQL Server 2005 and above.
Declare @varchar as varchar(50)
Declare @float as float

Set @float =1234567.12345678
Select @float as [Float]

Set @varchar =LTRIM(STR(@float,50,8))
Select @varchar as [Float converted to varchar]
--OUTPUT

Convertfloortovarchar1.1

Method 2:
In the above method, you can notice that we used two different methods (STR, LTRIM) to convert float to varchar and to trim extra spaces. In this method we will use ONLY FORMAT function to convert float to varchar.

--This script is compatible with SQL Server 2012 and above.
Declare @varchar as varchar(50)
Declare @float as float

Set @float =1234567.12345678
Select @float as [Float]

Set @varchar =Format(@float,'#.#############')
Select @varchar as [Float converted to varchar]
--OUTPUT

convertfloattovarchar1.2

Read Full Post »

“How to find the SQL Server port number ?” has been an old topic being discussed in multiple forums. The common solution provided is using xp_instance_regread. It is one of the useful undocumented stored procedures when you need to read registry settings. In this article, I will give you two solutions. First one using xp_instance_regread and second, using sys.dm_server_registry, a new dynamic management view shipped in SQL Server 2008 R2

Method 1 : Using xp_instance_regread.
In this method we will use xp_instance_regread to find the port number.

--This script will work on SQL Server 2005 and above
DECLARE @HkeyLocal nvarchar(18)
Declare @Instance varchar(100)
DECLARE @MSSqlServerRegPath nvarchar(200)
DECLARE @PortNumber nvarchar(100)

SET @Instance ='MSSQL11.MSSQLSERVER'
SET @HkeyLocal=N'HKEY_LOCAL_MACHINE'
SET @MSSqlServerRegPath=N'SOFTWARE\Microsoft\\Microsoft SQL Server\'
+ @Instance + '\MSSQLServer\SuperSocketNetLib\Tcp\IPAll'

Print @MSSqlServerRegPath
EXEC xp_instance_regread @HkeyLocal
, @MSSqlServerRegPath
, N'TcpPort'
, @PortNumber OUTPUT
SELECT @PortNumber as [Port Number]
--OUTPUT

Port Number
————
1433

(1 row(s) affected)

Method 2 : Using using sys.dm_server_registry.
In this method we will use sys.dm_server_registry to find the port number.

--This script will work on SQL Server 2012 and above
Use master
GO
Select value_data as [Port Number]
From sys.dm_server_registry
Where registry_key like '%IPALL%' and
value_name ='TcpPort'

Port Number
————
1433

(1 row(s) affected)

Conclusion :
If you compare both methods, you will feel the difference, because the code is much optimized in the second method. Also, you can utilize the result set of second method further without using any temporary table but on the other hand you need temporary table to utilize the result set further.

Read Full Post »

How to get the day of the week ? I have been asked this question several times and we do have its solution via DATENAME function. However today we will achieve the same solution using FORMAT function, introduced in SQL Server 2012 as well. Given below are the two methods that help in identifying the day of a week in SQL Server 2005 & SQL Server 2012 respectively.
Method 1 :
Script supported in SQL Server 2005 and above :

--This script will work in SQL Server 2005 and above
Declare @Datetime as datetime
Set @Datetime =getdate()
Select DATENAME(dw , @Datetime) as [Weekday Name]
--OR
Select DATENAME(weekday, @Datetime) as [Weekday Name]
--OUTPUT

Get week day name1.1

Method 2 :
Script supported in SQL Server 2012 and above :

--This script will work in SQL Server 2012 and above
Declare @Datetime as datetime
Set @Datetime =getdate()
Select FORMAT(@Datetime,'dddd') as [Weekday Name]
--OUTPUT

Get week day name1.2

Have you come across any other method ? Do share.

Read Full Post »

Today, I was working on contained database and came across with an issue (will post this issue in my upcoming post), where I had to find a list of uncontained objects (As per MSDN, uncontained objects are basically those objects that cross the database boundaries in a contained database.)

Also, as per MSDN, given below are the objects that usually cross the boundaries of the database:

  • Unknown containment behavior (dynamic SQL or deferred name resolution)
  • DBCC command
  • System stored procedure
  • System scalar function
  • System table valued function
  • System built-in function

But it is quiet difficult, if you search for any of the above objects in the database one by one. SQL Server resolves this issue by releasing a dynamic management view (sys.dm_db_uncontained_entities) that will give you all uncontained objects of any database, in one shot.

Let me create an uncontained objects in a contained database.

--Create a stored procdure by using sys.allobjects
USE AdventureWorks2012
GO
CREATE PROC test_Procedure
AS
SELECT * FROM sys.all_objects
GO

Once you created the above stored procedure, just execute the given below script it will give you the name of above procedure along with other uncontained objects.

Use AdventureWorks2012
GO
SELECT O.name
,O.type_desc
,UCE.class_desc
,UCE.statement_type
,UCE.feature_name
,UCE.feature_type_name
FROM sys.dm_db_uncontained_entities AS UCE
LEFT JOIN sys.objects AS O
ON UCE.major_id = O.object_id
--OUTPUT

dm_db_uncontained_entities1.1-1

Note : If the above query return Nil(or emplty) it means that you donot have any uncontained objects.

Read Full Post »

« Newer Posts - Older Posts »