恢复SQL Server被误删除的数据(再扩展)

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 原文:恢复SQL Server被误删除的数据(再扩展)恢复SQL Server被误删除的数据(再扩展)   大家对本人之前的文章《恢复SQL Server被误删除的数据》 反应非常热烈,但是文章里的存储过程不能实现对备份出来的日志备份里所删数据的恢复 这个是一个缺陷,本人决定对这个存储过程扩...
原文: 恢复SQL Server被误删除的数据(再扩展)

恢复SQL Server被误删除的数据(再扩展)

 

大家对本人之前的文章《恢复SQL Server被误删除的数据》 反应非常热烈,但是文章里的存储过程不能实现对备份出来的日志备份里所删数据的恢复

这个是一个缺陷,本人决定对这个存储过程扩展一下,支持对log backup文件里的delete语句进行恢复

 

实验步骤

 

1、首先先准备好测试表和测试语句

USE [sss]
GO

--建表
CREATE TABLE testdelete
    (
      id INT IDENTITY(1, 1)
             NOT NULL
             PRIMARY KEY ,
      NAME VARCHAR(200) ,
      dt DATETIME
    )


--插入数据
INSERT  [dbo].[testdelete]
        ( [NAME], [dt] )
VALUES  ( 'aa', -- NAME - varchar(200)
          '2015-07-04 07:06:40'  -- dt - datetime
          )




SELECT  *  FROM    [dbo].[testdelete]


--删除数据
DELETE  FROM [dbo].[testdelete]

 

2、删除数据之后对数据库进行日志备份

DECLARE @CurrentTime VARCHAR(50) ,
    @FileName VARCHAR(200)
SET @CurrentTime = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR, GETDATE(), 120),
                                           '-', '_'), ' ', '_'), ':', '')  
SET @FileName = 'c:\sss_logBackup_' + @CurrentTime + '.bak'
BACKUP LOG  [sss]
TO DISK=@FileName WITH FORMAT 

 

4、建立存储过程

-- Script Name: Recover_Deleted_Data_BylogBackup_Proc
-- Script Type : Recovery Procedure 
-- Develop By: Steven Lam
-- Date Created: 03 July  2015
-- Version    : 1.0
-- Notes : Included BLOB data types for recovery.& Compatibile with Default , CS collation , Arabic_CI_AS.
 
USE [sss]
GO


CREATE PROCEDURE Recover_Deleted_Data_BylogBackup_Proc
    @Database_Name NVARCHAR(MAX) ,
    @SchemaName_n_TableName NVARCHAR(MAX) ,
    @Backuppath NVARCHAR(2000),
    @Date_From DATETIME = '1900/01/01' ,
    @Date_To DATETIME = '9999/12/31' 
   
AS
    DECLARE @RowLogContents VARBINARY(8000)
    DECLARE @TransactionID NVARCHAR(MAX)
    DECLARE @AllocUnitID BIGINT
    DECLARE @AllocUnitName NVARCHAR(MAX)
    DECLARE @SQL NVARCHAR(MAX)
    DECLARE @Compatibility_Level INT

    IF ( @Backuppath IS NULL
         OR @Backuppath = ''
       )
        BEGIN
            RAISERROR('The parameter @Backuppath can not be null!',16,1)
            RETURN
        END


 
    SELECT  @Compatibility_Level = dtb.compatibility_level
    FROM    master.sys.databases AS dtb
    WHERE   dtb.name = @Database_Name
 
    IF ISNULL(@Compatibility_Level, 0) <= 80
        BEGIN
            RAISERROR('The compatibility level should be equal to or greater SQL SERVER 2005 (90)',16,1)
            RETURN
        END
 
    IF ( SELECT COUNT(*)
         FROM   INFORMATION_SCHEMA.TABLES
         WHERE  [TABLE_SCHEMA] + '.' + [TABLE_NAME] = @SchemaName_n_TableName
       ) = 0
        BEGIN
            RAISERROR('Could not found the table in the defined database',16,1)
            RETURN
        END
 
    DECLARE @bitTable TABLE
        (
          [ID] INT ,
          [Bitvalue] INT
        )
--Create table to set the bit position of one byte.
 
    INSERT  INTO @bitTable
            SELECT  0 ,
                    2
            UNION ALL
            SELECT  1 ,
                    2
            UNION ALL
            SELECT  2 ,
                    4
            UNION ALL
            SELECT  3 ,
                    8
            UNION ALL
            SELECT  4 ,
                    16
            UNION ALL
            SELECT  5 ,
                    32
            UNION ALL
            SELECT  6 ,
                    64
            UNION ALL
            SELECT  7 ,
                    128
 
--Create table to collect the row data.
    DECLARE @DeletedRecords TABLE
        (
          [Row ID] INT IDENTITY(1, 1) ,
          [RowLogContents] VARBINARY(8000) ,
          [AllocUnitID] BIGINT ,
          [Transaction ID] NVARCHAR(MAX) ,
          [FixedLengthData] SMALLINT ,
          [TotalNoOfCols] SMALLINT ,
          [NullBitMapLength] SMALLINT ,
          [NullBytes] VARBINARY(8000) ,
          [TotalNoofVarCols] SMALLINT ,
          [ColumnOffsetArray] VARBINARY(8000) ,
          [VarColumnStart] SMALLINT ,
          [Slot ID] INT ,
          [NullBitMap] VARCHAR(MAX)
        )
--Create a common table expression to get all the row data plus how many bytes we have for each row.
;
    WITH    RowData
              AS ( SELECT   [RowLog Contents 0] AS [RowLogContents] ,
                            [AllocUnitID] AS [AllocUnitID] ,
                            [Transaction ID] AS [Transaction ID]  
 
--[Fixed Length Data] = Substring (RowLog content 0, Status Bit A+ Status Bit B + 1,2 bytes)
                            ,
                            CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) AS [FixedLengthData]  --@FixedLengthData
 
-- [TotalnoOfCols] =  Substring (RowLog content 0, [Fixed Length Data] + 1,2 bytes)
                            ,
                            CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) AS [TotalNoOfCols]
 
--[NullBitMapLength]=ceiling([Total No of Columns] /8.0)
                            ,
                            CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0)) AS [NullBitMapLength] 
 
--[Null Bytes] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [NullBitMapLength] )
                            ,
                            SUBSTRING([RowLog Contents 0],
                                      CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 3,
                                      CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0))) AS [NullBytes]
 
--[TotalNoofVarCols] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 )
                            ,
                            ( CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN (
                                        0x10, 0x30, 0x70 )
                                   THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 3
                                                              + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0)), 2))))
                                   ELSE NULL
                              END ) AS [TotalNoofVarCols] 
 
--[ColumnOffsetArray]= Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 , [TotalNoofVarCols]*2 )
                            ,
                            ( CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN (
                                        0x10, 0x30, 0x70 )
                                   THEN SUBSTRING([RowLog Contents 0],
                                                  CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 3
                                                  + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0))
                                                  + 2,
                                                  ( CASE WHEN SUBSTRING([RowLog Contents 0],
                                                              1, 1) IN ( 0x10,
                                                              0x30, 0x70 )
                                                         THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 3
                                                              + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0)), 2))))
                                                         ELSE NULL
                                                    END ) * 2)
                                   ELSE NULL
                              END ) AS [ColumnOffsetArray] 
 
--  Variable column Start = Status Bit A+ Status Bit B + [Fixed Length Data] + [Null Bitmap length] + 2+([TotalNoofVarCols]*2)
                            ,
                            CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN (
                                      0x10, 0x30, 0x70 )
                                 THEN ( CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 4
                                        + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0))
                                        + ( ( CASE WHEN SUBSTRING([RowLog Contents 0],
                                                              1, 1) IN ( 0x10,
                                                              0x30, 0x70 )
                                                   THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 3
                                                              + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              2 + 1, 2)))) + 1,
                                                              2)))) / 8.0)), 2))))
                                                   ELSE NULL
                                              END ) * 2 ) )
                                 ELSE NULL
                            END AS [VarColumnStart] ,
                            [Slot ID]
                   FROM     fn_dump_dblog(NULL, NULL, N'DISK', 1, @Backuppath,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT)
                   WHERE    AllocUnitId IN (
                            SELECT  [Allocation_unit_id]
                            FROM    sys.allocation_units allocunits
                                    INNER JOIN sys.partitions partitions ON ( allocunits.type IN (
                                                              1, 3 )
                                                              AND partitions.hobt_id = allocunits.container_id
                                                              )
                                                              OR ( allocunits.type = 2
                                                              AND partitions.partition_id = allocunits.container_id
                                                              )
                            WHERE   object_id = OBJECT_ID(''
                                                          + @SchemaName_n_TableName
                                                          + '') )
                            AND Context IN ( 'LCX_MARK_AS_GHOST', 'LCX_HEAP' )
                            AND Operation IN ( 'LOP_DELETE_ROWS' )
                            AND SUBSTRING([RowLog Contents 0], 1, 1) IN ( 0x10,
                                                              0x30, 0x70 )
 
/*Use this subquery to filter the date*/
                            AND [TRANSACTION ID] IN (
                            SELECT DISTINCT
                                    [TRANSACTION ID]
                            FROM    fn_dump_dblog(NULL, NULL, N'DISK', 1,
                                                  @Backuppath, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT, DEFAULT,
                                                  DEFAULT, DEFAULT)
                            WHERE   Context IN ( 'LCX_NULL' )
                                    AND Operation IN ( 'LOP_BEGIN_XACT' )
                                    AND [Transaction Name] IN ( 'DELETE',
                                                              'user_transaction' )
                                    AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN @Date_From
                                                              AND
                                                              @Date_To )
                 ),
 
--Use this technique to repeate the row till the no of bytes of the row.
            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
                 )
        INSERT  INTO @DeletedRecords
                SELECT  RowLogContents ,
                        [AllocUnitID] ,
                        [Transaction ID] ,
                        [FixedLengthData] ,
                        [TotalNoOfCols] ,
                        [NullBitMapLength] ,
                        [NullBytes] ,
                        [TotalNoofVarCols] ,
                        [ColumnOffsetArray] ,
                        [VarColumnStart] ,
                        [Slot ID]
         ---Get the Null value against each column (1 means null zero means not null)
                        ,
                        [NullBitMap] = ( REPLACE(STUFF(( SELECT
                                                              ','
                                                              + ( CASE
                                                              WHEN [ID] = 0
                                                              THEN CONVERT(NVARCHAR(1), ( SUBSTRING(NullBytes,
                                                              n, 1) % 2 ))
                                                              ELSE CONVERT(NVARCHAR(1), ( ( SUBSTRING(NullBytes,
                                                              n, 1)
                                                              / [Bitvalue] )
                                                              % 2 ))
                                                              END ) --as [nullBitMap]
                                                         FROM N4 AS Nums
                                                              JOIN RowData AS C ON n <= NullBitMapLength
                                                              CROSS JOIN @bitTable
                                                         WHERE
                                                              C.[RowLogContents] = D.[RowLogContents]
                                                         ORDER BY [RowLogContents] ,
                                                              n ASC
                                                       FOR
                                                         XML PATH('')
                                                       ), 1, 1, ''), ',', '') )
                FROM    RowData D
 
    IF ( SELECT COUNT(*)
         FROM   @DeletedRecords
       ) = 0
        BEGIN
            RAISERROR('There is no data in the log as per the search criteria',16,1)
            RETURN
        END
 
    DECLARE @ColumnNameAndData TABLE
        (
          [Row ID] INT ,
          [Rowlogcontents] VARBINARY(MAX) ,
          [NAME] SYSNAME ,
          [nullbit] SMALLINT ,
          [leaf_offset] SMALLINT ,
          [length] SMALLINT ,
          [system_type_id] TINYINT ,
          [bitpos] TINYINT ,
          [xprec] TINYINT ,
          [xscale] TINYINT ,
          [is_null] INT ,
          [Column value Size] INT ,
          [Column Length] INT ,
          [hex_Value] VARBINARY(MAX) ,
          [Slot ID] INT ,
          [Update] INT
        )
 
--Create common table expression and join it with the rowdata table
-- to get each column details
/*This part is for variable data columns*/
--@RowLogContents, 
--(col.columnOffValue - col.columnLength) + 1,
--col.columnLength
--)
    INSERT  INTO @ColumnNameAndData
            SELECT  [Row ID] ,
                    Rowlogcontents ,
                    NAME ,
                    cols.leaf_null_bit AS nullbit ,
                    leaf_offset ,
                    ISNULL(syscolumns.length, cols.max_length) AS [length] ,
                    cols.system_type_id ,
                    cols.leaf_bit_position AS bitpos ,
                    ISNULL(syscolumns.xprec, cols.precision) AS xprec ,
                    ISNULL(syscolumns.xscale, cols.scale) AS xscale ,
                    SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null ,
                    ( CASE WHEN leaf_offset < 1
                                AND SUBSTRING([nullBitMap], cols.leaf_null_bit,
                                              1) = 0
                           THEN ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                       THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                            - POWER(2, 15)
                                       ELSE CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                  END )
                      END ) AS [Column value Size] ,
                    ( CASE WHEN leaf_offset < 1
                                AND SUBSTRING([nullBitMap], cols.leaf_null_bit,
                                              1) = 0
                           THEN ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                            AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                       [varColumnStart]) < 30000
                                       THEN ( CASE WHEN [System_type_id] IN (
                                                        35, 34, 99 ) THEN 16
                                                   ELSE 24
                                              END )
                                       WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                            AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                       [varColumnStart]) > 30000
                                       THEN ( CASE WHEN [System_type_id] IN (
                                                        35, 34, 99 ) THEN 16
                                                   ELSE 24
                                              END ) --24 
                                       WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) < 30000
                                            AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                       [varColumnStart]) < 30000
                                       THEN ( CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                              - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                       [varColumnStart]) )
                                       WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) < 30000
                                            AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                       [varColumnStart]) > 30000
                                       THEN POWER(2, 15)
                                            + CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                            - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                     [varColumnStart])
                                  END )
                      END ) AS [Column Length] ,
                    ( CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) = 1
                           THEN NULL
                           ELSE SUBSTRING(Rowlogcontents,
                                          ( ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                                   THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                                        - POWER(2, 15)
                                                   ELSE CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                              END )
                                            - ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                                          AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) < 30000
                                                     THEN ( CASE
                                                              WHEN [System_type_id] IN (
                                                              35, 34, 99 )
                                                              THEN 16
                                                              ELSE 24
                                                            END ) --24 
                                                     WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                                          AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) > 30000
                                                     THEN ( CASE
                                                              WHEN [System_type_id] IN (
                                                              35, 34, 99 )
                                                              THEN 16
                                                              ELSE 24
                                                            END ) --24 
                                                     WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) < 30000
                                                          AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) < 30000
                                                     THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                                          - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart])
                                                     WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) < 30000
                                                          AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) > 30000
                                                     THEN POWER(2, 15)
                                                          + CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                                          - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart])
                                                END ) ) + 1,
                                          ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                                      AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) < 30000
                                                 THEN ( CASE WHEN [System_type_id] IN (
                                                              35, 34, 99 )
                                                             THEN 16
                                                             ELSE 24
                                                        END ) --24 
                                                 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) > 30000
                                                      AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) > 30000
                                                 THEN ( CASE WHEN [System_type_id] IN (
                                                              35, 34, 99 )
                                                             THEN 16
                                                             ELSE 24
                                                        END ) --24 
                                                 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) < 30000
                                                      AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) < 30000
                                                 THEN ABS(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                                          - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]))
                                                 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2)))) < 30000
                                                      AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart]) > 30000
                                                 THEN POWER(2, 15)
                                                      + CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * leaf_offset
                                                              * -1 ) - 1, 2))))
                                                      - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],
                                                              ( 2
                                                              * ( ( leaf_offset
                                                              * -1 ) - 1 ) )
                                                              - 1, 2)))), 0),
                                                              [varColumnStart])
                                            END ))
                      END ) AS hex_Value ,
                    [Slot ID] ,
                    0
            FROM    @DeletedRecords A
                    INNER JOIN sys.allocation_units allocunits ON A.[AllocUnitId] = allocunits.[Allocation_Unit_Id]
                    INNER JOIN sys.partitions partitions ON ( allocunits.type IN (
                                                              1, 3 )
                                                              AND partitions.hobt_id = allocunits.container_id
                                                            )
                                                            OR ( allocunits.type = 2
                                                              AND partitions.partition_id = allocunits.container_id
                                                              )
                    INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_id
                    LEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_id
                                                  AND syscolumns.colid = cols.partition_column_id
            WHERE   leaf_offset < 0
            UNION
/*This part is for fixed data columns*/
            SELECT  [Row ID] ,
                    Rowlogcontents ,
                    NAME ,
                    cols.leaf_null_bit AS nullbit ,
                    leaf_offset ,
                    ISNULL(syscolumns.length, cols.max_length) AS [length] ,
                    cols.system_type_id ,
                    cols.leaf_bit_position AS bitpos ,
                    ISNULL(syscolumns.xprec, cols.precision) AS xprec ,
                    ISNULL(syscolumns.xscale, cols.scale) AS xscale ,
                    SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null ,
                    ( SELECT TOP 1
                                ISNULL(SUM(CASE WHEN C.leaf_offset > 1
                                                THEN max_length
                                                ELSE 0
                                           END), 0)
                      FROM      sys.system_internals_partition_columns C
                      WHERE     cols.partition_id = C.partition_id
                                AND C.leaf_null_bit < cols.leaf_null_bit
                    ) + 5 AS [Column value Size] ,
                    syscolumns.length AS [Column Length] ,
                    CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) = 1
                         THEN NULL
                         ELSE SUBSTRING(Rowlogcontents,
                                        ( SELECT TOP 1
                                                    ISNULL(SUM(CASE
                                                              WHEN C.leaf_offset > 1
                                                              AND C.leaf_bit_position = 0
                                                              THEN max_length
                                                              ELSE 0
                                                              END), 0)
                                          FROM      sys.system_internals_partition_columns C
                                          WHERE     cols.partition_id = C.partition_id
                                                    AND C.leaf_null_bit < cols.leaf_null_bit
                                        ) + 5, syscolumns.length)
                    END AS hex_Value ,
                    [Slot ID] ,
                    0
            FROM    @DeletedRecords A
                    INNER JOIN sys.allocation_units allocunits ON A.[AllocUnitId] = allocunits.[Allocation_Unit_Id]
                    INNER JOIN sys.partitions partitions ON ( allocunits.type IN (
                                                              1, 3 )
                                                              AND partitions.hobt_id = allocunits.container_id
                                                            )
                                                            OR ( allocunits.type = 2
                                                              AND partitions.partition_id = allocunits.container_id
                                                              )
                    INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_id
                    LEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_id
                                                  AND syscolumns.colid = cols.partition_column_id
            WHERE   leaf_offset > 0
            ORDER BY nullbit
 
    DECLARE @BitColumnByte AS INT
    SELECT  @BitColumnByte = CONVERT(INT, CEILING(COUNT(*) / 8.0))
    FROM    @ColumnNameAndData
    WHERE   [System_Type_id] = 104;
    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
                 ),
            CTE
              AS ( SELECT   RowLogContents ,
                            [nullbit] ,
                            [BitMap] = CONVERT(VARBINARY(1), CONVERT(INT, SUBSTRING(( REPLACE(STUFF(( SELECT
                                                              ','
                                                              + ( CASE
                                                              WHEN [ID] = 0
                                                              THEN CONVERT(NVARCHAR(1), ( SUBSTRING(hex_Value,
                                                              n, 1) % 2 ))
                                                              ELSE CONVERT(NVARCHAR(1), ( ( SUBSTRING(hex_Value,
                                                              n, 1)
                                                              / [Bitvalue] )
                                                              % 2 ))
                                                              END ) --as [nullBitMap]
                                                              FROM
                                                              N4 AS Nums
                                                              JOIN @ColumnNameAndData
                                                              AS C ON n <= @BitColumnByte
                                                              AND [System_Type_id] = 104
                                                              AND bitpos = 0
                                                              CROSS JOIN @bitTable
                                                              WHERE
                                                              C.[RowLogContents] = D.[RowLogContents]
                                                              ORDER BY [RowLogContents] ,
                                                              n ASC
                                                              FOR
                                                              XML
                                                              PATH('')
                                                              ), 1, 1, ''),
                                                              ',', '') ),
                                                              bitpos + 1, 1)))
                   FROM     @ColumnNameAndData D
                   WHERE    [System_Type_id] = 104
                 )
        UPDATE  A
        SET     [hex_Value] = [BitMap]
        FROM    @ColumnNameAndData A
                INNER JOIN CTE B ON A.[RowLogContents] = B.[RowLogContents]
                                    AND A.[nullbit] = B.[nullbit]
 
 
/**************Check for BLOB DATA TYPES******************************/
    DECLARE @Fileid INT
    DECLARE @Pageid INT
    DECLARE @Slotid INT
    DECLARE @CurrentLSN INT
    DECLARE @LinkID INT
    DECLARE @Context VARCHAR(50)
    DECLARE @ConsolidatedPageID VARCHAR(MAX)
    DECLARE @LCX_TEXT_MIX VARBINARY(MAX)
 
    DECLARE @temppagedata TABLE
        (
          [ParentObject] SYSNAME ,
          [Object] SYSNAME ,
          [Field] SYSNAME ,
          [Value] SYSNAME
        )
 
    DECLARE @pagedata TABLE
        (
          [Page ID] SYSNAME ,
          [File IDS] INT ,
          [Page IDS] INT ,
          [AllocUnitId] BIGINT ,
          [ParentObject] SYSNAME ,
          [Object] SYSNAME ,
          [Field] SYSNAME ,
          [Value] SYSNAME
        )
 
    DECLARE @ModifiedRawData TABLE
        (
          [ID] INT IDENTITY(1, 1) ,
          [PAGE ID] VARCHAR(MAX) ,
          [FILE IDS] INT ,
          [PAGE IDS] INT ,
          [Slot ID] INT ,
          [AllocUnitId] BIGINT ,
          [RowLog Contents 0_var] VARCHAR(MAX) ,
          [RowLog Length] VARCHAR(50) ,
          [RowLog Len] INT ,
          [RowLog Contents 0] VARBINARY(MAX) ,
          [Link ID] INT DEFAULT ( 0 ) ,
          [Update] INT
        )
 
    DECLARE Page_Data_Cursor CURSOR
    FOR
        /*We need to filter LOP_MODIFY_ROW,LOP_MODIFY_COLUMNS from log for deleted records of BLOB data type& Get its Slot No, Page ID & AllocUnit ID*/
            SELECT  LTRIM(RTRIM(REPLACE([Description], 'Deallocated', ''))) AS [PAGE ID] ,
                    [Slot ID] ,
                    [AllocUnitId] ,
                    NULL AS [RowLog Contents 0] ,
                    NULL AS [RowLog Contents 0] ,
                    Context
            FROM    fn_dump_dblog(NULL, NULL, N'DISK', 1, @Backuppath, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT)
            WHERE   AllocUnitId IN (
                    SELECT  [Allocation_unit_id]
                    FROM    sys.allocation_units allocunits
                            INNER JOIN sys.partitions partitions ON ( allocunits.type IN (
                                                              1, 3 )
                                                              AND partitions.hobt_id = allocunits.container_id
                                                              )
                                                              OR ( allocunits.type = 2
                                                              AND partitions.partition_id = allocunits.container_id
                                                              )
                    WHERE   object_id = OBJECT_ID('' + @SchemaName_n_TableName
                                                  + '') )
                    AND Operation IN ( 'LOP_MODIFY_ROW' )
                    AND [Context] IN ( 'LCX_PFS' )
                    AND Description LIKE '%Deallocated%'
            /*Use this subquery to filter the date*/
                    AND [TRANSACTION ID] IN (
                    SELECT DISTINCT
                            [TRANSACTION ID]
                    FROM    fn_dump_dblog(NULL, NULL, N'DISK', 1, @Backuppath,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT)
                    WHERE   Context IN ( 'LCX_NULL' )
                            AND Operation IN ( 'LOP_BEGIN_XACT' )
                            AND [Transaction Name] = 'DELETE'
                            AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN @Date_From
                                                              AND
                                                              @Date_To )
            GROUP BY [Description] ,
                    [Slot ID] ,
                    [AllocUnitId] ,
                    Context
            UNION
            SELECT  [PAGE ID] ,
                    [Slot ID] ,
                    [AllocUnitId] ,
                    SUBSTRING([RowLog Contents 0], 15,
                              LEN([RowLog Contents 0])) AS [RowLog Contents 0] ,
                    CONVERT(INT, SUBSTRING([RowLog Contents 0], 7, 2)) ,
                    Context --,CAST(RIGHT([Current LSN],4) AS INT) AS [Current LSN]
            FROM    fn_dump_dblog(NULL, NULL, N'DISK', 1, @Backuppath, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                  DEFAULT, DEFAULT)
            WHERE   AllocUnitId IN (
                    SELECT  [Allocation_unit_id]
                    FROM    sys.allocation_units allocunits
                            INNER JOIN sys.partitions partitions ON ( allocunits.type IN (
                                                              1, 3 )
                                                              AND partitions.hobt_id = allocunits.container_id
                                                              )
                                                              OR ( allocunits.type = 2
                                                              AND partitions.partition_id = allocunits.container_id
                                                              )
                    WHERE   object_id = OBJECT_ID('' + @SchemaName_n_TableName
                                                  + '') )
                    AND Context IN ( 'LCX_TEXT_MIX' )
                    AND Operation IN ( 'LOP_DELETE_ROWS' ) 
            /*Use this subquery to filter the date*/
                    AND [TRANSACTION ID] IN (
                    SELECT DISTINCT
                            [TRANSACTION ID]
                    FROM    fn_dump_dblog(NULL, NULL, N'DISK', 1, @Backuppath,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT, DEFAULT,
                                          DEFAULT, DEFAULT, DEFAULT)
                    WHERE   Context IN ( 'LCX_NULL' )
                            AND Operation IN ( 'LOP_BEGIN_XACT' )
                            AND [Transaction Name] = 'DELETE'
                            AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN @Date_From
                                                              AND
                                                              @Date_To )
                         
            /****************************************/
 
    OPEN Page_Data_Cursor
 
    FETCH NEXT FROM Page_Data_Cursor INTO @ConsolidatedPageID, @Slotid,
        @AllocUnitID, @LCX_TEXT_MIX, @LinkID, @Context
 
    WHILE @@FETCH_STATUS = 0
        BEGIN
            DECLARE @hex_pageid AS VARCHAR(MAX)
            /*Page ID contains File Number and page number It looks like 0001:00000130.
              In this example 0001 is file Number &  00000130 is Page Number & These numbers are in Hex format*/
            SET @Fileid = SUBSTRING(@ConsolidatedPageID, 0,
                                    CHARINDEX(':', @ConsolidatedPageID)) -- Seperate File ID from Page ID
         
            SET @hex_pageid = '0x' + SUBSTRING(@ConsolidatedPageID,
                                               CHARINDEX(':',
                                                         @ConsolidatedPageID)
                                               + 1, LEN(@ConsolidatedPageID))  ---Seperate the page ID
            SELECT  @Pageid = CONVERT(INT, CAST('' AS XML).value('xs:hexBinary(substring(sql:variable("@hex_pageid"),sql:column("t.pos")) )',
                                                              'varbinary(max)')) -- Convert Page ID from hex to integer
            FROM    ( SELECT    CASE SUBSTRING(@hex_pageid, 1, 2)
                                  WHEN '0x' THEN 3
                                  ELSE 0
                                END
                    ) AS t ( pos ) 
             
            IF @Context = 'LCX_PFS'
                BEGIN
                    DELETE  @temppagedata
                    INSERT  INTO @temppagedata
                            EXEC
                                ( 'DBCC PAGE(' + @DataBase_Name + ', '
                                  + @fileid + ', ' + @pageid
                                  + ', 1) with tableresults,no_infomsgs;'
                                ); 
                    INSERT  INTO @pagedata
                            SELECT  @ConsolidatedPageID ,
                                    @fileid ,
                                    @pageid ,
                                    @AllocUnitID ,
                                    [ParentObject] ,
                                    [Object] ,
                                    [Field] ,
                                    [Value]
                            FROM    @temppagedata
                END
            ELSE
                IF @Context = 'LCX_TEXT_MIX'
                    BEGIN
                        INSERT  INTO @ModifiedRawData
                                SELECT  @ConsolidatedPageID ,
                                        @fileid ,
                                        @pageid ,
                                        @Slotid ,
                                        @AllocUnitID ,
                                        NULL ,
                                        0 ,
                                        CONVERT(INT, CONVERT(VARBINARY, REVERSE(SUBSTRING(@LCX_TEXT_MIX,
                                                              11, 2)))) ,
                                        @LCX_TEXT_MIX ,
                                        @LinkID ,
                                        0
                    END    
            FETCH NEXT FROM Page_Data_Cursor INTO @ConsolidatedPageID, @Slotid,
                @AllocUnitID, @LCX_TEXT_MIX, @LinkID, @Context
        END
     
    CLOSE Page_Data_Cursor
    DEALLOCATE Page_Data_Cursor
 
    DECLARE @Newhexstring VARCHAR(MAX);
 
    --The data is in multiple rows in the page, so we need to convert it into one row as a single hex value.
    --This hex value is in string format
    INSERT  INTO @ModifiedRawData
            ( [PAGE ID] ,
              [FILE IDS] ,
              [PAGE IDS] ,
              [Slot ID] ,
              [AllocUnitId] ,
              [RowLog Contents 0_var] ,
              [RowLog Length]
            )
            SELECT  [Page ID] ,
                    [FILE IDS] ,
                    [PAGE IDS] ,
                    SUBSTRING([ParentObject],
                              CHARINDEX('Slot', [ParentObject]) + 4,
                              ( CHARINDEX('Offset', [ParentObject])
                                - ( CHARINDEX('Slot', [ParentObject]) + 4 ) )
                              - 2) AS [Slot ID] ,
                    [AllocUnitId] ,
                    SUBSTRING(( SELECT  REPLACE(STUFF(( SELECT
                                                              REPLACE(SUBSTRING([Value],
                                                              CHARINDEX(':',
                                                              [Value]) + 1,
                                                              CHARINDEX('',
                                                              [Value])
                                                              - CHARINDEX(':',
                                                              [Value])), '',
                                                              '')
                                                        FROM  @pagedata C
                                                        WHERE B.[Page ID] = C.[Page ID]
                                                              AND SUBSTRING(B.[ParentObject],
                                                              CHARINDEX('Slot',
                                                              B.[ParentObject])
                                                              + 4,
                                                              ( CHARINDEX('Offset',
                                                              B.[ParentObject])
                                                              - ( CHARINDEX('Slot',
                                                              B.[ParentObject])
                                                              + 4 ) )) = SUBSTRING(C.[ParentObject],
                                                              CHARINDEX('Slot',
                                                              C.[ParentObject])
                                                              + 4,
                                                              ( CHARINDEX('Offset',
                                                              C.[ParentObject])
                                                              - ( CHARINDEX('Slot',
                                                              C.[ParentObject])
                                                              + 4 ) ))
                                                              AND [Object] LIKE '%Memory Dump%'
                                                        ORDER BY '0x'
                                                              + LEFT([Value],
                                                              CHARINDEX(':',
                                                              [Value]) - 1)
                                                      FOR
                                                        XML PATH('')
                                                      ), 1, 1, ''), ' ', '')
                              ), 1, 20000) AS [Value] ,
                    SUBSTRING(( SELECT  '0x'
                                        + REPLACE(STUFF(( SELECT
                                                              REPLACE(SUBSTRING([Value],
                                                              CHARINDEX(':',
                                                              [Value]) + 1,
                                                              CHARINDEX('',
                                                              [Value])
                                                              - CHARINDEX(':',
                                                              [Value])), '',
                                                              '')
                                                          FROM
                                                              @pagedata C
                                                          WHERE
                                                              B.[Page ID] = C.[Page ID]
                                                              AND SUBSTRING(B.[ParentObject],
                                                              CHARINDEX('Slot',
                                                              B.[ParentObject])
                                                              + 4,
                                                              ( CHARINDEX('Offset',
                                                              B.[ParentObject])
                                                              - ( CHARINDEX('Slot',
                                                              B.[ParentObject])
                                                              + 4 ) )) = SUBSTRING(C.[ParentObject],
                                                              CHARINDEX('Slot',
                                                              C.[ParentObject])
                                                              + 4,
                                                              ( CHARINDEX('Offset',
                                                              C.[ParentObject])
                                                              - ( CHARINDEX('Slot',
                                                              C.[ParentObject])
                                                              + 4 ) ))
                                                              AND [Object] LIKE '%Memory Dump%'
                                                          ORDER BY '0x'
                                                              + LEFT([Value],
                                                              CHARINDEX(':',
                                                              [Value]) - 1)
                                                        FOR
                                                          XML PATH('')
                                                        ), 1, 1, ''), ' ', '')
                              ), 7, 4) AS [Length]
            FROM    @pagedata B
            WHERE   [Object] LIKE '%Memory Dump%'
            GROUP BY [Page ID] ,
                    [FILE IDS] ,
                    [PAGE IDS] ,
                    [ParentObject] ,
                    [AllocUnitId]--,[Current LSN]
            ORDER BY [Slot ID]
 
    UPDATE  @ModifiedRawData
    SET     [RowLog Len] = CONVERT(VARBINARY(8000), REVERSE(CAST('' AS XML).value('xs:hexBinary(substring(sql:column("[RowLog Length]"),0))',
                                                              'varbinary(Max)')))
    FROM    @ModifiedRawData
    WHERE   [LINK ID] = 0
 
    UPDATE  @ModifiedRawData
    SET     [RowLog Contents 0] = CAST('' AS XML).value('xs:hexBinary(substring(sql:column("[RowLog Contents 0_var]"),0))',
                                                        'varbinary(Max)')
    FROM    @ModifiedRawData
    WHERE   [LINK ID] = 0
 
    UPDATE  B
    SET     B.[RowLog Contents 0] = ( CASE WHEN A.[RowLog Contents 0] IS NOT NULL
                                                AND C.[RowLog Contents 0] IS NOT NULL
                                           THEN A.[RowLog Contents 0]
                                                + C.[RowLog Contents 0]
                                           WHEN A.[RowLog Contents 0] IS NULL
                                                AND C.[RowLog Contents 0] IS NOT NULL
                                           THEN C.[RowLog Contents 0]
                                           WHEN A.[RowLog Contents 0] IS NOT NULL
                                                AND C.[RowLog Contents 0] IS NULL
                                           THEN A.[RowLog Contents 0]
                                      END ) ,
            B.[Update] = ISNULL(B.[Update], 0) + 1
    FROM    @ModifiedRawData B
            LEFT JOIN @ModifiedRawData A ON A.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              15 + 14, 2))))
                                            AND A.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              19 + 14, 2))))
                                            AND A.[Link ID] = B.[Link ID]
            LEFT JOIN @ModifiedRawData C ON C.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              27 + 14, 2))))
                                            AND C.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              31 + 14, 2))))
                                            AND C.[Link ID] = B.[Link ID]
    WHERE   ( A.[RowLog Contents 0] IS NOT NULL
              OR C.[RowLog Contents 0] IS NOT NULL
            )
 
 
    UPDATE  B
    SET     B.[RowLog Contents 0] = ( CASE WHEN A.[RowLog Contents 0] IS NOT NULL
                                                AND C.[RowLog Contents 0] IS NOT NULL
                                           THEN A.[RowLog Contents 0]
                                                + C.[RowLog Contents 0]
                                           WHEN A.[RowLog Contents 0] IS NULL
                                                AND C.[RowLog Contents 0] IS NOT NULL
                                           THEN C.[RowLog Contents 0]
                                           WHEN A.[RowLog Contents 0] IS NOT NULL
                                                AND C.[RowLog Contents 0] IS NULL
                                           THEN A.[RowLog Contents 0]
                                      END )
    --,B.[Update]=ISNULL(B.[Update],0)+1
    FROM    @ModifiedRawData B
            LEFT JOIN @ModifiedRawData A ON A.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              15 + 14, 2))))
                                            AND A.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              19 + 14, 2))))
                                            AND A.[Link ID] <> B.[Link ID]
                                            AND B.[Update] = 0
            LEFT JOIN @ModifiedRawData C ON C.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              27 + 14, 2))))
                                            AND C.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0],
                                                              31 + 14, 2))))
                                            AND C.[Link ID] <> B.[Link ID]
                                            AND B.[Update] = 0
    WHERE   ( A.[RowLog Contents 0] IS NOT NULL
              OR C.[RowLog Contents 0] IS NOT NULL
            )
 
    UPDATE  @ModifiedRawData
    SET     [RowLog Contents 0] = ( CASE WHEN [RowLog Len] >= 8000
                                         THEN SUBSTRING([RowLog Contents 0],
                                                        15, [RowLog Len])
                                         WHEN [RowLog Len] < 8000
                                         THEN SUBSTRING([RowLog Contents 0],
                                                        15 + 6,
                                                        CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([RowLog Contents 0],
                                                              15, 6)))))
                                    END )
    FROM    @ModifiedRawData
    WHERE   [LINK ID] = 0
 
    UPDATE  @ColumnNameAndData
    SET     [hex_Value] = [RowLog Contents 0] 
    --,A.[Update]=A.[Update]+1
    FROM    @ColumnNameAndData A
            INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value],
                                                              17, 4)))) = [PAGE IDS]
                                             AND CONVERT(INT, SUBSTRING([hex_value],
                                                              9, 2)) = B.[Link ID]
    WHERE   [System_Type_Id] IN ( 99, 167, 175, 231, 239, 241, 165, 98 )
            AND [Link ID] <> 0 
 
    UPDATE  @ColumnNameAndData
    SET     [hex_Value] = ( CASE WHEN B.[RowLog Contents 0] IS NOT NULL
                                      AND C.[RowLog Contents 0] IS NOT NULL
                                 THEN B.[RowLog Contents 0]
                                      + C.[RowLog Contents 0]
                                 WHEN B.[RowLog Contents 0] IS NULL
                                      AND C.[RowLog Contents 0] IS NOT NULL
                                 THEN C.[RowLog Contents 0]
                                 WHEN B.[RowLog Contents 0] IS NOT NULL
                                      AND C.[RowLog Contents 0] IS NULL
                                 THEN B.[RowLog Contents 0]
                            END )
    --,A.[Update]=A.[Update]+1
    FROM    @ColumnNameAndData A
            LEFT JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value],
                                                              5, 4)))) = B.[PAGE IDS]
                                            AND B.[Link ID] = 0
            LEFT JOIN @ModifiedRawData C ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value],
                                                              17, 4)))) = C.[PAGE IDS]
                                            AND C.[Link ID] = 0
    WHERE   [System_Type_Id] IN ( 99, 167, 175, 231, 239, 241, 165, 98 )
            AND ( B.[RowLog Contents 0] IS NOT NULL
                  OR C.[RowLog Contents 0] IS NOT NULL
                )
 
    UPDATE  @ColumnNameAndData
    SET     [hex_Value] = [RowLog Contents 0] 
    --,A.[Update]=A.[Update]+1
    FROM    @ColumnNameAndData A
            INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value],
                                                              9, 4)))) = [PAGE IDS]
                                             AND CONVERT(INT, SUBSTRING([hex_value],
                                                              3, 2)) = [Link ID]
    WHERE   [System_Type_Id] IN ( 35, 34, 99 )
            AND [Link ID] <> 0 
     
    UPDATE  @ColumnNameAndData
    SET     [hex_Value] = [RowLog Contents 0]
    --,A.[Update]=A.[Update]+10
    FROM    @ColumnNameAndData A
            INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value],
                                                              9, 4)))) = [PAGE IDS]
    WHERE   [System_Type_Id] IN ( 35, 34, 99 )
            AND [Link ID] = 0
 
    UPDATE  @ColumnNameAndData
    SET     [hex_Value] = [RowLog Contents 0] 
    --,A.[Update]=A.[Update]+1
    FROM    @ColumnNameAndData A
            INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value],
                                                              15, 4)))) = [PAGE IDS]
    WHERE   [System_Type_Id] IN ( 35, 34, 99 )
            AND [Link ID] = 0
 
    UPDATE  @ColumnNameAndData
    SET     [hex_value] = 0xFFFE + SUBSTRING([hex_value], 9, LEN([hex_value]))
    --,[Update]=[Update]+1
    WHERE   [system_type_id] = 241
 
    CREATE TABLE [#temp_Data]
        (
          [FieldName] VARCHAR(MAX) ,
          [FieldValue] NVARCHAR(MAX) ,
          [Rowlogcontents] VARBINARY(8000) ,
          [Row ID] INT
        )
 
    INSERT  INTO #temp_Data
            SELECT  NAME ,
                    CASE WHEN system_type_id IN ( 231, 239 )
                         THEN LTRIM(RTRIM(CONVERT(NVARCHAR(MAX), hex_Value)))  --NVARCHAR ,NCHAR
                         WHEN system_type_id IN ( 167, 175 )
                         THEN LTRIM(RTRIM(CONVERT(VARCHAR(MAX), hex_Value)))  --VARCHAR,CHAR
                         WHEN system_type_id IN ( 35 )
                         THEN LTRIM(RTRIM(CONVERT(VARCHAR(MAX), hex_Value))) --Text
                         WHEN system_type_id IN ( 99 )
                         THEN LTRIM(RTRIM(CONVERT(NVARCHAR(MAX), hex_Value))) --nText 
                         WHEN system_type_id = 48
                         THEN CONVERT(VARCHAR(MAX), CONVERT(TINYINT, CONVERT(BINARY(1), REVERSE(hex_Value)))) --TINY INTEGER
                         WHEN system_type_id = 52
                         THEN CONVERT(VARCHAR(MAX), CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(hex_Value)))) --SMALL INTEGER
                         WHEN system_type_id = 56
                         THEN CONVERT(VARCHAR(MAX), CONVERT(INT, CONVERT(BINARY(4), REVERSE(hex_Value)))) -- INTEGER
                         WHEN system_type_id = 127
                         THEN CONVERT(VARCHAR(MAX), CONVERT(BIGINT, CONVERT(BINARY(8), REVERSE(hex_Value))))-- BIG INTEGER
                         WHEN system_type_id = 61
                         THEN CONVERT(VARCHAR(MAX), CONVERT(DATETIME, CONVERT(VARBINARY(8000), REVERSE(hex_Value))), 100) --DATETIME
                         WHEN system_type_id = 58
                         THEN CONVERT(VARCHAR(MAX), CONVERT(SMALLDATETIME, CONVERT(VARBINARY(8000), REVERSE(hex_Value))), 100) --SMALL DATETIME
                         WHEN system_type_id = 108
                         THEN CONVERT(VARCHAR(MAX), CONVERT(NUMERIC(38, 20), CONVERT(VARBINARY, CONVERT(VARBINARY(1), xprec)
                              + CONVERT(VARBINARY(1), xscale))
                              + CONVERT(VARBINARY(1), 0) + hex_Value)) --- NUMERIC
                         WHEN system_type_id = 106
                         THEN CONVERT(VARCHAR(MAX), CONVERT(DECIMAL(38, 20), CONVERT(VARBINARY, CONVERT(VARBINARY(1), xprec)
                              + CONVERT(VARBINARY(1), xscale))
                              + CONVERT(VARBINARY(1), 0) + hex_Value)) --- DECIMAL
                         WHEN system_type_id IN ( 60, 122 )
                         THEN CONVERT(VARCHAR(MAX), CONVERT(MONEY, CONVERT(VARBINARY(8000), REVERSE(hex_Value))), 2) --MONEY,SMALLMONEY
                         WHEN system_type_id = 104
                         THEN CONVERT(VARCHAR(MAX), CONVERT (BIT, CONVERT(BINARY(1), hex_Value)
                              % 2))  -- BIT
                         WHEN system_type_id = 62
                         THEN RTRIM(LTRIM(STR(CONVERT(FLOAT, SIGN(CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT))
                                              * ( 1.0
                                                  + ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT)
                                                      & 0x000FFFFFFFFFFFFF )
                                                  * POWER(CAST(2 AS FLOAT),
                                                          -52) )
                                              * POWER(CAST(2 AS FLOAT),
                                                      ( ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT)
                                                          & 0x7ff0000000000000 )
                                                        / EXP(52 * LOG(2))
                                                        - 1023 ))), 53,
                                              LEN(hex_Value)))) --- FLOAT
                         WHEN system_type_id = 59
                         THEN LEFT(LTRIM(STR(CAST(SIGN(CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT))
                                             * ( 1.0
                                                 + ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT)
                                                     & 0x007FFFFF )
                                                 * POWER(CAST(2 AS REAL), -23) )
                                             * POWER(CAST(2 AS REAL),
                                                     ( ( ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS INT) )
                                                         & 0x7f800000 )
                                                       / EXP(23 * LOG(2))
                                                       - 127 )) AS REAL), 23,
                                             23)), 8) --Real
                         WHEN system_type_id IN ( 165, 173 )
                         THEN ( CASE WHEN CHARINDEX(0x,
                                                    CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'VARBINARY(8000)')) = 0
                                     THEN '0x'
                                     ELSE ''
                                END ) + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'varchar(max)') -- BINARY,VARBINARY
                         WHEN system_type_id = 34
                         THEN ( CASE WHEN CHARINDEX(0x,
                                                    CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'VARBINARY(8000)')) = 0
                                     THEN '0x'
                                     ELSE ''
                                END ) + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'varchar(max)')  --IMAGE
                         WHEN system_type_id = 36
                         THEN CONVERT(VARCHAR(MAX), CONVERT(UNIQUEIDENTIFIER, hex_Value)) --UNIQUEIDENTIFIER
                         WHEN system_type_id = 231
                         THEN CONVERT(VARCHAR(MAX), CONVERT(SYSNAME, hex_Value)) --SYSNAME
                         WHEN system_type_id = 241
                         THEN CONVERT(VARCHAR(MAX), CONVERT(XML, hex_Value)) --XML
                         WHEN system_type_id = 189
                         THEN ( CASE WHEN CHARINDEX(0x,
                                                    CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'VARBINARY(8000)')) = 0
                                     THEN '0x'
                                     ELSE ''
                                END ) + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'varchar(max)') --TIMESTAMP
                         WHEN system_type_id = 98
                         THEN ( CASE WHEN CONVERT(INT, SUBSTRING(hex_Value, 1,
                                                              1)) = 56
                                     THEN CONVERT(VARCHAR(MAX), CONVERT(INT, CONVERT(BINARY(4), REVERSE(SUBSTRING(hex_Value,
                                                              3,
                                                              LEN(hex_Value))))))  -- INTEGER
                                     WHEN CONVERT(INT, SUBSTRING(hex_Value, 1,
                                                              1)) = 108
                                     THEN CONVERT(VARCHAR(MAX), CONVERT(NUMERIC(38,
                                                              20), CONVERT(VARBINARY(1), SUBSTRING(hex_Value,
                                                              3, 1))
                                          + CONVERT(VARBINARY(1), SUBSTRING(hex_Value,
                                                              4, 1))
                                          + CONVERT(VARBINARY(1), 0)
                                          + SUBSTRING(hex_Value, 5,
                                                      LEN(hex_Value)))) --- NUMERIC
                                     WHEN CONVERT(INT, SUBSTRING(hex_Value, 1,
                                                              1)) = 167
                                     THEN LTRIM(RTRIM(CONVERT(VARCHAR(MAX), SUBSTRING(hex_Value,
                                                              9,
                                                              LEN(hex_Value))))) --VARCHAR,CHAR
                                     WHEN CONVERT(INT, SUBSTRING(hex_Value, 1,
                                                              1)) = 36
                                     THEN CONVERT(VARCHAR(MAX), CONVERT(UNIQUEIDENTIFIER, SUBSTRING(( hex_Value ),
                                                              3, 20))) --UNIQUEIDENTIFIER
                                     WHEN CONVERT(INT, SUBSTRING(hex_Value, 1,
                                                              1)) = 61
                                     THEN CONVERT(VARCHAR(MAX), CONVERT(DATETIME, CONVERT(VARBINARY(8000), REVERSE(SUBSTRING(hex_Value,
                                                              3,
                                                              LEN(hex_Value))))), 100) --DATETIME
                                     WHEN CONVERT(INT, SUBSTRING(hex_Value, 1,
                                                              1)) = 165
                                     THEN '0x'
                                          + SUBSTRING(( CASE WHEN CHARINDEX(0x,
                                                              CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'VARBINARY(8000)')) = 0
                                                             THEN '0x'
                                                             ELSE ''
                                                        END )
                                                      + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))',
                                                              'varchar(max)'),
                                                      11, LEN(hex_Value)) -- BINARY,VARBINARY
                                END )
                    END AS FieldValue ,
                    [Rowlogcontents] ,
                    [Row ID]
            FROM    @ColumnNameAndData
            ORDER BY nullbit
 
--Create the column name in the same order to do pivot table.
 
    DECLARE @FieldName VARCHAR(MAX)
    SET @FieldName = STUFF(( SELECT ','
                                    + CAST(QUOTENAME([Name]) AS VARCHAR(MAX))
                             FROM   syscolumns
                             WHERE  id = OBJECT_ID(''
                                                   + @SchemaName_n_TableName
                                                   + '')
                           FOR
                             XML PATH('')
                           ), 1, 1, '')
 
--Finally did pivot table and get the data back in the same format.
 
    SET @sql = 'SELECT ' + @FieldName
        + ' FROM #temp_Data PIVOT (Min([FieldValue]) FOR FieldName IN ('
        + @FieldName + ')) AS pvt'
    EXEC sp_executesql @sql
 
GO
View Code

 

5、在C盘看到备份出来的日志备份文件

 

 

6、存储过程的两种调用方式

--存储过程依然保持着两种调用方式
EXEC Recover_Deleted_Data_BylogBackup_Proc 'sss','dbo.testdelete',N'C:\sss_logBackup_2015_07_04_150756.BAK'
GO


EXEC Recover_Deleted_Data_BylogBackup_Proc 'sss','dbo.testdelete',N'C:\sss_logBackup_2015_07_04_150756.BAK','2012-06-01','2016-06-30'
GO

 

可以看到被误删的那条数据.

 


为什麽要扩展这个存储过程

 

因为进行了日志备份之后,原先的delete语句的log record可能已经不存在于ldf文件里面,这时候要恢复被那条delete语句删除的数据就需要读取

log backup文件里面的log record来进行恢复

 

对比图

Recover_Deleted_Data_Proc

Recover_Deleted_Data_BylogBackup_Proc

 

因为很多公司为了数据安全,一般会对数据库半个小时或者15分钟做一次日志备份,目的是做日志传送或者及时把数据库备份拷走

考虑到这种情况,本人决定扩展一下这个存储过程,其实原理也很简单,就是把fn_dblog函数替换为fn_dump_dblog函数

 

在文章《恢复SQL Server被误删除的数据》发布之后,有很多人通过QQ咨询我,为什麽执行了你的存储过程之后会显示

There is no data in the log as per the search criteria

 

我发现原因基本上有两个:

(1)数据库从来没有做过完整备份

(2)因为数据库实例下有一个job定时对数据库做日志备份,误删除了数据之后(误执行delete语句之后),刚好那个job到达运行时间,对数据库进行了日志备份

 

对于第一种情况,可以参考本人写的这篇文章《您真的理解了SQLSERVER的日志链了吗?》,文章里面有解释

对于第二种情况,可以使用本篇文章的方法,回想一下delete语句的执行时间,然后指定日志备份的备份文件进行恢复

--指定日志备份的备份文件
EXEC Recover_Deleted_Data_BylogBackup_Proc 'sss','dbo.testdelete',N'C:\sss_logBackup_2015_07_04_150756.BAK'
GO

 

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o 

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
5天前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
13天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
52 10
|
25天前
|
SQL 存储 关系型数据库
一文搞懂SQL优化——如何高效添加数据
**SQL优化关键点:** 1. **批量插入**提高效率,一次性建议不超过500条。 2. **手动事务**减少开销,多条插入语句用一个事务。 3. **主键顺序插入**避免页分裂,提升性能。 4. **使用`LOAD DATA INFILE`**大批量导入快速。 5. **避免主键乱序**,减少不必要的磁盘操作。 6. **选择合适主键类型**,避免UUID或长主键导致的性能问题。 7. **避免主键修改**,保持索引稳定。 这些技巧能优化数据库操作,提升系统性能。
220 4
一文搞懂SQL优化——如何高效添加数据
|
23天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
17 0
|
13天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
78 6
|
1天前
|
SQL 关系型数据库 MySQL
:“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versi
:“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versi
6 0
|
5天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
5天前
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
5天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL条件控制:数据的“红绿灯”与“分岔路”
【4月更文挑战第19天】在Oracle PL/SQL中,IF语句与CASE语句扮演着数据流程控制的关键角色。IF语句如红绿灯,依据条件决定程序执行路径;ELSE和ELSIF提供多分支逻辑。CASE语句则是分岔路,按表达式值选择执行路径。这些条件控制语句在数据验证、错误处理和业务逻辑中不可或缺,通过巧妙运用能实现高效程序逻辑,保障数据正确流转,支持企业业务发展。理解并熟练掌握这些语句的使用是成为合格数据管理员的重要一环。
|
5天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。