1 2 /****** Object: StoredProcedure [dbo].[Recover_Deleted_Data_Proc] Script Date: 04/23/2014 22:11:59 ******/ 3 SET ANSI_NULLS ON 4 GO 5 SET QUOTED_IDENTIFIER ON 6 GO 7 -- Script Name: Recover_Deleted_Data_Proc 8 -- Script Type : Recovery Procedure 9 -- Develop By: Muhammad Imran 10 -- Date Created: 15 Oct 2011 11 -- Modify Date: 22 Aug 2012 12 -- Version : 3.1 13 -- Notes : Included BLOB data types for recovery.& Compatibile with Default , CS collation , Arabic_CI_AS. 14 15 16 ALTER PROCEDURE [dbo].[Recover_Deleted_Data_Proc] 17 @Database_Name NVARCHAR(MAX) , 18 @SchemaName_n_TableName NVARCHAR(MAX) , 19 @Date_From DATETIME = '1900/01/01' , 20 @Date_To DATETIME = '9999/12/31' 21 AS 22 DECLARE @RowLogContents VARBINARY(8000) 23 DECLARE @TransactionID NVARCHAR(MAX) 24 DECLARE @AllocUnitID BIGINT 25 DECLARE @AllocUnitName NVARCHAR(MAX) 26 DECLARE @SQL NVARCHAR(MAX) 27 DECLARE @Compatibility_Level INT 28 29 30 SELECT @Compatibility_Level = dtb.compatibility_level 31 FROM master.sys.databases AS dtb 32 WHERE dtb.name = @Database_Name 33 34 IF ISNULL(@Compatibility_Level, 0) <= 80 35 BEGIN 36 RAISERROR('The compatibility level should be equal to or greater SQL SERVER 2005 (90)',16,1) 37 RETURN 38 END 39 40 IF ( SELECT COUNT(*) 41 FROM INFORMATION_SCHEMA.TABLES 42 WHERE [TABLE_SCHEMA] + '.' + [TABLE_NAME] = @SchemaName_n_TableName 43 ) = 0 44 BEGIN 45 RAISERROR('Could not found the table in the defined database',16,1) 46 RETURN 47 END 48 49 DECLARE @bitTable TABLE 50 ( 51 [ID] INT , 52 [Bitvalue] INT 53 ) 54 --Create table to set the bit position of one byte. 55 56 INSERT INTO @bitTable 57 SELECT 0 , 58 2 59 UNION ALL 60 SELECT 1 , 61 2 62 UNION ALL 63 SELECT 2 , 64 4 65 UNION ALL 66 SELECT 3 , 67 8 68 UNION ALL 69 SELECT 4 , 70 16 71 UNION ALL 72 SELECT 5 , 73 32 74 UNION ALL 75 SELECT 6 , 76 64 77 UNION ALL 78 SELECT 7 , 79 128 80 81 --Create table to collect the row data. 82 DECLARE @DeletedRecords TABLE 83 ( 84 [Row ID] INT IDENTITY(1, 1) , 85 [RowLogContents] VARBINARY(8000) , 86 [AllocUnitID] BIGINT , 87 [Transaction ID] NVARCHAR(MAX) , 88 [FixedLengthData] SMALLINT , 89 [TotalNoOfCols] SMALLINT , 90 [NullBitMapLength] SMALLINT , 91 [NullBytes] VARBINARY(8000) , 92 [TotalNoofVarCols] SMALLINT , 93 [ColumnOffsetArray] VARBINARY(8000) , 94 [VarColumnStart] SMALLINT , 95 [Slot ID] INT , 96 [NullBitMap] VARCHAR(MAX) 97 ) 98 --Create a common table expression to get all the row data plus how many bytes we have for each row. 99 ; 100 WITH RowData 101 AS ( SELECT [RowLog Contents 0] AS [RowLogContents] , 102 [AllocUnitID] AS [AllocUnitID] , 103 [Transaction ID] AS [Transaction ID] 104 105 --[Fixed Length Data] = Substring (RowLog content 0, Status Bit A+ Status Bit B + 1,2 bytes) 106 , 107 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 108 2 + 1, 2)))) AS [FixedLengthData] --@FixedLengthData 109 110 -- [TotalnoOfCols] = Substring (RowLog content 0, [Fixed Length Data] + 1,2 bytes) 111 , 112 CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 113 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 114 2 + 1, 2)))) + 1, 115 2)))) AS [TotalNoOfCols] 116 117 --[NullBitMapLength]=ceiling([Total No of Columns] /8.0) 118 , 119 CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 120 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 121 2 + 1, 2)))) + 1, 122 2)))) / 8.0)) AS [NullBitMapLength] 123 124 --[Null Bytes] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [NullBitMapLength] ) 125 , 126 SUBSTRING([RowLog Contents 0], 127 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 128 2 + 1, 2)))) + 3, 129 CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 130 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 131 2 + 1, 2)))) + 1, 132 2)))) / 8.0))) AS [NullBytes] 133 134 --[TotalNoofVarCols] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 ) 135 , 136 ( CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN ( 137 0x10, 0x30, 0x70 ) 138 THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 139 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 140 2 + 1, 2)))) + 3 141 + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 142 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 143 2 + 1, 2)))) + 1, 144 2)))) / 8.0)), 2)))) 145 ELSE NULL 146 END ) AS [TotalNoofVarCols] 147 148 --[ColumnOffsetArray]= Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 , [TotalNoofVarCols]*2 ) 149 , 150 ( CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN ( 151 0x10, 0x30, 0x70 ) 152 THEN SUBSTRING([RowLog Contents 0], 153 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 154 2 + 1, 2)))) + 3 155 + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 156 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 157 2 + 1, 2)))) + 1, 158 2)))) / 8.0)) 159 + 2, 160 ( CASE WHEN SUBSTRING([RowLog Contents 0], 161 1, 1) IN ( 0x10, 162 0x30, 0x70 ) 163 THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 164 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 165 2 + 1, 2)))) + 3 166 + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 167 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 168 2 + 1, 2)))) + 1, 169 2)))) / 8.0)), 2)))) 170 ELSE NULL 171 END ) * 2) 172 ELSE NULL 173 END ) AS [ColumnOffsetArray] 174 175 -- Variable column Start = Status Bit A+ Status Bit B + [Fixed Length Data] + [Null Bitmap length] + 2+([TotalNoofVarCols]*2) 176 , 177 CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN ( 178 0x10, 0x30, 0x70 ) 179 THEN ( CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 180 2 + 1, 2)))) + 4 181 + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 182 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 183 2 + 1, 2)))) + 1, 184 2)))) / 8.0)) 185 + ( ( CASE WHEN SUBSTRING([RowLog Contents 0], 186 1, 1) IN ( 0x10, 187 0x30, 0x70 ) 188 THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 189 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 190 2 + 1, 2)))) + 3 191 + CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 192 CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 193 2 + 1, 2)))) + 1, 194 2)))) / 8.0)), 2)))) 195 ELSE NULL 196 END ) * 2 ) ) 197 ELSE NULL 198 END AS [VarColumnStart] , 199 [Slot ID] 200 FROM sys.fn_dblog(NULL, NULL) 201 WHERE AllocUnitId IN ( 202 SELECT [Allocation_unit_id] 203 FROM sys.allocation_units allocunits 204 INNER JOIN sys.partitions partitions ON ( allocunits.type IN ( 205 1, 3 ) 206 AND partitions.hobt_id = allocunits.container_id 207 ) 208 OR ( allocunits.type = 2 209 AND partitions.partition_id = allocunits.container_id 210 ) 211 WHERE object_id = OBJECT_ID('' 212 + @SchemaName_n_TableName 213 + '') ) 214 AND Context IN ( 'LCX_MARK_AS_GHOST', 'LCX_HEAP' ) 215 AND Operation IN ( 'LOP_DELETE_ROWS' ) 216 AND SUBSTRING([RowLog Contents 0], 1, 1) IN ( 0x10, 217 0x30, 0x70 ) 218 219 /*Use this subquery to filter the date*/ 220 AND [TRANSACTION ID] IN ( 221 SELECT DISTINCT 222 [TRANSACTION ID] 223 FROM sys.fn_dblog(NULL, NULL) 224 WHERE Context IN ( 'LCX_NULL' ) 225 AND Operation IN ( 'LOP_BEGIN_XACT' ) 226 AND [Transaction Name] IN ( 'DELETE', 227 'user_transaction' ) 228 AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN @Date_From 229 AND 230 @Date_To ) 231 ), 232 233 --Use this technique to repeate the row till the no of bytes of the row. 234 N1 ( n ) 235 AS ( SELECT 1 236 UNION ALL 237 SELECT 1 238 ), 239 N2 ( n ) 240 AS ( SELECT 1 241 FROM N1 AS X , 242 N1 AS Y 243 ), 244 N3 ( n ) 245 AS ( SELECT 1 246 FROM N2 AS X , 247 N2 AS Y 248 ), 249 N4 ( n ) 250 AS ( SELECT ROW_NUMBER() OVER ( ORDER BY X.n ) 251 FROM N3 AS X , 252 N3 AS Y 253 ) 254 INSERT INTO @DeletedRecords 255 SELECT RowLogContents , 256 [AllocUnitID] , 257 [Transaction ID] , 258 [FixedLengthData] , 259 [TotalNoOfCols] , 260 [NullBitMapLength] , 261 [NullBytes] , 262 [TotalNoofVarCols] , 263 [ColumnOffsetArray] , 264 [VarColumnStart] , 265 [Slot ID] 266 ---Get the Null value against each column (1 means null zero means not null) 267 , 268 [NullBitMap] = ( REPLACE(STUFF(( SELECT 269 ',' 270 + ( CASE 271 WHEN [ID] = 0 272 THEN CONVERT(NVARCHAR(1), ( SUBSTRING(NullBytes, 273 n, 1) % 2 )) 274 ELSE CONVERT(NVARCHAR(1), ( ( SUBSTRING(NullBytes, 275 n, 1) 276 / [Bitvalue] ) 277 % 2 )) 278 END ) --as [nullBitMap] 279 FROM N4 AS Nums 280 JOIN RowData AS C ON n <= NullBitMapLength 281 CROSS JOIN @bitTable 282 WHERE 283 C.[RowLogContents] = D.[RowLogContents] 284 ORDER BY [RowLogContents] , 285 n ASC 286 FOR 287 XML PATH('') 288 ), 1, 1, ''), ',', '') ) 289 FROM RowData D 290 291 IF ( SELECT COUNT(*) 292 FROM @DeletedRecords 293 ) = 0 294 BEGIN 295 RAISERROR('There is no data in the log as per the search criteria',16,1) 296 RETURN 297 END 298 299 DECLARE @ColumnNameAndData TABLE 300 ( 301 [Row ID] INT , 302 [Rowlogcontents] VARBINARY(MAX) , 303 [NAME] SYSNAME , 304 [nullbit] SMALLINT , 305 [leaf_offset] SMALLINT , 306 [length] SMALLINT , 307 [system_type_id] TINYINT , 308 [bitpos] TINYINT , 309 [xprec] TINYINT , 310 [xscale] TINYINT , 311 [is_null] INT , 312 [Column value Size] INT , 313 [Column Length] INT , 314 [hex_Value] VARBINARY(MAX) , 315 [Slot ID] INT , 316 [Update] INT 317 ) 318 319 --Create common table expression and join it with the rowdata table 320 -- to get each column details 321 /*This part is for variable data columns*/ 322 --@RowLogContents, 323 --(col.columnOffValue - col.columnLength) + 1, 324 --col.columnLength 325 --) 326 INSERT INTO @ColumnNameAndData 327 SELECT [Row ID] , 328 Rowlogcontents , 329 NAME , 330 cols.leaf_null_bit AS nullbit , 331 leaf_offset , 332 ISNULL(syscolumns.length, cols.max_length) AS [length] , 333 cols.system_type_id , 334 cols.leaf_bit_position AS bitpos , 335 ISNULL(syscolumns.xprec, cols.precision) AS xprec , 336 ISNULL(syscolumns.xscale, cols.scale) AS xscale , 337 SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null , 338 ( CASE WHEN leaf_offset < 1 339 AND SUBSTRING([nullBitMap], cols.leaf_null_bit, 340 1) = 0 341 THEN ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 342 ( 2 343 * leaf_offset 344 * -1 ) - 1, 2)))) > 30000 345 THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 346 ( 2 347 * leaf_offset 348 * -1 ) - 1, 2)))) 349 - POWER(2, 15) 350 ELSE CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 351 ( 2 352 * leaf_offset 353 * -1 ) - 1, 2)))) 354 END ) 355 END ) AS [Column value Size] , 356 ( CASE WHEN leaf_offset < 1 357 AND SUBSTRING([nullBitMap], cols.leaf_null_bit, 358 1) = 0 359 THEN ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 360 ( 2 361 * leaf_offset 362 * -1 ) - 1, 2)))) > 30000 363 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 364 ( 2 365 * ( ( leaf_offset 366 * -1 ) - 1 ) ) 367 - 1, 2)))), 0), 368 [varColumnStart]) < 30000 369 THEN ( CASE WHEN [System_type_id] IN ( 370 35, 34, 99 ) THEN 16 371 ELSE 24 372 END ) 373 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 374 ( 2 375 * leaf_offset 376 * -1 ) - 1, 2)))) > 30000 377 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 378 ( 2 379 * ( ( leaf_offset 380 * -1 ) - 1 ) ) 381 - 1, 2)))), 0), 382 [varColumnStart]) > 30000 383 THEN ( CASE WHEN [System_type_id] IN ( 384 35, 34, 99 ) THEN 16 385 ELSE 24 386 END ) --24 387 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 388 ( 2 389 * leaf_offset 390 * -1 ) - 1, 2)))) < 30000 391 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 392 ( 2 393 * ( ( leaf_offset 394 * -1 ) - 1 ) ) 395 - 1, 2)))), 0), 396 [varColumnStart]) < 30000 397 THEN ( CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 398 ( 2 399 * leaf_offset 400 * -1 ) - 1, 2)))) 401 - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 402 ( 2 403 * ( ( leaf_offset 404 * -1 ) - 1 ) ) 405 - 1, 2)))), 0), 406 [varColumnStart]) ) 407 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 408 ( 2 409 * leaf_offset 410 * -1 ) - 1, 2)))) < 30000 411 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 412 ( 2 413 * ( ( leaf_offset 414 * -1 ) - 1 ) ) 415 - 1, 2)))), 0), 416 [varColumnStart]) > 30000 417 THEN POWER(2, 15) 418 + CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 419 ( 2 420 * leaf_offset 421 * -1 ) - 1, 2)))) 422 - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 423 ( 2 424 * ( ( leaf_offset 425 * -1 ) - 1 ) ) 426 - 1, 2)))), 0), 427 [varColumnStart]) 428 END ) 429 END ) AS [Column Length] , 430 ( CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) = 1 431 THEN NULL 432 ELSE SUBSTRING(Rowlogcontents, 433 ( ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 434 ( 2 435 * leaf_offset 436 * -1 ) - 1, 2)))) > 30000 437 THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 438 ( 2 439 * leaf_offset 440 * -1 ) - 1, 2)))) 441 - POWER(2, 15) 442 ELSE CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 443 ( 2 444 * leaf_offset 445 * -1 ) - 1, 2)))) 446 END ) 447 - ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 448 ( 2 449 * leaf_offset 450 * -1 ) - 1, 2)))) > 30000 451 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 452 ( 2 453 * ( ( leaf_offset 454 * -1 ) - 1 ) ) 455 - 1, 2)))), 0), 456 [varColumnStart]) < 30000 457 THEN ( CASE 458 WHEN [System_type_id] IN ( 459 35, 34, 99 ) 460 THEN 16 461 ELSE 24 462 END ) --24 463 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 464 ( 2 465 * leaf_offset 466 * -1 ) - 1, 2)))) > 30000 467 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 468 ( 2 469 * ( ( leaf_offset 470 * -1 ) - 1 ) ) 471 - 1, 2)))), 0), 472 [varColumnStart]) > 30000 473 THEN ( CASE 474 WHEN [System_type_id] IN ( 475 35, 34, 99 ) 476 THEN 16 477 ELSE 24 478 END ) --24 479 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 480 ( 2 481 * leaf_offset 482 * -1 ) - 1, 2)))) < 30000 483 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 484 ( 2 485 * ( ( leaf_offset 486 * -1 ) - 1 ) ) 487 - 1, 2)))), 0), 488 [varColumnStart]) < 30000 489 THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 490 ( 2 491 * leaf_offset 492 * -1 ) - 1, 2)))) 493 - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 494 ( 2 495 * ( ( leaf_offset 496 * -1 ) - 1 ) ) 497 - 1, 2)))), 0), 498 [varColumnStart]) 499 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 500 ( 2 501 * leaf_offset 502 * -1 ) - 1, 2)))) < 30000 503 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 504 ( 2 505 * ( ( leaf_offset 506 * -1 ) - 1 ) ) 507 - 1, 2)))), 0), 508 [varColumnStart]) > 30000 509 THEN POWER(2, 15) 510 + CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 511 ( 2 512 * leaf_offset 513 * -1 ) - 1, 2)))) 514 - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 515 ( 2 516 * ( ( leaf_offset 517 * -1 ) - 1 ) ) 518 - 1, 2)))), 0), 519 [varColumnStart]) 520 END ) ) + 1, 521 ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 522 ( 2 523 * leaf_offset 524 * -1 ) - 1, 2)))) > 30000 525 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 526 ( 2 527 * ( ( leaf_offset 528 * -1 ) - 1 ) ) 529 - 1, 2)))), 0), 530 [varColumnStart]) < 30000 531 THEN ( CASE WHEN [System_type_id] IN ( 532 35, 34, 99 ) 533 THEN 16 534 ELSE 24 535 END ) --24 536 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 537 ( 2 538 * leaf_offset 539 * -1 ) - 1, 2)))) > 30000 540 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 541 ( 2 542 * ( ( leaf_offset 543 * -1 ) - 1 ) ) 544 - 1, 2)))), 0), 545 [varColumnStart]) > 30000 546 THEN ( CASE WHEN [System_type_id] IN ( 547 35, 34, 99 ) 548 THEN 16 549 ELSE 24 550 END ) --24 551 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 552 ( 2 553 * leaf_offset 554 * -1 ) - 1, 2)))) < 30000 555 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 556 ( 2 557 * ( ( leaf_offset 558 * -1 ) - 1 ) ) 559 - 1, 2)))), 0), 560 [varColumnStart]) < 30000 561 THEN ABS(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 562 ( 2 563 * leaf_offset 564 * -1 ) - 1, 2)))) 565 - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 566 ( 2 567 * ( ( leaf_offset 568 * -1 ) - 1 ) ) 569 - 1, 2)))), 0), 570 [varColumnStart])) 571 WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 572 ( 2 573 * leaf_offset 574 * -1 ) - 1, 2)))) < 30000 575 AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 576 ( 2 577 * ( ( leaf_offset 578 * -1 ) - 1 ) ) 579 - 1, 2)))), 0), 580 [varColumnStart]) > 30000 581 THEN POWER(2, 15) 582 + CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 583 ( 2 584 * leaf_offset 585 * -1 ) - 1, 2)))) 586 - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], 587 ( 2 588 * ( ( leaf_offset 589 * -1 ) - 1 ) ) 590 - 1, 2)))), 0), 591 [varColumnStart]) 592 END )) 593 END ) AS hex_Value , 594 [Slot ID] , 595 0 596 FROM @DeletedRecords A 597 INNER JOIN sys.allocation_units allocunits ON A.[AllocUnitId] = allocunits.[Allocation_Unit_Id] 598 INNER JOIN sys.partitions partitions ON ( allocunits.type IN ( 599 1, 3 ) 600 AND partitions.hobt_id = allocunits.container_id 601 ) 602 OR ( allocunits.type = 2 603 AND partitions.partition_id = allocunits.container_id 604 ) 605 INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_id 606 LEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_id 607 AND syscolumns.colid = cols.partition_column_id 608 WHERE leaf_offset < 0 609 UNION 610 /*This part is for fixed data columns*/ 611 SELECT [Row ID] , 612 Rowlogcontents , 613 NAME , 614 cols.leaf_null_bit AS nullbit , 615 leaf_offset , 616 ISNULL(syscolumns.length, cols.max_length) AS [length] , 617 cols.system_type_id , 618 cols.leaf_bit_position AS bitpos , 619 ISNULL(syscolumns.xprec, cols.precision) AS xprec , 620 ISNULL(syscolumns.xscale, cols.scale) AS xscale , 621 SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null , 622 ( SELECT TOP 1 623 ISNULL(SUM(CASE WHEN C.leaf_offset > 1 624 THEN max_length 625 ELSE 0 626 END), 0) 627 FROM sys.system_internals_partition_columns C 628 WHERE cols.partition_id = C.partition_id 629 AND C.leaf_null_bit < cols.leaf_null_bit 630 ) + 5 AS [Column value Size] , 631 syscolumns.length AS [Column Length] , 632 CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) = 1 633 THEN NULL 634 ELSE SUBSTRING(Rowlogcontents, 635 ( SELECT TOP 1 636 ISNULL(SUM(CASE 637 WHEN C.leaf_offset > 1 638 AND C.leaf_bit_position = 0 639 THEN max_length 640 ELSE 0 641 END), 0) 642 FROM sys.system_internals_partition_columns C 643 WHERE cols.partition_id = C.partition_id 644 AND C.leaf_null_bit < cols.leaf_null_bit 645 ) + 5, syscolumns.length) 646 END AS hex_Value , 647 [Slot ID] , 648 0 649 FROM @DeletedRecords A 650 INNER JOIN sys.allocation_units allocunits ON A.[AllocUnitId] = allocunits.[Allocation_Unit_Id] 651 INNER JOIN sys.partitions partitions ON ( allocunits.type IN ( 652 1, 3 ) 653 AND partitions.hobt_id = allocunits.container_id 654 ) 655 OR ( allocunits.type = 2 656 AND partitions.partition_id = allocunits.container_id 657 ) 658 INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_id 659 LEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_id 660 AND syscolumns.colid = cols.partition_column_id 661 WHERE leaf_offset > 0 662 ORDER BY nullbit 663 664 DECLARE @BitColumnByte AS INT 665 SELECT @BitColumnByte = CONVERT(INT, CEILING(COUNT(*) / 8.0)) 666 FROM @ColumnNameAndData 667 WHERE [System_Type_id] = 104; 668 WITH N1 ( n ) 669 AS ( SELECT 1 670 UNION ALL 671 SELECT 1 672 ), 673 N2 ( n ) 674 AS ( SELECT 1 675 FROM N1 AS X , 676 N1 AS Y 677 ), 678 N3 ( n ) 679 AS ( SELECT 1 680 FROM N2 AS X , 681 N2 AS Y 682 ), 683 N4 ( n ) 684 AS ( SELECT ROW_NUMBER() OVER ( ORDER BY X.n ) 685 FROM N3 AS X , 686 N3 AS Y 687 ), 688 CTE 689 AS ( SELECT RowLogContents , 690 [nullbit] , 691 [BitMap] = CONVERT(VARBINARY(1), CONVERT(INT, SUBSTRING(( REPLACE(STUFF(( SELECT 692 ',' 693 + ( CASE 694 WHEN [ID] = 0 695 THEN CONVERT(NVARCHAR(1), ( SUBSTRING(hex_Value, 696 n, 1) % 2 )) 697 ELSE CONVERT(NVARCHAR(1), ( ( SUBSTRING(hex_Value, 698 n, 1) 699 / [Bitvalue] ) 700 % 2 )) 701 END ) --as [nullBitMap] 702 FROM 703 N4 AS Nums 704 JOIN @ColumnNameAndData 705 AS C ON n <= @BitColumnByte 706 AND [System_Type_id] = 104 707 AND bitpos = 0 708 CROSS JOIN @bitTable 709 WHERE 710 C.[RowLogContents] = D.[RowLogContents] 711 ORDER BY [RowLogContents] , 712 n ASC 713 FOR 714 XML 715 PATH('') 716 ), 1, 1, ''), 717 ',', '') ), 718 bitpos + 1, 1))) 719 FROM @ColumnNameAndData D 720 WHERE [System_Type_id] = 104 721 ) 722 UPDATE A 723 SET [hex_Value] = [BitMap] 724 FROM @ColumnNameAndData A 725 INNER JOIN CTE B ON A.[RowLogContents] = B.[RowLogContents] 726 AND A.[nullbit] = B.[nullbit] 727 728 729 /**************Check for BLOB DATA TYPES******************************/ 730 DECLARE @Fileid INT 731 DECLARE @Pageid INT 732 DECLARE @Slotid INT 733 DECLARE @CurrentLSN INT 734 DECLARE @LinkID INT 735 DECLARE @Context VARCHAR(50) 736 DECLARE @ConsolidatedPageID VARCHAR(MAX) 737 DECLARE @LCX_TEXT_MIX VARBINARY(MAX) 738 739 DECLARE @temppagedata TABLE 740 ( 741 [ParentObject] SYSNAME , 742 [Object] SYSNAME , 743 [Field] SYSNAME , 744 [Value] SYSNAME 745 ) 746 747 DECLARE @pagedata TABLE 748 ( 749 [Page ID] SYSNAME , 750 [File IDS] INT , 751 [Page IDS] INT , 752 [AllocUnitId] BIGINT , 753 [ParentObject] SYSNAME , 754 [Object] SYSNAME , 755 [Field] SYSNAME , 756 [Value] SYSNAME 757 ) 758 759 DECLARE @ModifiedRawData TABLE 760 ( 761 [ID] INT IDENTITY(1, 1) , 762 [PAGE ID] VARCHAR(MAX) , 763 [FILE IDS] INT , 764 [PAGE IDS] INT , 765 [Slot ID] INT , 766 [AllocUnitId] BIGINT , 767 [RowLog Contents 0_var] VARCHAR(MAX) , 768 [RowLog Length] VARCHAR(50) , 769 [RowLog Len] INT , 770 [RowLog Contents 0] VARBINARY(MAX) , 771 [Link ID] INT DEFAULT ( 0 ) , 772 [Update] INT 773 ) 774 775 DECLARE Page_Data_Cursor CURSOR 776 FOR 777 /*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*/ 778 SELECT LTRIM(RTRIM(REPLACE([Description], 'Deallocated', ''))) AS [PAGE ID] , 779 [Slot ID] , 780 [AllocUnitId] , 781 NULL AS [RowLog Contents 0] , 782 NULL AS [RowLog Contents 0] , 783 Context 784 FROM sys.fn_dblog(NULL, NULL) 785 WHERE AllocUnitId IN ( 786 SELECT [Allocation_unit_id] 787 FROM sys.allocation_units allocunits 788 INNER JOIN sys.partitions partitions ON ( allocunits.type IN ( 789 1, 3 ) 790 AND partitions.hobt_id = allocunits.container_id 791 ) 792 OR ( allocunits.type = 2 793 AND partitions.partition_id = allocunits.container_id 794 ) 795 WHERE object_id = OBJECT_ID('' + @SchemaName_n_TableName 796 + '') ) 797 AND Operation IN ( 'LOP_MODIFY_ROW' ) 798 AND [Context] IN ( 'LCX_PFS' ) 799 AND Description LIKE '%Deallocated%' 800 /*Use this subquery to filter the date*/ 801 AND [TRANSACTION ID] IN ( 802 SELECT DISTINCT 803 [TRANSACTION ID] 804 FROM sys.fn_dblog(NULL, NULL) 805 WHERE Context IN ( 'LCX_NULL' ) 806 AND Operation IN ( 'LOP_BEGIN_XACT' ) 807 AND [Transaction Name] = 'DELETE' 808 AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN @Date_From 809 AND 810 @Date_To ) 811 GROUP BY [Description] , 812 [Slot ID] , 813 [AllocUnitId] , 814 Context 815 UNION 816 SELECT [PAGE ID] , 817 [Slot ID] , 818 [AllocUnitId] , 819 SUBSTRING([RowLog Contents 0], 15, 820 LEN([RowLog Contents 0])) AS [RowLog Contents 0] , 821 CONVERT(INT, SUBSTRING([RowLog Contents 0], 7, 2)) , 822 Context --,CAST(RIGHT([Current LSN],4) AS INT) AS [Current LSN] 823 FROM sys.fn_dblog(NULL, NULL) 824 WHERE AllocUnitId IN ( 825 SELECT [Allocation_unit_id] 826 FROM sys.allocation_units allocunits 827 INNER JOIN sys.partitions partitions ON ( allocunits.type IN ( 828 1, 3 ) 829 AND partitions.hobt_id = allocunits.container_id 830 ) 831 OR ( allocunits.type = 2 832 AND partitions.partition_id = allocunits.container_id 833 ) 834 WHERE object_id = OBJECT_ID('' + @SchemaName_n_TableName 835 + '') ) 836 AND Context IN ( 'LCX_TEXT_MIX' ) 837 AND Operation IN ( 'LOP_DELETE_ROWS' ) 838 /*Use this subquery to filter the date*/ 839 AND [TRANSACTION ID] IN ( 840 SELECT DISTINCT 841 [TRANSACTION ID] 842 FROM sys.fn_dblog(NULL, NULL) 843 WHERE Context IN ( 'LCX_NULL' ) 844 AND Operation IN ( 'LOP_BEGIN_XACT' ) 845 AND [Transaction Name] = 'DELETE' 846 AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN @Date_From 847 AND 848 @Date_To ) 849 850 /****************************************/ 851 852 OPEN Page_Data_Cursor 853 854 FETCH NEXT FROM Page_Data_Cursor INTO @ConsolidatedPageID, @Slotid, 855 @AllocUnitID, @LCX_TEXT_MIX, @LinkID, @Context 856 857 WHILE @@FETCH_STATUS = 0 858 BEGIN 859 DECLARE @hex_pageid AS VARCHAR(MAX) 860 /*Page ID contains File Number and page number It looks like 0001:00000130. 861 In this example 0001 is file Number & 00000130 is Page Number & These numbers are in Hex format*/ 862 SET @Fileid = SUBSTRING(@ConsolidatedPageID, 0, 863 CHARINDEX(':', @ConsolidatedPageID)) -- Seperate File ID from Page ID 864 865 SET @hex_pageid = '0x' + SUBSTRING(@ConsolidatedPageID, 866 CHARINDEX(':', 867 @ConsolidatedPageID) 868 + 1, LEN(@ConsolidatedPageID)) ---Seperate the page ID 869 SELECT @Pageid = CONVERT(INT, CAST('' AS XML).value('xs:hexBinary(substring(sql:variable("@hex_pageid"),sql:column("t.pos")) )', 870 'varbinary(max)')) -- Convert Page ID from hex to integer 871 FROM ( SELECT CASE SUBSTRING(@hex_pageid, 1, 2) 872 WHEN '0x' THEN 3 873 ELSE 0 874 END 875 ) AS t ( pos ) 876 877 IF @Context = 'LCX_PFS' 878 BEGIN 879 DELETE @temppagedata 880 INSERT INTO @temppagedata 881 EXEC 882 ( 'DBCC PAGE(' + @DataBase_Name + ', ' 883 + @fileid + ', ' + @pageid 884 + ', 1) with tableresults,no_infomsgs;' 885 ); 886 INSERT INTO @pagedata 887 SELECT @ConsolidatedPageID , 888 @fileid , 889 @pageid , 890 @AllocUnitID , 891 [ParentObject] , 892 [Object] , 893 [Field] , 894 [Value] 895 FROM @temppagedata 896 END 897 ELSE 898 IF @Context = 'LCX_TEXT_MIX' 899 BEGIN 900 INSERT INTO @ModifiedRawData 901 SELECT @ConsolidatedPageID , 902 @fileid , 903 @pageid , 904 @Slotid , 905 @AllocUnitID , 906 NULL , 907 0 , 908 CONVERT(INT, CONVERT(VARBINARY, REVERSE(SUBSTRING(@LCX_TEXT_MIX, 909 11, 2)))) , 910 @LCX_TEXT_MIX , 911 @LinkID , 912 0 913 END 914 FETCH NEXT FROM Page_Data_Cursor INTO @ConsolidatedPageID, @Slotid, 915 @AllocUnitID, @LCX_TEXT_MIX, @LinkID, @Context 916 END 917 918 CLOSE Page_Data_Cursor 919 DEALLOCATE Page_Data_Cursor 920 921 DECLARE @Newhexstring VARCHAR(MAX); 922 923 --The data is in multiple rows in the page, so we need to convert it into one row as a single hex value. 924 --This hex value is in string format 925 INSERT INTO @ModifiedRawData 926 ( [PAGE ID] , 927 [FILE IDS] , 928 [PAGE IDS] , 929 [Slot ID] , 930 [AllocUnitId] , 931 [RowLog Contents 0_var] , 932 [RowLog Length] 933 ) 934 SELECT [Page ID] , 935 [FILE IDS] , 936 [PAGE IDS] , 937 SUBSTRING([ParentObject], 938 CHARINDEX('Slot', [ParentObject]) + 4, 939 ( CHARINDEX('Offset', [ParentObject]) 940 - ( CHARINDEX('Slot', [ParentObject]) + 4 ) ) 941 - 2) AS [Slot ID] , 942 [AllocUnitId] , 943 SUBSTRING(( SELECT REPLACE(STUFF(( SELECT 944 REPLACE(SUBSTRING([Value], 945 CHARINDEX(':', 946 [Value]) + 1, 947 CHARINDEX('†', 948 [Value]) 949 - CHARINDEX(':', 950 [Value])), '†', 951 '') 952 FROM @pagedata C 953 WHERE B.[Page ID] = C.[Page ID] 954 AND SUBSTRING(B.[ParentObject], 955 CHARINDEX('Slot', 956 B.[ParentObject]) 957 + 4, 958 ( CHARINDEX('Offset', 959 B.[ParentObject]) 960 - ( CHARINDEX('Slot', 961 B.[ParentObject]) 962 + 4 ) )) = SUBSTRING(C.[ParentObject], 963 CHARINDEX('Slot', 964 C.[ParentObject]) 965 + 4, 966 ( CHARINDEX('Offset', 967 C.[ParentObject]) 968 - ( CHARINDEX('Slot', 969 C.[ParentObject]) 970 + 4 ) )) 971 AND [Object] LIKE '%Memory Dump%' 972 ORDER BY '0x' 973 + LEFT([Value], 974 CHARINDEX(':', 975 [Value]) - 1) 976 FOR 977 XML PATH('') 978 ), 1, 1, ''), ' ', '') 979 ), 1, 20000) AS [Value] , 980 SUBSTRING(( SELECT '0x' 981 + REPLACE(STUFF(( SELECT 982 REPLACE(SUBSTRING([Value], 983 CHARINDEX(':', 984 [Value]) + 1, 985 CHARINDEX('†', 986 [Value]) 987 - CHARINDEX(':', 988 [Value])), '†', 989 '') 990 FROM 991 @pagedata C 992 WHERE 993 B.[Page ID] = C.[Page ID] 994 AND SUBSTRING(B.[ParentObject], 995 CHARINDEX('Slot', 996 B.[ParentObject]) 997 + 4, 998 ( CHARINDEX('Offset', 999 B.[ParentObject]) 1000 - ( CHARINDEX('Slot', 1001 B.[ParentObject]) 1002 + 4 ) )) = SUBSTRING(C.[ParentObject], 1003 CHARINDEX('Slot', 1004 C.[ParentObject]) 1005 + 4, 1006 ( CHARINDEX('Offset', 1007 C.[ParentObject]) 1008 - ( CHARINDEX('Slot', 1009 C.[ParentObject]) 1010 + 4 ) )) 1011 AND [Object] LIKE '%Memory Dump%' 1012 ORDER BY '0x' 1013 + LEFT([Value], 1014 CHARINDEX(':', 1015 [Value]) - 1) 1016 FOR 1017 XML PATH('') 1018 ), 1, 1, ''), ' ', '') 1019 ), 7, 4) AS [Length] 1020 FROM @pagedata B 1021 WHERE [Object] LIKE '%Memory Dump%' 1022 GROUP BY [Page ID] , 1023 [FILE IDS] , 1024 [PAGE IDS] , 1025 [ParentObject] , 1026 [AllocUnitId]--,[Current LSN] 1027 ORDER BY [Slot ID] 1028 1029 UPDATE @ModifiedRawData 1030 SET [RowLog Len] = CONVERT(VARBINARY(8000), REVERSE(CAST('' AS XML).value('xs:hexBinary(substring(sql:column("[RowLog Length]"),0))', 1031 'varbinary(Max)'))) 1032 FROM @ModifiedRawData 1033 WHERE [LINK ID] = 0 1034 1035 UPDATE @ModifiedRawData 1036 SET [RowLog Contents 0] = CAST('' AS XML).value('xs:hexBinary(substring(sql:column("[RowLog Contents 0_var]"),0))', 1037 'varbinary(Max)') 1038 FROM @ModifiedRawData 1039 WHERE [LINK ID] = 0 1040 1041 UPDATE B 1042 SET B.[RowLog Contents 0] = ( CASE WHEN A.[RowLog Contents 0] IS NOT NULL 1043 AND C.[RowLog Contents 0] IS NOT NULL 1044 THEN A.[RowLog Contents 0] 1045 + C.[RowLog Contents 0] 1046 WHEN A.[RowLog Contents 0] IS NULL 1047 AND C.[RowLog Contents 0] IS NOT NULL 1048 THEN C.[RowLog Contents 0] 1049 WHEN A.[RowLog Contents 0] IS NOT NULL 1050 AND C.[RowLog Contents 0] IS NULL 1051 THEN A.[RowLog Contents 0] 1052 END ) , 1053 B.[Update] = ISNULL(B.[Update], 0) + 1 1054 FROM @ModifiedRawData B 1055 LEFT JOIN @ModifiedRawData A ON A.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1056 15 + 14, 2)))) 1057 AND A.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1058 19 + 14, 2)))) 1059 AND A.[Link ID] = B.[Link ID] 1060 LEFT JOIN @ModifiedRawData C ON C.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1061 27 + 14, 2)))) 1062 AND C.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1063 31 + 14, 2)))) 1064 AND C.[Link ID] = B.[Link ID] 1065 WHERE ( A.[RowLog Contents 0] IS NOT NULL 1066 OR C.[RowLog Contents 0] IS NOT NULL 1067 ) 1068 1069 1070 UPDATE B 1071 SET B.[RowLog Contents 0] = ( CASE WHEN A.[RowLog Contents 0] IS NOT NULL 1072 AND C.[RowLog Contents 0] IS NOT NULL 1073 THEN A.[RowLog Contents 0] 1074 + C.[RowLog Contents 0] 1075 WHEN A.[RowLog Contents 0] IS NULL 1076 AND C.[RowLog Contents 0] IS NOT NULL 1077 THEN C.[RowLog Contents 0] 1078 WHEN A.[RowLog Contents 0] IS NOT NULL 1079 AND C.[RowLog Contents 0] IS NULL 1080 THEN A.[RowLog Contents 0] 1081 END ) 1082 --,B.[Update]=ISNULL(B.[Update],0)+1 1083 FROM @ModifiedRawData B 1084 LEFT JOIN @ModifiedRawData A ON A.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1085 15 + 14, 2)))) 1086 AND A.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1087 19 + 14, 2)))) 1088 AND A.[Link ID] <> B.[Link ID] 1089 AND B.[Update] = 0 1090 LEFT JOIN @ModifiedRawData C ON C.[Page IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1091 27 + 14, 2)))) 1092 AND C.[File IDS] = CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(B.[RowLog Contents 0], 1093 31 + 14, 2)))) 1094 AND C.[Link ID] <> B.[Link ID] 1095 AND B.[Update] = 0 1096 WHERE ( A.[RowLog Contents 0] IS NOT NULL 1097 OR C.[RowLog Contents 0] IS NOT NULL 1098 ) 1099 1100 UPDATE @ModifiedRawData 1101 SET [RowLog Contents 0] = ( CASE WHEN [RowLog Len] >= 8000 1102 THEN SUBSTRING([RowLog Contents 0], 1103 15, [RowLog Len]) 1104 WHEN [RowLog Len] < 8000 1105 THEN SUBSTRING([RowLog Contents 0], 1106 15 + 6, 1107 CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([RowLog Contents 0], 1108 15, 6))))) 1109 END ) 1110 FROM @ModifiedRawData 1111 WHERE [LINK ID] = 0 1112 1113 UPDATE @ColumnNameAndData 1114 SET [hex_Value] = [RowLog Contents 0] 1115 --,A.[Update]=A.[Update]+1 1116 FROM @ColumnNameAndData A 1117 INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value], 1118 17, 4)))) = [PAGE IDS] 1119 AND CONVERT(INT, SUBSTRING([hex_value], 1120 9, 2)) = B.[Link ID] 1121 WHERE [System_Type_Id] IN ( 99, 167, 175, 231, 239, 241, 165, 98 ) 1122 AND [Link ID] <> 0 1123 1124 UPDATE @ColumnNameAndData 1125 SET [hex_Value] = ( CASE WHEN B.[RowLog Contents 0] IS NOT NULL 1126 AND C.[RowLog Contents 0] IS NOT NULL 1127 THEN B.[RowLog Contents 0] 1128 + C.[RowLog Contents 0] 1129 WHEN B.[RowLog Contents 0] IS NULL 1130 AND C.[RowLog Contents 0] IS NOT NULL 1131 THEN C.[RowLog Contents 0] 1132 WHEN B.[RowLog Contents 0] IS NOT NULL 1133 AND C.[RowLog Contents 0] IS NULL 1134 THEN B.[RowLog Contents 0] 1135 END ) 1136 --,A.[Update]=A.[Update]+1 1137 FROM @ColumnNameAndData A 1138 LEFT JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value], 1139 5, 4)))) = B.[PAGE IDS] 1140 AND B.[Link ID] = 0 1141 LEFT JOIN @ModifiedRawData C ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value], 1142 17, 4)))) = C.[PAGE IDS] 1143 AND C.[Link ID] = 0 1144 WHERE [System_Type_Id] IN ( 99, 167, 175, 231, 239, 241, 165, 98 ) 1145 AND ( B.[RowLog Contents 0] IS NOT NULL 1146 OR C.[RowLog Contents 0] IS NOT NULL 1147 ) 1148 1149 UPDATE @ColumnNameAndData 1150 SET [hex_Value] = [RowLog Contents 0] 1151 --,A.[Update]=A.[Update]+1 1152 FROM @ColumnNameAndData A 1153 INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value], 1154 9, 4)))) = [PAGE IDS] 1155 AND CONVERT(INT, SUBSTRING([hex_value], 1156 3, 2)) = [Link ID] 1157 WHERE [System_Type_Id] IN ( 35, 34, 99 ) 1158 AND [Link ID] <> 0 1159 1160 UPDATE @ColumnNameAndData 1161 SET [hex_Value] = [RowLog Contents 0] 1162 --,A.[Update]=A.[Update]+10 1163 FROM @ColumnNameAndData A 1164 INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value], 1165 9, 4)))) = [PAGE IDS] 1166 WHERE [System_Type_Id] IN ( 35, 34, 99 ) 1167 AND [Link ID] = 0 1168 1169 UPDATE @ColumnNameAndData 1170 SET [hex_Value] = [RowLog Contents 0] 1171 --,A.[Update]=A.[Update]+1 1172 FROM @ColumnNameAndData A 1173 INNER JOIN @ModifiedRawData B ON CONVERT(INT, CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING([hex_value], 1174 15, 4)))) = [PAGE IDS] 1175 WHERE [System_Type_Id] IN ( 35, 34, 99 ) 1176 AND [Link ID] = 0 1177 1178 UPDATE @ColumnNameAndData 1179 SET [hex_value] = 0xFFFE + SUBSTRING([hex_value], 9, LEN([hex_value])) 1180 --,[Update]=[Update]+1 1181 WHERE [system_type_id] = 241 1182 1183 CREATE TABLE [#temp_Data] 1184 ( 1185 [FieldName] VARCHAR(MAX) , 1186 [FieldValue] NVARCHAR(MAX) , 1187 [Rowlogcontents] VARBINARY(8000) , 1188 [Row ID] INT 1189 ) 1190 1191 INSERT INTO #temp_Data 1192 SELECT NAME , 1193 CASE WHEN system_type_id IN ( 231, 239 ) 1194 THEN LTRIM(RTRIM(CONVERT(NVARCHAR(MAX), hex_Value))) --NVARCHAR ,NCHAR 1195 WHEN system_type_id IN ( 167, 175 ) 1196 THEN LTRIM(RTRIM(CONVERT(VARCHAR(MAX), hex_Value))) --VARCHAR,CHAR 1197 WHEN system_type_id IN ( 35 ) 1198 THEN LTRIM(RTRIM(CONVERT(VARCHAR(MAX), hex_Value))) --Text 1199 WHEN system_type_id IN ( 99 ) 1200 THEN LTRIM(RTRIM(CONVERT(NVARCHAR(MAX), hex_Value))) --nText 1201 WHEN system_type_id = 48 1202 THEN CONVERT(VARCHAR(MAX), CONVERT(TINYINT, CONVERT(BINARY(1), REVERSE(hex_Value)))) --TINY INTEGER 1203 WHEN system_type_id = 52 1204 THEN CONVERT(VARCHAR(MAX), CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(hex_Value)))) --SMALL INTEGER 1205 WHEN system_type_id = 56 1206 THEN CONVERT(VARCHAR(MAX), CONVERT(INT, CONVERT(BINARY(4), REVERSE(hex_Value)))) -- INTEGER 1207 WHEN system_type_id = 127 1208 THEN CONVERT(VARCHAR(MAX), CONVERT(BIGINT, CONVERT(BINARY(8), REVERSE(hex_Value))))-- BIG INTEGER 1209 WHEN system_type_id = 61 1210 THEN CONVERT(VARCHAR(MAX), CONVERT(DATETIME, CONVERT(VARBINARY(8000), REVERSE(hex_Value))), 100) --DATETIME 1211 WHEN system_type_id = 58 1212 THEN CONVERT(VARCHAR(MAX), CONVERT(SMALLDATETIME, CONVERT(VARBINARY(8000), REVERSE(hex_Value))), 100) --SMALL DATETIME 1213 WHEN system_type_id = 108 1214 THEN CONVERT(VARCHAR(MAX), CONVERT(NUMERIC(38, 20), CONVERT(VARBINARY, CONVERT(VARBINARY(1), xprec) 1215 + CONVERT(VARBINARY(1), xscale)) 1216 + CONVERT(VARBINARY(1), 0) + hex_Value)) --- NUMERIC 1217 WHEN system_type_id = 106 1218 THEN CONVERT(VARCHAR(MAX), CONVERT(DECIMAL(38, 20), CONVERT(VARBINARY, CONVERT(VARBINARY(1), xprec) 1219 + CONVERT(VARBINARY(1), xscale)) 1220 + CONVERT(VARBINARY(1), 0) + hex_Value)) --- DECIMAL 1221 WHEN system_type_id IN ( 60, 122 ) 1222 THEN CONVERT(VARCHAR(MAX), CONVERT(MONEY, CONVERT(VARBINARY(8000), REVERSE(hex_Value))), 2) --MONEY,SMALLMONEY 1223 WHEN system_type_id = 104 1224 THEN CONVERT(VARCHAR(MAX), CONVERT (BIT, CONVERT(BINARY(1), hex_Value) 1225 % 2)) -- BIT 1226 WHEN system_type_id = 62 1227 THEN RTRIM(LTRIM(STR(CONVERT(FLOAT, SIGN(CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT)) 1228 * ( 1.0 1229 + ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT) 1230 & 0x000FFFFFFFFFFFFF ) 1231 * POWER(CAST(2 AS FLOAT), 1232 -52) ) 1233 * POWER(CAST(2 AS FLOAT), 1234 ( ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT) 1235 & 0x7ff0000000000000 ) 1236 / EXP(52 * LOG(2)) 1237 - 1023 ))), 53, 1238 LEN(hex_Value)))) --- FLOAT 1239 WHEN system_type_id = 59 1240 THEN LEFT(LTRIM(STR(CAST(SIGN(CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT)) 1241 * ( 1.0 1242 + ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS BIGINT) 1243 & 0x007FFFFF ) 1244 * POWER(CAST(2 AS REAL), -23) ) 1245 * POWER(CAST(2 AS REAL), 1246 ( ( ( CAST(CONVERT(VARBINARY(8000), REVERSE(hex_Value)) AS INT) ) 1247 & 0x7f800000 ) 1248 / EXP(23 * LOG(2)) 1249 - 127 )) AS REAL), 23, 1250 23)), 8) --Real 1251 WHEN system_type_id IN ( 165, 173 ) 1252 THEN ( CASE WHEN CHARINDEX(0x, 1253 CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1254 'VARBINARY(8000)')) = 0 1255 THEN '0x' 1256 ELSE '' 1257 END ) + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1258 'varchar(max)') -- BINARY,VARBINARY 1259 WHEN system_type_id = 34 1260 THEN ( CASE WHEN CHARINDEX(0x, 1261 CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1262 'VARBINARY(8000)')) = 0 1263 THEN '0x' 1264 ELSE '' 1265 END ) + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1266 'varchar(max)') --IMAGE 1267 WHEN system_type_id = 36 1268 THEN CONVERT(VARCHAR(MAX), CONVERT(UNIQUEIDENTIFIER, hex_Value)) --UNIQUEIDENTIFIER 1269 WHEN system_type_id = 231 1270 THEN CONVERT(VARCHAR(MAX), CONVERT(SYSNAME, hex_Value)) --SYSNAME 1271 WHEN system_type_id = 241 1272 THEN CONVERT(VARCHAR(MAX), CONVERT(XML, hex_Value)) --XML 1273 WHEN system_type_id = 189 1274 THEN ( CASE WHEN CHARINDEX(0x, 1275 CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1276 'VARBINARY(8000)')) = 0 1277 THEN '0x' 1278 ELSE '' 1279 END ) + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1280 'varchar(max)') --TIMESTAMP 1281 WHEN system_type_id = 98 1282 THEN ( CASE WHEN CONVERT(INT, SUBSTRING(hex_Value, 1, 1283 1)) = 56 1284 THEN CONVERT(VARCHAR(MAX), CONVERT(INT, CONVERT(BINARY(4), REVERSE(SUBSTRING(hex_Value, 1285 3, 1286 LEN(hex_Value)))))) -- INTEGER 1287 WHEN CONVERT(INT, SUBSTRING(hex_Value, 1, 1288 1)) = 108 1289 THEN CONVERT(VARCHAR(MAX), CONVERT(NUMERIC(38, 1290 20), CONVERT(VARBINARY(1), SUBSTRING(hex_Value, 1291 3, 1)) 1292 + CONVERT(VARBINARY(1), SUBSTRING(hex_Value, 1293 4, 1)) 1294 + CONVERT(VARBINARY(1), 0) 1295 + SUBSTRING(hex_Value, 5, 1296 LEN(hex_Value)))) --- NUMERIC 1297 WHEN CONVERT(INT, SUBSTRING(hex_Value, 1, 1298 1)) = 167 1299 THEN LTRIM(RTRIM(CONVERT(VARCHAR(MAX), SUBSTRING(hex_Value, 1300 9, 1301 LEN(hex_Value))))) --VARCHAR,CHAR 1302 WHEN CONVERT(INT, SUBSTRING(hex_Value, 1, 1303 1)) = 36 1304 THEN CONVERT(VARCHAR(MAX), CONVERT(UNIQUEIDENTIFIER, SUBSTRING(( hex_Value ), 1305 3, 20))) --UNIQUEIDENTIFIER 1306 WHEN CONVERT(INT, SUBSTRING(hex_Value, 1, 1307 1)) = 61 1308 THEN CONVERT(VARCHAR(MAX), CONVERT(DATETIME, CONVERT(VARBINARY(8000), REVERSE(SUBSTRING(hex_Value, 1309 3, 1310 LEN(hex_Value))))), 100) --DATETIME 1311 WHEN CONVERT(INT, SUBSTRING(hex_Value, 1, 1312 1)) = 165 1313 THEN '0x' 1314 + SUBSTRING(( CASE WHEN CHARINDEX(0x, 1315 CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1316 'VARBINARY(8000)')) = 0 1317 THEN '0x' 1318 ELSE '' 1319 END ) 1320 + CAST('' AS XML).value('xs:hexBinary(sql:column("hex_Value"))', 1321 'varchar(max)'), 1322 11, LEN(hex_Value)) -- BINARY,VARBINARY 1323 END ) 1324 END AS FieldValue , 1325 [Rowlogcontents] , 1326 [Row ID] 1327 FROM @ColumnNameAndData 1328 ORDER BY nullbit 1329 1330 --Create the column name in the same order to do pivot table. 1331 1332 DECLARE @FieldName VARCHAR(MAX) 1333 SET @FieldName = STUFF(( SELECT ',' 1334 + CAST(QUOTENAME([Name]) AS VARCHAR(MAX)) 1335 FROM syscolumns 1336 WHERE id = OBJECT_ID('' 1337 + @SchemaName_n_TableName 1338 + '') 1339 FOR 1340 XML PATH('') 1341 ), 1, 1, '') 1342 1343 --Finally did pivot table and get the data back in the same format. 1344 1345 SET @sql = 'SELECT ' + @FieldName 1346 + ' FROM #temp_Data PIVOT (Min([FieldValue]) FOR FieldName IN (' 1347 + @FieldName + ')) AS pvt' 1348 EXEC sp_executesql @sql 1349
调用 EXEC Recover_Deleted_Data_Proc 'db','dbo.Test_Table'
或者EXEC Recover_Deleted_Data_Proc 'db','dbo.Test_Table','2012-06-01','2012-06-30'
引用 http://www.cnblogs.com/lyhabc/p/3683147.html