-- Script Name: Recover_Deleted_Data_Proc
-- Script Type : Recovery Procedure 
-- Develop By: Muhammad Imran
-- Date Created: 15 Oct 2011
-- Modify Date: 22 Aug 2012
-- Version    : 3.1
-- Notes : Included BLOB data types for recovery.& Compatibile with Default , CS collation , Arabic_CI_AS.
 
--DROP PROCEDURE Recover_Deleted_Data_Proc
--GO
  1. /*只能说令人叹服。。。还有谁。。。
    好吧,膜拜完大神开始正餐。。。
    */
  2.  
  3. --------------------------===========我是华丽的分割线=======-------------------------------------
    Create PROCEDURE Recover_Deleted_Data_Proc
  4. @Database_Name NVARCHAR(MAX),
  5. @SchemaName_n_TableName NVARCHAR(Max),
  6. @Date_From DATETIME='1900/01/01',
  7. @Date_To DATETIME ='9999/12/31'
  8. AS
  9.  
  10. DECLARE @RowLogContents VARBINARY(8000)
  11. DECLARE @TransactionID NVARCHAR(Max)
  12. DECLARE @AllocUnitID BIGINT
  13. DECLARE @AllocUnitName NVARCHAR(Max)
  14. DECLARE @SQL NVARCHAR(Max)
  15. DECLARE @Compatibility_Level INT
  16.  
  17. SELECT @Compatibility_Level=dtb.compatibility_level
  18. FROM
  19. master.sys.databases AS dtb WHERE dtb.name=@Database_Name
  20.  
  21. IF ISNULL(@Compatibility_Level,0)<=80
  22. BEGIN
  23. RAISERROR('The compatibility level should be equal to or greater SQL SERVER 2005 (90)',16,1)
  24. RETURN
  25. END
  26.  
  27. IF (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE [TABLE_SCHEMA]+'.'+[TABLE_NAME]=@SchemaName_n_TableName)=0
  28. BEGIN
  29. RAISERROR('Could not found the table in the defined database',16,1)
  30. RETURN
  31. END
  32.  
  33. DECLARE @bitTable TABLE
  34. (
  35. [ID] INT,
  36. [Bitvalue] INT
  37. )
  38. --Create table to set the bit position of one byte.
  39.  
  40. INSERT INTO @bitTable
  41. SELECT 0,2 UNION ALL
  42. SELECT 1,2 UNION ALL
  43. SELECT 2,4 UNION ALL
  44. SELECT 3,8 UNION ALL
  45. SELECT 4,16 UNION ALL
  46. SELECT 5,32 UNION ALL
  47. SELECT 6,64 UNION ALL
  48. SELECT 7,128
  49.  
  50. --Create table to collect the row data.
  51. DECLARE @DeletedRecords TABLE
  52. (
  53. [Row ID] INT IDENTITY(1,1),
  54. [RowLogContents] VARBINARY(8000),
  55. [AllocUnitID] BIGINT,
  56. [Transaction ID] NVARCHAR(Max),
  57. [FixedLengthData] SMALLINT,
  58. [TotalNoOfCols] SMALLINT,
  59. [NullBitMapLength] SMALLINT,
  60. [NullBytes] VARBINARY(8000),
  61. [TotalNoofVarCols] SMALLINT,
  62. [ColumnOffsetArray] VARBINARY(8000),
  63. [VarColumnStart] SMALLINT,
  64. [Slot ID] INT,
  65. [NullBitMap] VARCHAR(MAX)
  66.  
  67. )
  68. --Create a common table expression to get all the row data plus how many bytes we have for each row.
  69. ;WITH RowData AS (
  70. SELECT
  71.  
  72. [RowLog Contents 0] AS [RowLogContents]
  73.  
  74. ,[AllocUnitID] AS [AllocUnitID]
  75.  
  76. ,[Transaction ID] AS [Transaction ID]
  77.  
  78. --[Fixed Length Data] = Substring (RowLog content 0, Status Bit A+ Status Bit B + 1,2 bytes)
  79. ,CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) AS [FixedLengthData] --@FixedLengthData
  80.  
  81. -- [TotalnoOfCols] = Substring (RowLog content 0, [Fixed Length Data] + 1,2 bytes)
  82. ,CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  83. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2)))) as [TotalNoOfCols]
  84.  
  85. --[NullBitMapLength]=ceiling([Total No of Columns] /8.0)
  86. ,CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  87. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0)) as [NullBitMapLength]
  88.  
  89. --[Null Bytes] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [NullBitMapLength] )
  90. ,SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 3,
  91. CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  92. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0))) as [NullBytes]
  93.  
  94. --[TotalNoofVarCols] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 )
  95. ,(CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) In (0x10,0x30,0x70) THEN
  96. CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
  97. CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 3
  98. + CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  99. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0)), 2)))) ELSE null END) AS [TotalNoofVarCols]
  100.  
  101. --[ColumnOffsetArray]= Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 , [TotalNoofVarCols]*2 )
  102. ,(CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) In (0x10,0x30,0x70) THEN
  103. SUBSTRING([RowLog Contents 0]
  104. , CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 3
  105. + CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  106. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0)) + 2
  107. , (CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) In (0x10,0x30,0x70) THEN
  108. CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
  109. CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 3
  110. + CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  111. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0)), 2)))) ELSE null END)
  112. * 2) ELSE null END) AS [ColumnOffsetArray]
  113.  
  114. -- Variable column Start = Status Bit A+ Status Bit B + [Fixed Length Data] + [Null Bitmap length] + 2+([TotalNoofVarCols]*2)
  115. ,CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1)In (0x10,0x30,0x70)
  116. THEN (
  117. CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 4
  118.  
  119. + CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  120. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0))
  121.  
  122. + ((CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) In (0x10,0x30,0x70) THEN
  123. CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],
  124. CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 3
  125. + CONVERT(INT, ceiling(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0], CONVERT(SMALLINT, CONVERT(BINARY(2)
  126. ,REVERSE(SUBSTRING([RowLog Contents 0], 2 + 1, 2)))) + 1, 2))))/8.0)), 2)))) ELSE null END) * 2))
  127.  
  128. ELSE null End AS [VarColumnStart]
  129. ,[Slot ID]
  130. FROM sys.fn_dblog(NULL, NULL)
  131. WHERE
  132. AllocUnitId IN
  133. (SELECT [Allocation_unit_id] FROM sys.allocation_units allocunits
  134. INNER JOIN sys.partitions partitions ON (allocunits.type IN (1, 3)
  135. AND partitions.hobt_id = allocunits.container_id) OR (allocunits.type = 2
  136. AND partitions.partition_id = allocunits.container_id)
  137. WHERE object_id=object_ID('' + @SchemaName_n_TableName + ''))
  138.  
  139. AND Context IN ('LCX_MARK_AS_GHOST', 'LCX_HEAP') AND Operation in ('LOP_DELETE_ROWS')
  140. And SUBSTRING([RowLog Contents 0], 1, 1)In (0x10,0x30,0x70)
  141.  
  142. /*Use this subquery to filter the date*/
  143. AND [TRANSACTION ID] IN (SELECT DISTINCT [TRANSACTION ID] FROM sys.fn_dblog(NULL, NULL)
  144. WHERE Context IN ('LCX_NULL') AND Operation in ('LOP_BEGIN_XACT')
  145. And [Transaction Name] In ('DELETE','user_transaction')
  146. And CONVERT(NVARCHAR(11),[Begin Time]) BETWEEN @Date_From AND @Date_To)),
  147.  
  148. --Use this technique to repeate the row till the no of bytes of the row.
  149. N1 (n) AS (SELECT 1 UNION ALL SELECT 1),
  150. N2 (n) AS (SELECT 1 FROM N1 AS X, N1 AS Y),
  151. N3 (n) AS (SELECT 1 FROM N2 AS X, N2 AS Y),
  152. N4 (n) AS (SELECT ROW_NUMBER() OVER(ORDER BY X.n)
  153. FROM N3 AS X, N3 AS Y)
  154.  
  155. INSERT INTO @DeletedRecords
  156. SELECT RowLogContents
  157. ,[AllocUnitID]
  158. ,[Transaction ID]
  159. ,[FixedLengthData]
  160. ,[TotalNoOfCols]
  161. ,[NullBitMapLength]
  162. ,[NullBytes]
  163. ,[TotalNoofVarCols]
  164. ,[ColumnOffsetArray]
  165. ,[VarColumnStart]
  166. ,[Slot ID]
  167. ---Get the Null value against each column (1 means null zero means not null)
  168. ,[NullBitMap]=(REPLACE(STUFF((SELECT ',' +
  169. (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]
  170.  
  171. FROM
  172. N4 AS Nums
  173. Join RowData AS C ON n<=NullBitMapLength
  174. Cross Join @bitTable WHERE C.[RowLogContents]=D.[RowLogContents] ORDER BY [RowLogContents],n ASC FOR XML PATH('')),1,1,''),',',''))
  175. FROM RowData D
  176.  
  177. IF (SELECT COUNT(*) FROM @DeletedRecords)=0
  178. BEGIN
  179. RAISERROR('There is no data in the log as per the search criteria',16,1)
  180. RETURN
  181. END
  182.  
  183. DECLARE @ColumnNameAndData TABLE
  184. (
  185. [Row ID] int,
  186. [Rowlogcontents] varbinary(Max),
  187. [NAME] sysname,
  188. [nullbit] smallint,
  189. [leaf_offset] smallint,
  190. [length] smallint,
  191. [system_type_id] tinyint,
  192. [bitpos] tinyint,
  193. [xprec] tinyint,
  194. [xscale] tinyint,
  195. [is_null] int,
  196. [Column value Size]int,
  197. [Column Length] int,
  198. [hex_Value] varbinary(max),
  199. [Slot ID] int,
  200. [Update] int
  201. )
  202.  
  203. --Create common table expression and join it with the rowdata table
  204. -- to get each column details
  205. /*This part is for variable data columns*/
  206. --@RowLogContents,
  207. --(col.columnOffValue - col.columnLength) + 1,
  208. --col.columnLength
  209. --)
  210. INSERT INTO @ColumnNameAndData
  211. SELECT
  212. [Row ID],
  213. Rowlogcontents,
  214. NAME ,
  215. cols.leaf_null_bit AS nullbit,
  216. leaf_offset,
  217. ISNULL(syscolumns.length, cols.max_length) AS [length],
  218. cols.system_type_id,
  219. cols.leaf_bit_position AS bitpos,
  220. ISNULL(syscolumns.xprec, cols.precision) AS xprec,
  221. ISNULL(syscolumns.xscale, cols.scale) AS xscale,
  222. SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null,
  223. (CASE WHEN leaf_offset<1 and SUBSTRING([nullBitMap], cols.leaf_null_bit, 1)=0
  224. THEN
  225. (Case When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000
  226. THEN
  227. CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) - POWER(2, 15)
  228. ELSE
  229. CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  230. END)
  231. END) AS [Column value Size],
  232.  
  233. (CASE WHEN leaf_offset<1 and SUBSTRING([nullBitMap], cols.leaf_null_bit, 1)=0 THEN
  234. (Case
  235.  
  236. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000 And
  237. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])<30000
  238. THEN (Case When [System_type_id]In (35,34,99) Then 16 else 24 end)
  239.  
  240. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000 And
  241. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])>30000
  242. THEN (Case When [System_type_id]In (35,34,99) Then 16 else 24 end) --24
  243.  
  244. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) <30000 And
  245. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])<30000
  246. THEN (CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  247. - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart]))
  248.  
  249. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) <30000 And
  250. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])>30000
  251.  
  252. THEN POWER(2, 15) +CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  253. - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])
  254.  
  255. END)
  256.  
  257. END) AS [Column Length]
  258.  
  259. ,(CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1)=1 THEN NULL ELSE
  260. SUBSTRING
  261. (
  262. Rowlogcontents,
  263. (
  264.  
  265. (Case When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000
  266. THEN
  267. CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) - POWER(2, 15)
  268. ELSE
  269. CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  270. END)
  271.  
  272. -
  273. (Case When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000 And
  274. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])<30000
  275.  
  276. THEN (Case When [System_type_id]In (35,34,99) Then 16 else 24 end) --24
  277. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000 And
  278. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])>30000
  279.  
  280. THEN (Case When [System_type_id]In (35,34,99) Then 16 else 24 end) --24
  281. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) <30000 And
  282. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])<30000
  283.  
  284. THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  285. - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])
  286.  
  287. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) <30000 And
  288. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])>30000
  289.  
  290. THEN POWER(2, 15) +CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  291. - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])
  292.  
  293. END)
  294.  
  295. ) + 1,
  296. (Case When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000 And
  297. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])<30000
  298.  
  299. THEN (Case When [System_type_id] In (35,34,99) Then 16 else 24 end) --24
  300. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) >30000 And
  301. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])>30000
  302.  
  303. THEN (Case When [System_type_id] In (35,34,99) Then 16 else 24 end) --24
  304. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) <30000 And
  305. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])<30000
  306.  
  307. THEN ABS(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  308. - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart]))
  309.  
  310. When CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2)))) <30000 And
  311. ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])>30000
  312.  
  313. THEN POWER(2, 15) +CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * leaf_offset*-1) - 1, 2))))
  314. - ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE (SUBSTRING ([ColumnOffsetArray], (2 * ((leaf_offset*-1) - 1)) - 1, 2)))), 0), [varColumnStart])
  315.  
  316. END)
  317. )
  318.  
  319. END) AS hex_Value
  320. ,[Slot ID]
  321. ,0
  322. FROM @DeletedRecords A
  323. Inner Join sys.allocation_units allocunits On A.[AllocUnitId]=allocunits.[Allocation_Unit_Id]
  324. INNER JOIN sys.partitions partitions ON (allocunits.type IN (1, 3)
  325. AND partitions.hobt_id = allocunits.container_id) OR (allocunits.type = 2 AND partitions.partition_id = allocunits.container_id)
  326. INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_id
  327. LEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_id AND syscolumns.colid = cols.partition_column_id
  328. WHERE leaf_offset<0
  329. UNION
  330. /*This part is for fixed data columns*/
  331. SELECT
  332. [Row ID],
  333. Rowlogcontents,
  334. NAME ,
  335. cols.leaf_null_bit AS nullbit,
  336. leaf_offset,
  337. ISNULL(syscolumns.length, cols.max_length) AS [length],
  338. cols.system_type_id,
  339. cols.leaf_bit_position AS bitpos,
  340. ISNULL(syscolumns.xprec, cols.precision) AS xprec,
  341. ISNULL(syscolumns.xscale, cols.scale) AS xscale,
  342. SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null,
  343. (SELECT TOP 1 ISNULL(SUM(CASE WHEN C.leaf_offset >1 THEN max_length ELSE 0 END),0) FROM
  344. 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],
  345. syscolumns.length AS [Column Length]
  346.  
  347. ,CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1)=1 THEN NULL ELSE
  348. SUBSTRING
  349. (
  350. 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
  351. sys.system_internals_partition_columns C where cols.partition_id =C.partition_id And C.leaf_null_bit<cols.leaf_null_bit)+5
  352. ,syscolumns.length) END AS hex_Value
  353. ,[Slot ID]
  354. ,0
  355. FROM @DeletedRecords A
  356. Inner Join sys.allocation_units allocunits ON A.[AllocUnitId]=allocunits.[Allocation_Unit_Id]
  357. INNER JOIN sys.partitions partitions ON (allocunits.type IN (1, 3)
  358. AND partitions.hobt_id = allocunits.container_id) OR (allocunits.type = 2 AND partitions.partition_id = allocunits.container_id)
  359. INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_id
  360. LEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_id AND syscolumns.colid = cols.partition_column_id
  361. WHERE leaf_offset>0
  362. Order By nullbit
  363.  
  364. Declare @BitColumnByte as int
  365. Select @BitColumnByte=CONVERT(INT, ceiling( Count(*)/8.0)) from @ColumnNameAndData Where [System_Type_id]=104
  366.  
  367. ;With N1 (n) AS (SELECT 1 UNION ALL SELECT 1),
  368. N2 (n) AS (SELECT 1 FROM N1 AS X, N1 AS Y),
  369. N3 (n) AS (SELECT 1 FROM N2 AS X, N2 AS Y),
  370. N4 (n) AS (SELECT ROW_NUMBER() OVER(ORDER BY X.n)
  371. FROM N3 AS X, N3 AS Y),
  372. CTE As(
  373. Select RowLogContents,[nullbit]
  374. ,[BitMap]=Convert(varbinary(1),Convert(int,Substring((REPLACE(STUFF((SELECT ',' +
  375. (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]
  376.  
  377. from N4 AS Nums
  378. Join @ColumnNameAndData AS C ON n<=@BitColumnByte And [System_Type_id]=104 And bitpos=0
  379. Cross Join @bitTable WHERE C.[RowLogContents]=D.[RowLogContents] ORDER BY [RowLogContents],n ASC FOR XML PATH('')),1,1,''),',','')),bitpos+1,1)))
  380. FROM @ColumnNameAndData D Where [System_Type_id]=104)
  381.  
  382. Update A Set [hex_Value]=[BitMap]
  383. from @ColumnNameAndData A
  384. Inner Join CTE B On A.[RowLogContents]=B.[RowLogContents]
  385. And A.[nullbit]=B.[nullbit]
  386.  
  387. /**************Check for BLOB DATA TYPES******************************/
  388. DECLARE @Fileid INT
  389. DECLARE @Pageid INT
  390. DECLARE @Slotid INT
  391. DECLARE @CurrentLSN INT
  392. DECLARE @LinkID INT
  393. DECLARE @Context VARCHAR(50)
  394. DECLARE @ConsolidatedPageID VARCHAR(MAX)
  395. DECLARE @LCX_TEXT_MIX VARBINARY(MAX)
  396.  
  397. declare @temppagedata table
  398. (
  399. [ParentObject] sysname,
  400. [Object] sysname,
  401. [Field] sysname,
  402. [Value] sysname)
  403.  
  404. declare @pagedata table
  405. (
  406. [Page ID] sysname,
  407. [File IDS] int,
  408. [Page IDS] int,
  409. [AllocUnitId] bigint,
  410. [ParentObject] sysname,
  411. [Object] sysname,
  412. [Field] sysname,
  413. [Value] sysname)
  414.  
  415. DECLARE @ModifiedRawData TABLE
  416. (
  417. [ID] INT IDENTITY(1,1),
  418. [PAGE ID] VARCHAR(MAX),
  419. [FILE IDS] INT,
  420. [PAGE IDS] INT,
  421. [Slot ID] INT,
  422. [AllocUnitId] BIGINT,
  423. [RowLog Contents 0_var] VARCHAR(Max),
  424. [RowLog Length] VARCHAR(50),
  425. [RowLog Len] INT,
  426. [RowLog Contents 0] VARBINARY(Max),
  427. [Link ID] INT default (0),
  428. [Update] INT
  429. )
  430.  
  431. DECLARE Page_Data_Cursor CURSOR FOR
  432. /*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*/
  433. SELECT LTRIM(RTRIM(Replace([Description],'Deallocated',''))) AS [PAGE ID]
  434. ,[Slot ID],[AllocUnitId],NULL AS [RowLog Contents 0],NULL AS [RowLog Contents 0],Context
  435. FROM sys.fn_dblog(NULL, NULL)
  436. WHERE
  437. AllocUnitId IN
  438. (SELECT [Allocation_unit_id] FROM sys.allocation_units allocunits
  439. INNER JOIN sys.partitions partitions ON (allocunits.type IN (1, 3)
  440. AND partitions.hobt_id = allocunits.container_id) OR (allocunits.type = 2
  441. AND partitions.partition_id = allocunits.container_id)
  442. WHERE object_id=object_ID('' + @SchemaName_n_TableName + ''))
  443. AND Operation IN ('LOP_MODIFY_ROW') AND [Context] IN ('LCX_PFS')
  444. AND Description Like '%Deallocated%'
  445. /*Use this subquery to filter the date*/
  446. AND [TRANSACTION ID] IN (SELECT DISTINCT [TRANSACTION ID] FROM sys.fn_dblog(NULL, NULL)
  447. WHERE Context IN ('LCX_NULL') AND Operation in ('LOP_BEGIN_XACT')
  448. AND [Transaction Name]='DELETE'
  449. AND CONVERT(NVARCHAR(11),[Begin Time]) BETWEEN @Date_From AND @Date_To)
  450. GROUP BY [Description],[Slot ID],[AllocUnitId],Context
  451.  
  452. UNION
  453.  
  454. SELECT [PAGE ID],[Slot ID],[AllocUnitId]
  455. ,Substring([RowLog Contents 0],15,LEN([RowLog Contents 0])) AS [RowLog Contents 0]
  456. ,CONVERT(INT,Substring([RowLog Contents 0],7,2)),Context --,CAST(RIGHT([Current LSN],4) AS INT) AS [Current LSN]
  457. FROM sys.fn_dblog(NULL, NULL)
  458. WHERE
  459. AllocUnitId IN
  460. (SELECT [Allocation_unit_id] FROM sys.allocation_units allocunits
  461. INNER JOIN sys.partitions partitions ON (allocunits.type IN (1, 3)
  462. AND partitions.hobt_id = allocunits.container_id) OR (allocunits.type = 2
  463. AND partitions.partition_id = allocunits.container_id)
  464. WHERE object_id=object_ID('' + @SchemaName_n_TableName + ''))
  465. AND Context IN ('LCX_TEXT_MIX') AND Operation in ('LOP_DELETE_ROWS')
  466. /*Use this subquery to filter the date*/
  467. AND [TRANSACTION ID] IN (SELECT DISTINCT [TRANSACTION ID] FROM sys.fn_dblog(NULL, NULL)
  468. WHERE Context IN ('LCX_NULL') AND Operation in ('LOP_BEGIN_XACT')
  469. And [Transaction Name]='DELETE'
  470. And CONVERT(NVARCHAR(11),[Begin Time]) BETWEEN @Date_From AND @Date_To)
  471.  
  472. /****************************************/
  473.  
  474. OPEN Page_Data_Cursor
  475.  
  476. FETCH NEXT FROM Page_Data_Cursor INTO @ConsolidatedPageID, @Slotid,@AllocUnitID,@LCX_TEXT_MIX,@LinkID,@Context
  477.  
  478. WHILE @@FETCH_STATUS = 0
  479. BEGIN
  480. DECLARE @hex_pageid AS VARCHAR(Max)
  481. /*Page ID contains File Number and page number It looks like 0001:00000130.
  482. In this example 0001 is file Number & 00000130 is Page Number & These numbers are in Hex format*/
  483. SET @Fileid=SUBSTRING(@ConsolidatedPageID,0,CHARINDEX(':',@ConsolidatedPageID)) -- Seperate File ID from Page ID
  484.  
  485. SET @hex_pageid ='0x'+ SUBSTRING(@ConsolidatedPageID,CHARINDEX(':',@ConsolidatedPageID)+1,Len(@ConsolidatedPageID)) ---Seperate the page ID
  486. 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
  487. FROM (SELECT CASE substring(@hex_pageid, 1, 2) WHEN '0x' THEN 3 ELSE 0 END) AS t(pos)
  488.  
  489. IF @Context='LCX_PFS'
  490. BEGIN
  491. DELETE @temppagedata
  492. INSERT INTO @temppagedata EXEC( 'DBCC PAGE(' + @DataBase_Name + ', ' + @fileid + ', ' + @pageid + ', 1) with tableresults,no_infomsgs;');
  493. INSERT INTO @pagedata SELECT @ConsolidatedPageID,@fileid,@pageid,@AllocUnitID,[ParentObject],[Object],[Field] ,[Value] FROM @temppagedata
  494. END
  495. ELSE IF @Context='LCX_TEXT_MIX'
  496. BEGIN
  497. 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
  498. END
  499. FETCH NEXT FROM Page_Data_Cursor INTO @ConsolidatedPageID, @Slotid,@AllocUnitID,@LCX_TEXT_MIX,@LinkID,@Context
  500. END
  501.  
  502. CLOSE Page_Data_Cursor
  503. DEALLOCATE Page_Data_Cursor
  504.  
  505. DECLARE @Newhexstring VARCHAR(MAX);
  506.  
  507. --The data is in multiple rows in the page, so we need to convert it into one row as a single hex value.
  508. --This hex value is in string format
  509. INSERT INTO @ModifiedRawData ([PAGE ID],[FILE IDS],[PAGE IDS],[Slot ID],[AllocUnitId]
  510. ,[RowLog Contents 0_var]
  511. , [RowLog Length])
  512. SELECT [Page ID],[FILE IDS],[PAGE IDS],Substring([ParentObject],CHARINDEX('Slot', [ParentObject])+4, (CHARINDEX('Offset', [ParentObject])-(CHARINDEX('Slot', [ParentObject])+4))-2 ) as [Slot ID]
  513. ,[AllocUnitId]
  514. ,Substring((
  515. SELECT
  516. REPLACE(STUFF((SELECT REPLACE(SUBSTRING([Value],CHARINDEX(':',[Value])+1,CHARINDEX('+',[Value])-CHARINDEX(':',[Value])),'+','')
  517. 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
  518. [Object] Like '%Memory Dump%' Order By '0x'+ LEFT([Value],CHARINDEX(':',[Value])-1)
  519. FOR XML PATH('') ),1,1,'') ,' ','')
  520. ),1,20000) AS [Value]
  521.  
  522. ,
  523. Substring((
  524. SELECT '0x' +REPLACE(STUFF((SELECT REPLACE(SUBSTRING([Value],CHARINDEX(':',[Value])+1,CHARINDEX('+',[Value])-CHARINDEX(':',[Value])),'+','')
  525. 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
  526. [Object] Like '%Memory Dump%' Order By '0x'+ LEFT([Value],CHARINDEX(':',[Value])-1)
  527. FOR XML PATH('') ),1,1,'') ,' ','')
  528. ),7,4) AS [Length]
  529.  
  530. From @pagedata B
  531. Where [Object] Like '%Memory Dump%'
  532. Group By [Page ID],[FILE IDS],[PAGE IDS],[ParentObject],[AllocUnitId]--,[Current LSN]
  533. Order By [Slot ID]
  534.  
  535. UPDATE @ModifiedRawData SET [RowLog Len] = CONVERT(VARBINARY(8000),REVERSE(cast('' AS XML).value('xs:hexBinary(substring(sql:column("[RowLog Length]"),0))', 'varbinary(Max)')))
  536. FROM @ModifiedRawData Where [LINK ID]=0
  537.  
  538. UPDATE @ModifiedRawData SET [RowLog Contents 0] =cast('' AS XML).value('xs:hexBinary(substring(sql:column("[RowLog Contents 0_var]"),0))', 'varbinary(Max)')
  539. FROM @ModifiedRawData Where [LINK ID]=0
  540.  
  541. Update B Set B.[RowLog Contents 0] =
  542. (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]
  543. WHEN A.[RowLog Contents 0] IS NULL AND C.[RowLog Contents 0] IS NOT NULL THEN C.[RowLog Contents 0]
  544. WHEN A.[RowLog Contents 0] IS NOT NULL AND C.[RowLog Contents 0] IS NULL THEN A.[RowLog Contents 0]
  545. END)
  546. ,B.[Update]=ISNULL(B.[Update],0)+1
  547. from @ModifiedRawData B
  548. LEFT Join @ModifiedRawData A On A.[Page IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],15+14,2))))
  549. And A.[File IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],19+14,2))))
  550. And A.[Link ID]=B.[Link ID]
  551. LEFT Join @ModifiedRawData C On C.[Page IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],27+14,2))))
  552. And C.[File IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],31+14,2))))
  553. And C.[Link ID]=B.[Link ID]
  554. Where (A.[RowLog Contents 0] IS NOT NULL OR C.[RowLog Contents 0] IS NOT NULL)
  555.  
  556. Update B Set B.[RowLog Contents 0] =
  557. (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]
  558. WHEN A.[RowLog Contents 0] IS NULL AND C.[RowLog Contents 0] IS NOT NULL THEN C.[RowLog Contents 0]
  559. WHEN A.[RowLog Contents 0] IS NOT NULL AND C.[RowLog Contents 0] IS NULL THEN A.[RowLog Contents 0]
  560. END)
  561. --,B.[Update]=ISNULL(B.[Update],0)+1
  562. from @ModifiedRawData B
  563. LEFT Join @ModifiedRawData A On A.[Page IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],15+14,2))))
  564. And A.[File IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],19+14,2))))
  565. And A.[Link ID]<>B.[Link ID] And B.[Update]=0
  566. LEFT Join @ModifiedRawData C On C.[Page IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],27+14,2))))
  567. And C.[File IDS]=Convert(int,Convert(Varbinary(Max),Reverse(Substring(B.[RowLog Contents 0],31+14,2))))
  568. And C.[Link ID]<>B.[Link ID] And B.[Update]=0
  569. Where (A.[RowLog Contents 0] IS NOT NULL OR C.[RowLog Contents 0] IS NOT NULL)
  570.  
  571. UPDATE @ModifiedRawData SET [RowLog Contents 0] =
  572. (Case When [RowLog Len]>=8000 Then
  573. Substring([RowLog Contents 0] ,15,[RowLog Len])
  574. When [RowLog Len]<8000 Then
  575. SUBSTRING([RowLog Contents 0],15+6,Convert(int,Convert(varbinary(max),REVERSE(Substring([RowLog Contents 0],15,6)))))
  576. End)
  577. FROM @ModifiedRawData Where [LINK ID]=0
  578.  
  579. UPDATE @ColumnNameAndData SET [hex_Value]=[RowLog Contents 0]
  580. --,A.[Update]=A.[Update]+1
  581. FROM @ColumnNameAndData A
  582. INNER JOIN @ModifiedRawData B ON
  583. Convert(int,Convert(Varbinary(Max),Reverse(Substring([hex_value],17,4))))=[PAGE IDS]
  584. AND Convert(int,Substring([hex_value],9,2)) =B.[Link ID]
  585. Where [System_Type_Id] In (99,167,175,231,239,241,165,98) And [Link ID] <>0
  586.  
  587. UPDATE @ColumnNameAndData SET [hex_Value]=
  588. (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]
  589. WHEN B.[RowLog Contents 0] IS NULL AND C.[RowLog Contents 0] IS NOT NULL THEN C.[RowLog Contents 0]
  590. WHEN B.[RowLog Contents 0] IS NOT NULL AND C.[RowLog Contents 0] IS NULL THEN B.[RowLog Contents 0]
  591. END)
  592. --,A.[Update]=A.[Update]+1
  593. FROM @ColumnNameAndData A
  594. LEFT JOIN @ModifiedRawData B ON
  595. Convert(int,Convert(Varbinary(Max),Reverse(Substring([hex_value],5,4))))=B.[PAGE IDS] And B.[Link ID] =0
  596. LEFT JOIN @ModifiedRawData C ON
  597. Convert(int,Convert(Varbinary(Max),Reverse(Substring([hex_value],17,4))))=C.[PAGE IDS] And C.[Link ID] =0
  598. 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)
  599.  
  600. UPDATE @ColumnNameAndData SET [hex_Value]=[RowLog Contents 0]
  601. --,A.[Update]=A.[Update]+1
  602. FROM @ColumnNameAndData A
  603. INNER JOIN @ModifiedRawData B ON
  604. Convert(int,Convert(Varbinary(Max),Reverse(Substring([hex_value],9,4))))=[PAGE IDS]
  605. And Convert(int,Substring([hex_value],3,2))=[Link ID]
  606. Where [System_Type_Id] In (35,34,99) And [Link ID] <>0
  607.  
  608. UPDATE @ColumnNameAndData SET [hex_Value]=[RowLog Contents 0]
  609. --,A.[Update]=A.[Update]+10
  610. FROM @ColumnNameAndData A
  611. INNER JOIN @ModifiedRawData B ON
  612. Convert(int,Convert(Varbinary(Max),Reverse(Substring([hex_value],9,4))))=[PAGE IDS]
  613. Where [System_Type_Id] In (35,34,99) And [Link ID] =0
  614.  
  615. UPDATE @ColumnNameAndData SET [hex_Value]=[RowLog Contents 0]
  616. --,A.[Update]=A.[Update]+1
  617. FROM @ColumnNameAndData A
  618. INNER JOIN @ModifiedRawData B ON
  619. Convert(int,Convert(Varbinary(Max),Reverse(Substring([hex_value],15,4))))=[PAGE IDS]
  620. Where [System_Type_Id] In (35,34,99) And [Link ID] =0
  621.  
  622. Update @ColumnNameAndData set [hex_value]= 0xFFFE + Substring([hex_value],9,LEN([hex_value]))
  623. --,[Update]=[Update]+1
  624. Where [system_type_id]=241
  625.  
  626. CREATE TABLE [#temp_Data]
  627. (
  628. [FieldName] VARCHAR(MAX),
  629. [FieldValue] NVARCHAR(MAX),
  630. [Rowlogcontents] VARBINARY(8000),
  631. [Row ID] int
  632. )
  633.  
  634. INSERT INTO #temp_Data
  635. SELECT NAME,
  636. CASE
  637. WHEN system_type_id IN (231, 239) THEN LTRIM(RTRIM(CONVERT(NVARCHAR(max),hex_Value))) --NVARCHAR ,NCHAR
  638. WHEN system_type_id IN (167,175) THEN LTRIM(RTRIM(CONVERT(VARCHAR(max),hex_Value))) --VARCHAR,CHAR
  639. WHEN system_type_id IN (35) THEN LTRIM(RTRIM(CONVERT(VARCHAR(max),hex_Value))) --Text
  640. WHEN system_type_id IN (99) THEN LTRIM(RTRIM(CONVERT(NVARCHAR(max),hex_Value))) --nText
  641. WHEN system_type_id = 48 THEN CONVERT(VARCHAR(MAX), CONVERT(TINYINT, CONVERT(BINARY(1), REVERSE (hex_Value)))) --TINY INTEGER
  642. WHEN system_type_id = 52 THEN CONVERT(VARCHAR(MAX), CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE (hex_Value)))) --SMALL INTEGER
  643. WHEN system_type_id = 56 THEN CONVERT(VARCHAR(MAX), CONVERT(INT, CONVERT(BINARY(4), REVERSE(hex_Value)))) -- INTEGER
  644. WHEN system_type_id = 127 THEN CONVERT(VARCHAR(MAX), CONVERT(BIGINT, CONVERT(BINARY(8), REVERSE(hex_Value))))-- BIG INTEGER
  645. WHEN system_type_id = 61 Then CONVERT(VARCHAR(MAX),CONVERT(DATETIME,CONVERT(VARBINARY(8000),REVERSE (hex_Value))),100) --DATETIME
  646. WHEN system_type_id =58 Then CONVERT(VARCHAR(MAX),CONVERT(SMALLDATETIME,CONVERT(VARBINARY(8000),REVERSE(hex_Value))),100) --SMALL DATETIME
  647. 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
  648. 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
  649. WHEN system_type_id In(60,122) THEN CONVERT(VARCHAR(MAX),Convert(MONEY,Convert(VARBINARY(8000),Reverse(hex_Value))),2) --MONEY,SMALLMONEY
  650. WHEN system_type_id = 104 THEN CONVERT(VARCHAR(MAX),CONVERT (BIT,CONVERT(BINARY(1), hex_Value)%2)) -- BIT
  651. 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
  652. 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
  653. 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
  654. 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
  655. WHEN system_type_id =36 THEN CONVERT(VARCHAR(MAX),CONVERT(UNIQUEIDENTIFIER,hex_Value)) --UNIQUEIDENTIFIER
  656. WHEN system_type_id =231 THEN CONVERT(VARCHAR(MAX),CONVERT(sysname,hex_Value)) --SYSNAME
  657. WHEN system_type_id =241 THEN CONVERT(VARCHAR(MAX),CONVERT(xml,hex_Value)) --XML
  658.  
  659. 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
  660. WHEN system_type_id=98 THEN (CASE
  661. 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
  662. 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
  663. WHEN CONVERT(INT,SUBSTRING(hex_Value,1,1))=167 THEN LTRIM(RTRIM(CONVERT(VARCHAR(max),Substring(hex_Value,9,Len(hex_Value))))) --VARCHAR,CHAR
  664. WHEN CONVERT(INT,SUBSTRING(hex_Value,1,1))=36 THEN CONVERT(VARCHAR(MAX),CONVERT(UNIQUEIDENTIFIER,Substring((hex_Value),3,20))) --UNIQUEIDENTIFIER
  665. 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
  666. 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
  667. END)
  668.  
  669. END AS FieldValue
  670. ,[Rowlogcontents]
  671. ,[Row ID]
  672. FROM @ColumnNameAndData ORDER BY nullbit
  673.  
  674. --Create the column name in the same order to do pivot table.
  675.  
  676. DECLARE @FieldName VARCHAR(max)
  677. SET @FieldName = STUFF(
  678. (
  679. SELECT ',' + CAST(QUOTENAME([Name]) AS VARCHAR(MAX)) FROM syscolumns WHERE id=object_id('' + @SchemaName_n_TableName + '')
  680. FOR XML PATH('')), 1, 1, '')
  681.  
  682. --Finally did pivot table and get the data back in the same format.
  683.  
  684. SET @sql = 'SELECT ' + @FieldName + ' FROM #temp_Data PIVOT (Min([FieldValue]) FOR FieldName IN (' + @FieldName + ')) AS pvt'
  685. EXEC sp_executesql @sql
  686.  
  687. GO
  1. --------------------------===========我是华丽的分割线=======-------------------------------------
  1. --Execute the procedure like --Recover_Deleted_Data_Proc 'Database Name','Schema.table name' --EXAMPLE #1 : FOR ALL DELETED RECORDS EXEC Recover_Deleted_Data_Proc 'test','dbo.Test' GO --EXAMPLE #2 : FOR ANY SPECIFIC DATE RANGE EXEC Recover_Deleted_Data_Proc 'test','dbo.Test_Table' ,'2011/12/01','2012/01/30' --It will give you the result of all deleted records. /* My Test */ /* EXEC Recover_Deleted_Data_Proc'DB_Frank' ,'dbo.Test','2016/10/01','2016/10/20' */

恢复被误操作删除的数据 fn_dblog的更多相关文章

  1. MySQL误操作删除后,怎么恢复数据?

    MySQL误操作删除后,怎么恢复数据?登陆查数据库mysql> select * from abc.stad;+----+-----------+| id | name |+----+----- ...

  2. Oracle 恢复被删除的数据,解决误操作删除数据

    在删除数据的时候不小心,把delete语句执行错了,把别的表给delete,而且还执行了commit!真汗.......数据是相当的重要........废话少说了!赶快找方法吧: 第一种: 1.打开F ...

  3. 如何回复在Git中误操作删除的文件?

    不小心的操作,删除了某些文件 某天很高大地用上了git来管理版本,分布式版本管理工具,好是好,但是还不是很熟悉,结果某天一不小心就从本地仓库中删除了若干个文件,该如何找回这些文件呢? 调查现场 git ...

  4. 基于mysqldump备份集来恢复某个误操作的表(drop,truncate)

      Preface       How to rescue a dropped or truncated table online?Dropping or truncating is ddl oper ...

  5. 记一次生产mysql数据误操作恢复过程

    提示:建议每次对数据库进行修改时都做下备份 注意:以下Mysql开启的是row格式的binlog日志,确定到误操作具体时间可能有些麻烦,默认的格式就能很快找出来.这里开启row的原因是还有一种更快的方 ...

  6. Mysql使用binlog恢复数据解决误操作问题的两种方法

    为保证没有其他参数配置影响,重新安装配置了一台最小化安装的CentOS7虚拟机 1. 基础知识
 安装mysql5.6数据库Mysql binlog初步理解 2. 配置mysql 开启binlog.修 ...

  7. mongo 误操作恢复数据

    场景:我往同一个集合里面插入 三条数据  aa:aa  bb:bb  cc:cc .后来我后悔了,不想插入 bb:bb,通过oplog重放过滤好 bb:bb这条数据. 原理: 1.通过 oplog.r ...

  8. SQLServer 2008以上误操作数据库恢复方法——日志尾部备份(转)

    问题: 经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了.人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题. 遇到这 ...

  9. [转]SQLServer 2008以上误操作数据库恢复方法——日志尾部备份

    原文出处:http://blog.csdn.net/dba_huangzj/article/details/8491327 问题: 经常看到有人误删数据,或者误操作,特别是update和delete的 ...

随机推荐

  1. Django ORM 中的批量操作

    Django ORM 中的批量操作 在Hibenate中,通过批量提交SQL操作,部分地实现了数据库的批量操作.但在Django的ORM中的批量操作却要完美得多,真是一个惊喜. 数据模型定义 首先,定 ...

  2. ltt.js

    var dailyBox = $('.daily-box-office'), curDate = new Date(), curYear = curDate.getFullYear(), curMon ...

  3. (二)list或set的遍历

    <@e.table class="tablelist questionlist" listAction="devide_check_list_batch.do&qu ...

  4. Serializable在C#中的作用.net中的对象序列化 (转)

    序列化是指将对象实例的状态存储到存储媒体的过程,在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转 换为字节流,然后再把字节流写入数据流,在随后对对象进行反序列化时,将创建出 ...

  5. MapReduce的流程

    1. Inputformat会从job的INPUT_DIR目录下读入待处理的文件,检查输入的有效性并将文件切分成InputSplit列表.Job实例可以通过setInputFormatClass(Cl ...

  6. hadoop 2.0 详细配置教程

    http://www.cnblogs.com/scotoma/archive/2012/09/18/2689902.html

  7. windows消息钩子

    1.消息钩子的概念: Windows应用程序是基于消息驱动的,不论什么线程仅仅要注冊窗体类都会有一个消息队列用于接收用户输入的消息和系统消息.为了拦截消息,Windows提出了钩子的概念.钩子(Hoo ...

  8. VK Cup 2015 - Finals, online mirror D. Restructuring Company 并查集

    D. Restructuring Company Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  9. Android Settings 导入eclipse

    1.加载源码 Android Project from Existing Code 选择源码工程Settings: 2.加载所需要的jar包 (改下名字) out/target/common/obj/ ...

  10. 垃圾回收算法手册:自动内存管理的艺术 BOOK

    垃圾回收算法手册:自动内存管理的艺术 2016-03-18 华章计算机 内容简介 PROSPECTUS 本书是自动内存管理领域的里程碑作品,汇集了这个领域里经过50多年的研究沉积下来的最佳实践,包含当 ...