-- 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. HDU-4699 Editor 数据结构维护

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4699 题意:开始有一个光标,每次有5中操作:1,光标当前位置插入一个数,2,光标当前位置删除一个,3, ...

  2. [NOI2005]维修数列 Splay tree 区间反转,修改,求和,求最值

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数 ...

  3. Android实例-从照相机或图库获取照片(XE8+小米2)

    结果: 1.如果要取本地相册的话,小米手机要注意一下,不能取网络相册. 操作: 1.两个 TButton (Button1 和 Button2) , 一个 TActionList(ActionList ...

  4. SQL2008-备份SQL数据库的语句

    SQL2008:1.备份库BACKUP DATABASE CDJQ_CEM2008 TO DISK = 'd:\zhu\123.bak'2.开启RAR加压功能EXEC sp_configure 'sh ...

  5. DTD - XML Building Blocks

    The main building blocks of both XML and HTML documents are elements. The Building Blocks of XML Doc ...

  6. 转载 asp.net中ViewState的用法详解

    转载原地址: http://www.jb51.net/article/73662.htm 在web窗体控件设置为runat = "server",这个控件会被附加一个隐藏的属性_V ...

  7. Mac OS环境下媒体文件分割工具mediafilesegmenter的简单使用(生成M3U8 TS文件)

    mediafilesegmenter是苹果开发的一款用于分割媒体文件的工具,其功能与mediastreamsegmenter相似,但操作更简单. * 具体可以对比博客中的另一篇简介<Mac OS ...

  8. docker——Dockerfile创建镜像

    写在前面: 继续docker的学习,昨天用docker成功跑了tomcat,但是在centos中镜像跑的容器手动装jdk和tomcat,今天学习用Dockerfile创建镜像,并在上面搭建java环境 ...

  9. Oracle-12541:TNS:无监听程序 .

    背景:自己机子做oracle服务器,其他机子可以ping得通我的机子,但是jdbc就是连不上,后来用plsql连出现无监听程序.... 我昨天重新安装Oracle后,用PL/SQL Developer ...

  10. Asp.net中使用资源文件实现网站多语言

    首先需要新建一个ASP.NET Web Application.然后右键项目文件Add->Add ASP.NET Folder->App-GlobalResources. 新建好资源文件夹 ...