Recover Deleted data on Sql Server


Hi Today I will tell you how to recover the data in case data is deleted 
Please follow step by step & execute next step when first step will be finished.

Step 1 : Create a new fresh database and a table inside this database

USE master
GO

CREATE DATABASE TestDb
GO

USE TestDb
GO

CREATE TABLE TestTable (
 id INT identity(1, 1)
 ,NAME VARCHAR(50)
 ,Value INT
 ,ValueAt DATETIME DEFAULT(GetDate())
 )
GO

Step 2 : Create a Full Backup of this database

BACKUP DATABASE TestDb TO DISK = 'D:\TestDb_Full.bak'
WITH init
 ,format
 ,stats = 10
GO

Step 3 : Follow below DML On table dbo.TestTable

USE TestDb
GO

INSERT INTO TestTable ( NAME,Value)
SELECT 'Vimal' ,50
UNION
SELECT 'Kamal' ,250
UNION
SELECT 'Raj' ,1200
UNION
SELECT 'Swastika',150
UNION
SELECT 'Sibin' ,125
UNION
SELECT 'Manas' ,560
UNION
SELECT 'Amit' ,3200
GO

SELECT * FROM TestTable
GO

DELETE FROM TestTable WHERE id > 5
GO

SELECT * FROM TestTable
GO
 Step 4 : As data has been deleted. Now its time to recover that data.
Note : Here database is new & so as table. It is easy to recover. If you know the time of deleted data or approximate time you can recover data. But you will find it difficult if time range is too long or you forgot the time.
SELECT [Current LSN] ,[Transaction ID] ,[Operation] ,[Context] ,[AllocUnitName] FROM fn_dblog(NULL, NULL) WHERE [Operation] = 'LOP_DELETE_ROWS' AND [AllocUnitName] = 'dbo.TestTable' SELECT [Current LSN] ,[Operation] ,[Transaction ID] ,[Begin Time] ,[Transaction Name] ,[Transaction SID] ,[AllocUnitName] FROM fn_dblog(NULL, NULL) WHERE [Transaction ID] = '0000:00000343'--<<Paste the TransactionID AND [Operation] = 'LOP_BEGIN_XACT'
--Copy CurrentLSN 00000021:000000b0:0001
SELECT CONVERT(INT, CONVERT(VARBINARY, '0x00000021', 1)) --Same Value
SELECT CONVERT(INT, CONVERT(VARBINARY, '0x000000b0', 1)) --Total 10 digit preceeded by 0
SELECT CONVERT(INT, CONVERT(VARBINARY, '0x0001', 1)) --Total 5 digit preceeded by 0

-->33000000017600001
SELECT Cast(CONVERT(INT, CONVERT(VARBINARY, '0x00000021', 1)) AS VARCHAR(5)) + RIGHT('0000000000' + CAST(CONVERT(INT, CONVERT(VARBINARY, '0x000000b0', 1)) AS NVARCHAR), 10) + RIGHT('00000' + CAST(CONVERT(INT, CONVERT(VARBINARY, '0x0001', 1)) AS NVARCHAR), 5) AS 'MarkPoint'
GO

Step 5 : Take a log backup now. For this recovery model of database should be Full or Bulk-logged(Right click on Database>>Properties>>Options>>Recovery Model)

BACKUP log TestDb TO DISK = 'D:\TestDb_log.trn'
GO

Step 6 : Restore Full backup of database

-- Starting first with restoring the FULL BACKUP with NORECOVERY RESTORE filelistonly FROM DISK = 'D:\TestDb_Full.bak'; RESTORE DATABASE [TestDb_New] FROM DISK = 'D:\TestDb_Full.bak' WITH MOVE 'TestDb' TO 'C:\TestDb.mdf' ,MOVE 'TestDb_log' TO 'C:\TestDb_log.ldf' ,REPLACE ,NORECOVERY; GO

Step 7 : Restore log backup of database like below

RESTORE LOG TestDb_New FROM DISK = 'D:\TestDb_log.trn' WITH STOPBEFOREMARK = 'lsn:33000000017600001' GO

Step 8 : Check the table data

USE TestDb_New
GO
SELECT * FROM dbo.TestTable
--Export the deleted rows from this table to original table

Step 9 : Drop tables

USE master
GO
DROP DATABASE TestDb
DROP DATABASE TestDb_New
-->The End<--

Note : Step 4 time range
SELECT [Current LSN]
 ,[Operation]
 ,[Transaction ID]
 ,[Begin Time]
 ,[Transaction Name]
 ,[Transaction SID]
 ,[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE --[Operation] = 'LOP_BEGIN_XACT'
 --and 
 [Begin Time] BETWEEN '2015/07/17 15:30:00:000'
  AND '2015/07/17 16:00:00:000'


Store a file & Retrive it in Sql Server


/* 
Created By : Vimal Lohani on 12-May-2015
*/
--Create Table 
create table #FileSaveTest (Files varbinary(max), name varchar(200))





--Insert file & information
insert into #FileSaveTest (Files, name)
select img.*, 'abc.jpg'
from openrowset(bulk 'D:\b\abc.jpg', Single_Blob) img

--Show table data
select *
from #FileSaveTest







--Configure advance options
sp_configure 'show advanced options', 1;
go

reconfigure;
go

sp_configure 'Ole Automation Procedures', 1;
go

reconfigure;
go

--Retrieve file at a location (Path)   
declare @FileData varbinary(max);

select @FileData = (
  select convert(varbinary(max), Files, 1)
  from #FileSaveTest
  );

declare @Path nvarchar(200)

select @Path = 'D:\a a\';

declare @Filename nvarchar(1024);

select @Filename = (
  select name
  from #FileSaveTest
  );

declare @FullPathToOutputFile nvarchar(2048);

select @FullPathToOutputFile = @Path + '\' + @Filename;

declare @ObjectToken int

exec sp_OACreate 'ADODB.Stream', @ObjectToken output;

exec sp_OASetProperty @ObjectToken, 'Type', 1;

exec sp_OAMethod @ObjectToken, 'Open';

exec sp_OAMethod @ObjectToken, 'Write', null, @FileData;

exec sp_OAMethod @ObjectToken, 'SaveToFile', null, @FullPathToOutputFile, 2;

exec sp_OAMethod @ObjectToken, 'Close';

exec sp_OADestroy @ObjectToken;



















sp_configure 'Ole Automation Procedures', 0;
go

reconfigure;
go

sp_configure 'show advanced options', 0;
go

reconfigure;
go

--Drop table
drop table #FileSaveTest

Detach & Attach Procedure


/*
-->Created By- Vimal Lohani on 30-APR-2015
-->For successful run, Your sql server service account should have permission to old location & new location
-->Exec uspDetachAttach @DbName=<Database Name>, @NewLocationPath=<new Location for database like 'D:\Data'>
*/
CREATE PROCEDURE uspDetachAttach @DbName VARCHAR(200)
 ,@NewLocationPath VARCHAR(2000)
AS
BEGIN
 SET NOCOUNT ON

 DECLARE @Sql VARCHAR(max)
 DECLARE @OldLocation VARCHAR(2000)
 DECLARE @Size FLOAT
 DECLARE @max INT

 --Getting Database & Drive information
 SELECT ROW_NUMBER() OVER (
   ORDER BY fs.database_id
   ) 'RowNo'
  ,fs.database_id
  ,fs.size * 8.0 / 1024 size
  ,fs.physical_name 'OldLocation'
  ,reverse(left(reverse(fs.physical_name), charindex('\', reverse(fs.physical_name)) - 1)) 'FileName'
 INTO #temp
 FROM sys.databases db
 INNER JOIN sys.master_files fs ON fs.database_id = db.database_id
 WHERE fs.database_id NOT IN (
   1
   ,2
   ,3
   ,4
   ) --Not considered system databases
  AND db.NAME = @DbName

 SELECT @max = max(RowNo)
 FROM #temp

 IF (
   (
    SELECT Count(*)
    FROM #temp
    ) = 0
   )
 BEGIN
  PRINT 'database not exist so return'

  RETURN
 END
 ELSE
 BEGIN
  SELECT @Size = Sum(Size)
  FROM #temp

  DECLARE @drive TABLE (
   drive VARCHAR(2)
   ,MBfree FLOAT
   )

  INSERT INTO @drive
  EXEC master..xp_fixeddrives

  --Select * from @drive
  IF (
    (
     SELECT MBfree
     FROM @drive
     WHERE drive = SUBSTRING(@NewLocationPath, 1, 1)
     ) < (
     SELECT @Size
     )
    )
  BEGIN
   PRINT 'Size not available so return'

   RETURN
  END
  ELSE
  BEGIN
   --Detach database files
   SET @Sql = 'USE MASTER;
           ALTER DATABASE ' + @DbName + '
           SET SINGLE_USER
           WITH ROLLBACK IMMEDIATE;
           EXEC MASTER.dbo.sp_detach_db @dbname = N''' + @DbName + '''
           '

   EXEC (@Sql)

   -- Move MDF File from Loc1 to Loc 2
   DECLARE @file VARCHAR(2000)

   EXEC master.dbo.sp_configure 'show advanced options'
    ,1

   RECONFIGURE

   EXEC master.dbo.sp_configure 'xp_cmdshell'
    ,1

   RECONFIGURE

   IF ((Substring(REVERSE(@NewLocationPath), 1, 1)) <> '\')
    SET @NewLocationPath = @NewLocationPath + '\'
   SET @NewLocationPath = @NewLocationPath + @DbName + '\'

   EXEC master.dbo.xp_create_subdir @NewLocationPath

   WHILE (@max > 0)
   BEGIN
    SELECT @file = 'move "' + Cast(OldLocation AS VARCHAR(1000))
    FROM #temp
    WHERE RowNo = @max

    SELECT @file = @file + '" "' + @NewLocationPath + (
      SELECT FileName
      FROM #temp
      WHERE RowNo = @max
      )

    SET @file = @file + '"'

    PRINT @file

    EXEC master.dbo.xp_cmdshell @file

    SET @file = ''
    SET @max = @max - 1
   END

   -- Re-Attached DB
   SELECT @file = IsNull(@file, '') + '( FILENAME = N''' + @NewLocationPath + '' + FileName + ''' ),'
   FROM #temp

   SELECT @file = 'CREATE DATABASE ' + @DbName + ' ON ' + SUBSTRING(@file, 1, LEN(@file) - 1) + 'FOR ATTACH'

   PRINT @file

   EXEC (@file)

   SET @file = 'ALTER DATABASE ' + @DbName + ' SET MULTI_USER;'

   EXEC (@file)

   EXEC master.dbo.sp_configure 'xp_cmdshell'
    ,0

   RECONFIGURE

   EXEC master.dbo.sp_configure 'show advanced options'
    ,0

   RECONFIGURE
  END
 END

 DROP TABLE #temp
END

Comma separated values from sql table :

--Create temp table & Insert data-----
Create table #temp(id int, tech nvarchar(10))
Insert into #temp(id,tech) values(12, 'c#'),(12,'java'),(13,'sql'),(13,'Oracle'),(13,'Mysql'),(15,'hadoop')
Select * from #temp
--------------------------------------
--Process data------------------------
;WITH cte AS
(
SELECT DISTINCT id 
FROM #temp
)
SELECT Id, STUFF((SELECT ', ' + CAST(t2.tech AS NVARCHAR(MAX))
     FROM #temp t2 WHERE t1.ID = t2.ID
     FOR XML PATH('')),1,1,'') skills
into #temp1
FROM cte t1
--Getting Result---------------------
Select * from #temp1
--Drop temp tables-------------------
Drop table #temp
Drop table #temp1
-------------------------------------



sp_MSforeachtable Stored Procedure

sp_MSforeachtable stored procedure provided by Microsoft, is used for smooth processing on all tables of a single database. So why to use complex query when we have already that procedure.

How and when to use sp_MSFooreachtable :

Parameters
sp_MSforeachtable @command1, @replacechar, @command2,  @command3, @whereand, @precommand, @postcommand

  • @command1 nvarchar(2000) – is the first command to be executed
  • @replacechar nchar(1) – is a character in the command string that will be replaced with the table name being processed (default character is “?”)
  • @command2 nvarchar(2000)-  additional command that can be run for each table. It runs after @ command1
  • @command2 nvarchar(2000)-  another additional command that can be run for each table. It runs after @ comman2
  • @whereand nvarchar(2000)- you can specify the where clause in this parameter
  • @precommand nvarchar(2000) -  specifies a command to be run prior to processing any table
  • @postcommand nvarchar(2000)- command to be executed  after all commands have been processed
Eg 1 : Retriving all tables starting with 'c' and their row count

CREATE TABLE  #rowcount (tablename varchar(128), cnt int)
EXEC sp_MSforeachtable
 @command1 = 'Insert into #rowcount select ''?'',
              count(*) from ?',
 @whereand = 'and o.name like ''p%''',
 @postcommand = 'SELECT * from #rowcount'

DROP TABLE  #rowcount

Eg 2:  Disabling all constraints on all tables
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
Eg 3:  Enabling all constraints on all tables

EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
Eg 4:  Deleting rows from all tables

EXEC sp_MSForEachTable 'DELETE FROM ?'
Eg 5:  Reseed identity column

If any table doesn't contain identity column, it raise error and as a quality of stored procedure it will move on


EXEC sp_MSforeachtable 'DBCC CHECKIDENT ( ''?'', RESEED, 0)'


Eg 6:   Rebuild clustered index/all non clusted indexes on all the tables


EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD WITH (ONLINE=OFF)'

Find only characters or only integer from alphanumeric value :

Find only characters from string :

DECLARE @Temp VARCHAR(100)='548STA123Ldfgh45df45df5446fg54645dfg546';
Declare @NumRange AS varchar(50) = '%[0-9]%';
    While PatIndex(@NumRange, @Temp) > 0
        SET @Temp = Stuff(@Temp, PatIndex(@NumRange, @Temp), 1 ,'')

 SELECT @Temp

====================================

Find only integers from string :

DECLARE @var VARCHAR(100)='5STA123Ldfgh45df45df5446fg54645dfg546';
DECLARE @intdata INT
SET @intdata = PATINDEX('%[^0-9]%', @var)
BEGIN
WHILE @intdata > 0
BEGIN
SET @var = STUFF(@var, @intdata, 1, '' )
SET @intdata = PATINDEX('%[^0-9]%', @var )
END
END

Select ISNULL(@var,0)

Find a float value from string :

DECLARE @var VARCHAR(100)='STA123.26dfg';
DECLARE @intdata INT
SET @intdata = PATINDEX('%[^0-9]%', @var)
BEGIN
WHILE @intdata > 0
BEGIN
SET @var = STUFF(@var, @intdata, 1, '' )
SET @intdata = PATINDEX('%[^0-9.]%', @var )
END
END

Select ISNULL(@var,0)

=====================================