Feeds:
Posts
Comments

Archive for the ‘Solutions’ Category

Sometimes, it is very important to know when your database has been dropped as well who dropped it. Obviously, if you setup the database backup properly, you can easily recover it from the last backup but how to find who dropped/ deleted the database ? Today, I came across this issue and I started my research and found some solutions to recover this info using trace, however, I developed a script that will help you find who dropped database, at what time, by using SQL Server Log.

Note : Please do not use this script for any negative purpose.

Script :

--This script is compatible with SQL Server 2005 and above.
USE master
GO
DROP PROCEDURE Recover_Dropped_Database_Detail_Proc
GO
CREATE PROCEDURE Recover_Dropped_Database_Detail_Proc
@Date_From DATETIME='1900/01/01',
@Date_To DATETIME ='9999/12/31'
AS
;WITH CTE AS (
Select REPLACE(SUBSTRING(A.[RowLog Contents 0],9
,LEN(A.[RowLog Contents 0])),0x00,0x) AS [Database Name]
,[Transaction ID]
FROM fn_dblog(NULL,NULL) A
WHERE A.[AllocUnitName] ='sys.sysdbreg.nc1'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 '%dbdestroy%'
AND CONVERT(NVARCHAR(11),[Begin Time]) BETWEEN @Date_From AND @Date_To))

SELECT
A.[Database Name]
,B.[Begin Time] AS [Dropped Date & Time]
,C.[name] AS [Dropped By User Name]
FROM CTE A
INNER JOIN fn_dblog(NULL,NULL) B
ON A.[Transaction ID] =B.[Transaction ID]
AND Context IN ('LCX_NULL') AND Operation IN ('LOP_BEGIN_XACT')
AND [Transaction Name] LIKE '%dbdestroy%'
INNER JOIN sys.sysusers C ON B.[Transaction SID]=C.[Sid]

GO
EXEC Recover_Dropped_Database_Detail_Proc
GO

1

Let me know if you came across this issue and its solution as well.

Read Full Post »

On 26th May, we had a very informative session presented by Mr. Mohammed Owais (CTO at CAZAR) in SQL Server User Group meetup about Backups – not as simple as you think. He covered almost each and every aspect from full backup till tail log backup, however, a very nice question has been raised by an audience – ‘how to check the status of the backup / recovery along with the percentage via TSQL ?’. Because in most cases we have more than one DBA in an organization and sometimes they are geographically dispersed and if one of them takes backup / restore, how the others will come to know that he is performing any backup / restore using T-SQL.

Given below is the script which will give you the backup / restore progress along with the exact percentage and the user name (who is taking the backup).

USE master
GO
SELECT
A.session_id As [Session ID]
, login_name As [Login Name]
, [command] As [Command]
, [text] AS [Script]
, [start_time] As [Start Time]
, [percent_complete] AS [Percentage]
, DATEADD(SECOND,estimated_completion_time/1000, GETDATE())
as [Estimated Completion time]
, [program_name] As [Program Name]
FROM sys.dm_exec_requests A
CROSS APPLY sys.dm_exec_sql_text(A.sql_handle) B
INNER JOIN sys.dm_exec_sessions C ON A.session_id=C.session_id
WHERE A.command in ('BACKUP DATABASE','RESTORE DATABASE')
GO

1 : While Taking Backup

USE master;
GO
BACKUP DATABASE AdventureWorks2012
TO DISK = 'C:\Data\AdventureWorks2012.Bak'
WITH FORMAT,
MEDIANAME = 'SQLServerBackups',
NAME = 'Full Backup of AdventureWorks2012';
GO

raresql-Backup-Restore.1.2

2 : While Restoring Backup

USE master;
GO
RESTORE DATABASE AdventureWorks2012
FROM DISK = 'C:\Data\AdventureWorks2012.BAK'
WITH NORECOVERY
GO

raresql-Backup-Restore.1.1

Let me know if you came across this issue and its solution as well.

Read Full Post »

Paging became quite simpler & easy to script and manage by using OFFSET & FETCH NEXT keywords in SQL Server 2012 & above. I have written quite a detailed article earlier about it and implemented it in my most of the solutions wherever required. However, when you implement/use paging in your script, you face a big challenge, that is, to find the total number of records in that particular result-set.

Given below are the three methods which you can use to get the total row count from OFFSET / FETCH NEXT.
Before proceeding with the solutions, let me create a sample.

Sample :

USE AdventureWorks2014
GO
-- Create Sample Table Table
CREATE TABLE [dbo].[SalesOrderDetail](
[SalesOrderID] [int] NOT NULL,
[SalesOrderDetailID] [int] NOT NULL,
[CarrierTrackingNumber] [nvarchar](25) NULL,
[OrderQty] [smallint] NOT NULL,
[ProductID] [int] NOT NULL,
[SpecialOfferID] [int] NOT NULL,
[UnitPrice] [money] NOT NULL,
[UnitPriceDiscount] [money] NOT NULL,
[LineTotal] [numeric](38, 6) NOT NULL,
[rowguid] [uniqueidentifier] NOT NULL,
[ModifiedDate] [datetime] NOT NULL
) ON [PRIMARY]
GO

-- Insert bulk data into sample table
-- It may take few minutes depends upon the server performance
INSERT INTO [dbo].[SalesOrderDetail]
SELECT * FROM [SALES].[SalesOrderDetail]
GO 100

-- Verfiy the data
Select * from [dbo].[SalesOrderDetail]
GO

Method 1 : Using COUNT(*) OVER()

USE AdventureWorks2014
GO
DECLARE
@PageSize INT = 10,
@PageNum  INT = 1;

SELECT
[SalesOrderID]
, [SalesOrderDetailID]
, [CarrierTrackingNumber]
, [OrderQty]
, [ProductID]
, [SpecialOfferID]
, [TotalCount]= COUNT(*) OVER()
FROM [dbo].[SalesOrderDetail]
ORDER BY SalesOrderID
OFFSET (@PageNum-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
GO
--OUTPUT

row count using Offset 1.1

Method 2 : Using Common Table Expression

USE AdventureWorks2014
GO
DECLARE
@PageSize INT = 10,
@PageNum  INT = 1;

;WITH Main_CTE AS(
SELECT [SalesOrderID]
, [SalesOrderDetailID]
, [CarrierTrackingNumber]
, [OrderQty]
, [ProductID]
, [SpecialOfferID]
FROM [dbo].[SalesOrderDetail]
)
, Count_CTE AS (
SELECT COUNT(*) AS [TotalCount]
FROM Main_CTE
)
SELECT *
FROM Main_CTE, Count_CTE
ORDER BY Main_CTE.SalesOrderID
OFFSET (@PageNum-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY
GO
--OUTPUT

row count using Offset 1.1

Method 3 : Using Cross Apply

USE AdventureWorks2014
GO
DECLARE @PageSize INT = 10,
@PageNum  INT = 1;

SELECT
[SalesOrderID]
, [SalesOrderDetailID]
, [CarrierTrackingNumber]
, [OrderQty]
, [ProductID]
, [SpecialOfferID]
, [TotalCount]
FROM [dbo].[SalesOrderDetail]

CROSS APPLY (SELECT COUNT(*) TotalCount
FROM [dbo].[SalesOrderDetail] ) [Count]
ORDER BY SalesOrderID
OFFSET (@PageNum-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY
GO
--OUTPUT

row count using Offset 1.1

All of the above methods give you the same result-sets. Lets view their performance given below.

S.No

Method

CPU Time

Elapsed Time

1

COUNT(*) OVER()

30654 ms

40372 ms

2

Common Table Expression

11762 ms

7665 ms

3

Cross Apply

11794 ms

7373 ms

Conclusion :
On the basis of above results, I would recommend that you either use Common Table Expression or Cross Apply to get the faster results.

Note : The above queries have been tested on ~12 Million records.

Read Full Post »

SQL Server 2014 is shipped with lots of exciting features and enhancements, which I usually share with you in my blog from time to time. Today, I will discuss a new enhancement that will minimize your code. This enhancement is actually in the CREATE TABLE (Transact-SQL). Now you can actually create NONCLUSTERED index within the create statement and you do not need to alter table to add NONCLUSTERED index anymore. However, if you want to follow the old method, you can continue doing it. The old method has NOT been discontinued.

Given below are both methods, demonstrating the enhancement.

NEW Method : (Create NONCLUSTERED index within the create table statement)
In this method, we will create NONCLUSTERED index within create table statement. This script is compatible with SQL SERVER 2014 and above.

USE AdventureWorks2014
GO
--DROP TABLE Employee
--GO
CREATE TABLE Employee
(
[Emp_ID] int NOT NULL,
[LastName] varchar(255) NOT NULL,
[FirstName] varchar(255),
[Address] varchar(255),
[City] varchar(255),
[PostalCode] nvarchar(15),
CONSTRAINT pk_Emp_ID PRIMARY KEY ([Emp_ID]),
INDEX IX_Employee_PostalCode NONCLUSTERED (PostalCode)
);

GO
--OUTPUT

How to create a nonclustered index within the create table.1.1

OLD Method : (Create NONCLUSTERED index after creation of the table)
In this method, we will create NONCLUSTERED index AFTER table creation. This script is compatible with SQL SERVER 2005 and above.

USE AdventureWorks2012
GO
--DROP TABLE Employee
--GO
CREATE TABLE Employee
(
[Emp_ID] int NOT NULL,
[LastName] varchar(255) NOT NULL,
[FirstName] varchar(255),
[Address] varchar(255),
[City] varchar(255),
[PostalCode] nvarchar(15),
CONSTRAINT pk_Emp_ID PRIMARY KEY ([Emp_ID])
)
GO

CREATE NONCLUSTERED INDEX IX_Employee_PostalCode
ON dbo.Employee (PostalCode)
GO

How to create a nonclustered index within the create table.1.1

Conclusion
As you can see above, both methods will give you the same output, however, new method will reduce the line of code. Let me know your feedback about new enhancement.

Read Full Post »

How to convert hexadecimal to binary became very interesting when I was trying to read SQL Server log. Most part of SQL Server log data is in Hexadecimal so you need to convert it from hexadecimal to multiple formats to read it properly. Generally, programmers use the hexadecimal table to convert it into binary. But I developed this solution using remainder method and used it in almost all my solutions, wherever I used SQL Server log. Given below is the script.

Script :

--DROP FUNCTION dbo.[UDF_Convert_Hex_to_Binary]
--GO
CREATE FUNCTION dbo.[UDF_Convert_Hex_to_Binary]
(
@HEX VARBINARY(MAX)
)
RETURNS VARCHAR(MAX)
BEGIN

DECLARE @BINARY VARCHAR(MAX)

;WITH N1 (n) AS (SELECT 1 UNION ALL SELECT 1),
N2 (n) AS (SELECT 1 FROM N1 AS X, N1 AS Y),
N3 (n) AS (SELECT 1 FROM N2 AS X, N2 AS Y),
N4 (n) AS (SELECT ROW_NUMBER() OVER(ORDER BY X.n)
FROM N3 AS X, N3 AS Y)

SELECT @BINARY=ISNULL(@BINARY,'')
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 128) % 2)
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 64) % 2)
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 32) % 2)
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 16) % 2)
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 8) % 2)
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 4) % 2)
+ CONVERT(NVARCHAR(1), (SUBSTRING(@HEX, Nums.n, 1) / 2) % 2)
+ CONVERT(NVARCHAR(1), SUBSTRING(@HEX, Nums.n, 1) % 2)

FROM N4 Nums
WHERE Nums.n<=LEN(@HEX)

RETURN @BINARY
END
GO

Example :

Select dbo.[UDF_Convert_Hex_to_Binary](0x1cFEEE) AS [Hex to Binary]
GO
Select dbo.[UDF_Convert_Hex_to_Binary](0x2efd) AS [Hex to Binary]
GO
--OUTPUT

How to convert hexadecimal to binary.1.1

Read Full Post »

SQL Server Management Studio is a handy tool that gives us the control to easily manage SQL Server. However, in Azure SQL Server, you can use its own query windows, where you can pass query against database. In today’s article, I will explain how to connect Azure SQL Server using your (on premises) SQL Server Management Studio (SSMS).

Pre-Requisite :

Given below is a step by step approach, demonstrating how to CONNECT Azure SQL using SSMS in simple steps.

Step 1 : (Create SQL Server in Azure)
First of all, you need to create/ setup a Server in Azure SQL Server using pre-requisite article.

Note : If you already have Setup Azure SQL Server, skip this step.

Step 2 : (Configure IP Address)
Once you have setup the Azure SQL Server in the above step, you just need to select that particular Server then further select Configure to add your local Server IP address from where you want to connect Azure using SSMS. This step is most important step because if you bypass this step and unable to add IP address of your local Server here, Azure will not allow your SSMS to connect Azure SQL Server.

Connect Azure SQL using SSMS.1.1

Connect Azure SQL using SSMS.1.2

Note : If you already configured the IP address of your local SQL Server machine, skip this step.

Step 3 : (Open SSMS)
Lets open SQL Server Management Studio and try to connect Azure SQL Server. Given below is the info that you must pass at the time of connectivity as shown below and Press Connect Button. Make sure your caps lock key should be turned on/ off accordingly ;).

Server Name : Azure SQL Server Name.database.windows.net (gx8icm0cm.database.windows.net)
Login : The login name which we created in pre-requisite article step 3.
Password : The password which we created in pre-requisite article step 3.

Connect Azure SQL using SSMS.1.3

Step 4 : (Azure SQL Server Connected in SSMS)
Now, you have connected Azure SQL Server using SQL Server Management Studio as shown below.

Connect Azure SQL using SSMS.1.4

Read Full Post »

Remove-Duplicate-WordsI have been asked this question how to remove the duplicate words in a sentence, when my team and I were busy in messaging legacy application data and we had to migrate it to SQL Server 2012. Also, we had to check and clean the data if there was any duplicate word in a sentence. So I started scripting and checking multiple options to develop this solution including loop & XML, but I usually prefer XML. So I finally developed the solution using XML.

Before proceeding with the solution, I would like to create an example to demonstrate the solution.

--DROP TABLE tbl_Sample
--GO
CREATE TABLE tbl_Sample
(
[ID] INT IDENTITY(1,1),
[Sentence] VARCHAR(MAX)
)
GO
INSERT INTO tbl_Sample
VALUES ('This is the the test test script from from raresql.com')
GO
INSERT INTO tbl_Sample
VALUES ('This should should remove duplicates')
GO

The script of this solution is given below. and can be downloadable from here.

--DROP FUNCTION dbo.[UDF_Remove_Duplicate_Entry]
--GO
CREATE FUNCTION dbo.[UDF_Remove_Duplicate_Entry]
(
@Duplicate_Word VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
BEGIN
DECLARE @Xml XML
DECLARE @Removed_Duplicate_Word VARCHAR(MAX)
SET @Xml = CAST(('<A>'+REPLACE(@Duplicate_Word,' ','</A><A>')+'</A>') AS XML)

;WITH CTE AS (
SELECT
ROW_NUMBER() OVER(ORDER BY A) AS [Sno],
A.value('.', 'varchar(max)') AS [Column]
FROM @Xml.nodes('A') AS FN(A) )

SELECT @Removed_Duplicate_Word =(SELECT Stuff((SELECT '' + ' ' + '' + A.[Column] FROM CTE A
LEFT JOIN CTE B ON A.[Sno]+1=B.[Sno]
WHERE (A.[Column]<>B.[Column] Or B.[Sno] is NULL)
FOR XML PATH('') ),1,1,''))

RETURN @Removed_Duplicate_Word
END
GO

SELECT
[ID]
,[Sentence] As [Before Duplicate removal]
,dbo.[UDF_Remove_Duplicate_Entry]([Sentence]) As [After Duplicate removal]
FROM tbl_Sample
GO
--OUTPUT

How to remove the duplicate words in the sentence.1.1

Let me know if you come across this scenario and its solution.

Read Full Post »

In my earlier article, I explained, how to RESTORE the backup from URL using T-SQL and it was quite simple & easy to understand. In this article, I will explain how to how to RESTORE the backup from URL using SQL Server Management Studio (SSMS). It would be the same configuration but with the different screens & steps.

Pre-Requisite :

  1. Microsoft Azure – How to create storage and container
  2. SQL SERVER 2014 – How to take backup to URL (Windows Azure Storage) – SSMS

Let me now demonstrate in few easy steps how to RESTORE backup from URL.

Step 1 – Create Account, storage & container :
First of all you need to create a windows Azure account, a storage and a container as explained in this article.

Step 2 – Create Credential :
Once you have the details of Azure account, you need to create the credential using given below script. But if you notice, this script requires two parameters namely IDENTITY & SECRET. So how will I get them? Actually IDENTITY is the storage name that we created in the Pre-Requisite article -1 (Step 4) namely ‘raresql‘ and SECRET is the primary access key that we also picked up in the Pre-Requisite article -1 (Step 5). Lets create a credential.

Note: Please skip this step if you have already created the credentials.

USE master
GO
CREATE CREDENTIAL [My_Credential]
WITH IDENTITY ='raresql'
,SECRET = '/ByNUTZqJ6EcJR/VQcNmNj+zSu++iCfbcxlyWye6Ok9uY3L5nw3XkndmAnDjiKn'
GO

Step 3 – Open Windows Azure Storage dialogue box :
Once you created the credentials, the next step is to right click on the particular database you want to restore the back up and select tasks, further you need to select Restore and Database … as shown below.

How to take backup to URL (Windows Azure Storage) - SSMS.1.1

Step 4 – Connect to Windows Azure Storage :
Now, SSMS opened the Connect Windows Azure Storage dialogue box, here you need to enter storage account (Pre-Requisite article -1 (Step 4)), account key (Pre-Requisite article -1 (Step 5)) & select / create the credentials. As we have already created the credentials in the above step, we will just select the credentials and click on Connect button as shown below.

How to take backup to URL (Windows Azure Storage) - SSMS.1.2

Step 5 – RESTORE the backup from URL :
Once you click on the Connect button, it will authenticate your account with Azure, once it will be authenticated, it will open the restore dialogue box and shows your back up. Now, you can select the back and restore it as shown below.

How to take backup to URL (Windows Azure Storage) - SSMS.1.3

How to take backup to URL (Windows Azure Storage) - SSMS.1.4

How to take backup to URL (Windows Azure Storage) - SSMS.1.5

As you can see, the messages show that your backup has been restored successfully.

Read Full Post »

In my earlier articles, I explained, how to take SQL Server backup to URL using T-SQL, SQL Server Management Studio (SSMS) & PowerShell. In this article, I will explain how to RESTORE the backup from URL using T-SQL.

Pre-Requisite :

  1. Microsoft Azure – How to create storage and container
  2. SQL SERVER 2014 – How to take backup to URL (Windows Azure Storage) – TSQL

Let me now demonstrate in few easy steps how to RESTORE backup from URL.

Step 1 – Create Account, storage & container :
First of all you need to create a windows Azure account, a storage and a container as explained in this article.

Step 2 – Create Credential :
Once you have the details, you need to create the credential using given below script. But if you notice, this script requires two parameters namely IDENTITY & SECRET. So how will I get them? Actually IDENTITY is the storage name that we created in the Pre-Requisite article -1 (Step 4) namely ‘raresql‘ and SECRET is the primary access key that we also picked up in the Pre-Requisite article -1 (Step 5). Lets create a credential.

Note: Please skip this step if you have already created the credentials.

USE master
GO
CREATE CREDENTIAL [My_Credential]
WITH IDENTITY ='raresql'
,SECRET = '/ByNUTZqJ6EcJR/VQcNmNj+zSu++iCfbcxlyWye6Ok9uY3L5nw3XkndmAnDjiKn'
GO

Step 3 – RESTORE the backup from URL :
Once you created the credential, lets RESTORE the backup on URL using given below script, which requires two parameters, one is credential that we created in the above step and the second is the URL of the backup that we created in the Pre-Requisite article -2 (Step 3).

Note: Before proceeding with the Backup restore, kindly log in to your Azure account and verify the existence of the backup which URL you will mention in the below script.

USE [master]
ALTER DATABASE [AdventureWorks2012] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [AdventureWorks2012] FROM  URL = N'https://raresql.blob.core.windows.net/sql-backup/AdventureWorks2012_25_Dec_2014.bak'
WITH  CREDENTIAL = N'My_Credential'
,  FILE = 1,  NOUNLOAD,  STATS = 5
ALTER DATABASE [AdventureWorks2012] SET MULTI_USER
GO
--OUTPUT

How to RESTORE backup from URL (Windows Azure Storage) - TSQL

As you can see, the messages show that your backup has been restored successfully.

Read Full Post »

SQL Server backup to URL is a new feature shipped with SQL Server 2014. I explained how to take backup via SSMS (SQL Server Management Studio) in my earlier article. Today,  I will demonstrate how to take SQL Server backup to URL via PowerShell.

Pre-Requisite :

Let me now demonstrate in few easy steps how to take backup to URL via PowerShell.

Step 1 – Create Account, storage & container :
First of all, you need to create a windows Azure account, a storage and a container as explained in this article.

Step 2 – Take backup to URL :
Once you created the the Azure account, a storage and container, you can take a backup on URL using given below script. In this script, first of all I declared the variables , then created credentials. After that take the backup as shown below. Rest of the script is self explanatory. Make sure that you have downloaded PowerShell Extensions for SQL Server in case you are using Windows PowerShell ISE instead of Windows PowerShell.


#Import sql module
Import-Module sqlps

#Create & set variables
$serverPath = "SQLSERVER:\SQL\WIN-KK48BQM9IS0\DEFAULT"
$storageAccount = "raresql"
$storageKey = "/ByNUTZqJ6EcJR/VQcNmNj+zSu++iCfbcxlyWye6Ok9uhsd5jsd62sjhsd7ksdh7sksdsdlhsd4bsdhsd52ksd=="
$secureString = convertto-securestring $storageKey -asplaintext -force
$credentialName = "My_Credential"

# Create Credentials
New-sqlcredential -Name $credentialName -Identity $storageAccount -Secret $secureString

# Set SQL Server instance Path
CD $serverPath

# Set the backup file name
$backupFile = "https://raresql.blob.core.windows.net/sql-backup/AdventureWorks2012_25_Dec_2014.bak"

# Take Backup Database to URL
Backup-SqlDatabase -Database "AdventureWorks2012" -backupFile $backupFile -SqlCredential $credentialName -CompressionOption On

How to take backup to URL (Windows Azure Storage) - PowerShell.1.2

How to take backup to URL (Windows Azure Storage) - PowerShell1.3

Step 3 – Verify backup to URL :
Lets go to the container inside the storage and check if the backup is available there or NOT because we saw the confirmation report in the above step.

How to take backup to URL (Windows Azure Storage) - PowerShell.1.1

Now, you can see above that your backup is available on Azure, what you have taken in the above step.

Read Full Post »

« Newer Posts - Older Posts »