-- drop function dbo.f_splitBinary
create   function  dbo.f_splitBinary( @s   varbinary ( 8000 ))
returns   @t   table (id  int   identity ( 1 , 1 ),Value  binary ( 1 ))
as
begin
declare   @i   int , @im   int
select   @i = 1 , @im = datalength ( @s )
while   @i <= @im
begin
  
insert   into   @t   select   substring ( @s , @i , 1 )
  
set   @i = @i + 1
end
return
end

GO

-- drop function dbo.f_reverseBinary
create   function  dbo.f_reverseBinary( @s   varbinary ( 128 ))
returns   varbinary ( 128 )
as
begin
declare   @r   varbinary ( 128 )
set   @r = 0x
select   @r = @r + Value  from  dbo.f_splitBinary( @s ) a  order   by  id  desc
return   @r
end

GO
 
 
-- drop proc [dbo].[p_getLog]
create   proc   [ dbo ] . [ p_getLog ] ( @TableName  sysname, @c   int = 100 )
as
set  nocount  on
declare   @s   varbinary ( 8000 ), @s1   varbinary ( 8000 ), @str   varchar ( 8000 ), @str1   varchar ( 8000 ), @lb   int , @le   int , @operation   varchar ( 128 )
declare   @i   int , @lib   int , @lie   int , @ib   int , @ie   int , @lenVar   int , @columnname  sysname, @length   int , @columntype   varchar ( 32 ), @prec   int , @scale   int
declare   @TUVLength   int , @vc   int , @tc   int , @bitAdd   int , @bitCount   int , @count   int

select  b.name,b.length,c.name typename,b.colid,b.xprec,b.xscale,
    
case   when  c.name  not   like   ' %var% '   and  c.name  not   in  ( ' xml ' , ' text ' , ' image ' then   1   else   2   end  p,row_number()  over (partition  by
    
case   when  c.name  not   like   ' %var% '   and  c.name  not   in  ( ' xml ' , ' text ' , ' image ' then   1   else   2   end   order   by  colid) pid
into  #t
    
from  sysobjects a  inner   join  syscolumns b  on  a.id = b.id  inner   join  systypes c  on  b.xtype = c.xusertype
    
where  a.name = @TableName   order   by  b.colid

SELECT   top ( @c ) Operation, [ RowLog Contents 0 ] , [ RowLog Contents 1 ] , [ RowLog Contents 2 ] , [ RowLog Contents 3 ] , [ Log Record ] ,id = identity ( int , 1 , 1 into  #t1
    
from ::fn_dblog ( null null )
    
where  AllocUnitName  like ' dbo. ' + @TableName + ' % ' and
    Operation 
in ( ' LOP_INSERT_ROWS ' , ' LOP_DELETE_ROWS ' , ' LOP_MODIFY_ROW '  )
    
AND  Context  not   in  ( ' LCX_IAM ' , ' LCX_PFS ' )
     
order   by   [ Current LSN ]   desc

select   @tc = count ( * from  #t

select   @lb = min (id), @le = max (id)  from  #t1
while   @lb <= @le
begin
    
select   @operation = Operation, @s = [ RowLog Contents 0 ] , @s1 = [ RowLog Contents 1 ]   from  #t1  where  id = @lb   AND   [ RowLog Contents 1 ]   IS   NOT   NULL
    
set   @TUVLength = convert ( int ,dbo.f_reverseBinary( substring ( @s , 3 , 2 ))) + 3
    
select   @i = 5 , @str = '' , @vc = 0 , @bitCount = 0
    
select   @lib = min (pid), @lie = max (pid)  from  #t  where  p = 1
    
while   @lib <= @lie
    
begin
        
select   @columnname = name, @length = length, @columntype = typename, @prec = xprec, @scale = xscale, @vc = colid - 1   from  #t  where  p = 1   and  pid = @lib
--         if @columntype<>'bit'
--
            print rtrim(@i)+'->'+rtrim(@length)

        
if  dbo.f_reverseBinary( substring ( @s , @TUVLength , 1 + (( @tc - 1 ) / 8 )))  &   power ( 2 , @vc <>   0
        
begin
            
if   @columntype <> ' bit '
                
select   @str = @str + @columnname + ' =NULL, ' , @i = @i + @length
            
else
            
begin
                
select   @str = @str + @columnname + ' =NULL, '
                
set   @bitAdd   =   case   when   @bitCount = 0   then   @i   else   @bitAdd   end
                
set   @bitCount   =  ( @bitCount   +   1 ) % 8    
                
set   @i = @i + case   @bitCount   when   1   then   1   else   0   end
--                 print rtrim(@bitAdd)+'->'+rtrim(@length)
             end                
        
end
        
else   if   @columntype = ' char '
            
select   @str = @str + @columnname + ' = ' + convert ( varchar ( 256 ), substring ( @s , @i , @length )) + ' , ' , @i = @i + @length
        
else   if   @columntype = ' nchar '
            
select   @str = @str + @columnname + ' = ' + convert ( nvarchar ( 256 ), substring ( @s , @i , @length )) + ' , ' , @i = @i + @length
        
else   if   @columntype = ' datetime '
            
select   @str = @str + @columnname + ' = ' + convert ( varchar , dateadd (second, convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 4 ))) / 300
                ,
dateadd ( day , convert ( int ,dbo.f_reverseBinary( substring ( @s , @i + 4 , 4 ))), ' 1900-01-01 ' )), 120 ) + ' , ' , @i = @i + 8
        
else   if   @columntype = ' smalldatetime '
            
select   @str = @str + @columnname + ' = ' + convert ( varchar , dateadd (minute, convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 2 )))
                ,
dateadd ( day , convert ( int ,dbo.f_reverseBinary( substring ( @s , @i + 2 , 2 ))), ' 1900-01-01 ' )), 120 ) + ' , ' , @i = @i + 4
        
else   if   @columntype = ' int '
            
select   @str = @str + @columnname + ' = ' + rtrim ( convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 4 )))) + ' , ' , @i = @i + 4
        
else   if   @columntype = ' decimal '
            
select   @str = @str + @columnname + ' =DECIMAL, ' , @i = @i + @length
        
else   if   @columntype = ' bit '
        
begin
            
set   @bitAdd   =   case   when   @bitCount = 0   then   @i   else   @bitAdd   end
            
set   @bitCount   =  ( @bitCount   +   1 ) % 8
            
select   @str = @str + @columnname + ' = ' + rtrim ( convert ( bit , substring ( @s , @bitAdd , 1 ) & power ( 2 , case   @bitCount   when   0   then   8   else   @bitCount   end - 1 ))) + ' , '
                ,
@i = @i + case   @bitCount   when   1   then   1   else   0   end
--             print rtrim(@bitAdd)+'->'+rtrim(@length)
         end
        
set   @lib = @lib + 1
    
end
    
set   @i = convert ( int ,dbo.f_reverseBinary( substring ( @s , 3 , 2 ))) + 4 + (( @tc - 1 ) / 8 )
    
set   @lenVar = convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 2 )))
    
set   @i = @i + 2
    
set   @ib = @i   +   @lenVar * 2
    
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 2 )))
    
set   @count = 0
    
select   @lib = min (pid), @lie = max (pid)  from  #t  where  p = 2
    
while   @lib <= @lie
    
begin
--         print rtrim(@ib)+'->'+rtrim(@ie)
         select   @columnname = name, @length = length, @columntype = typename, @vc = colid - 1   from  #t  where  p = 2   and  pid = @lib
        
if  dbo.f_reverseBinary( substring ( @s , @TUVLength , 1 + (( @tc - 1 ) / 8 )))  &   power ( 2 , @vc <>   0
        
begin
            
select   @str = @str + @columnname + ' =NULL, '
            
select   @ib = @ie + 1 , @i = @i + 2
            
if   @count < @lenVar
                
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 2 )))
        
end
        
else   if   @columntype = ' varchar '
        
begin
            
select   @str = @str + @columnname + ' = ' + convert ( varchar ( 256 ), substring ( @s , @ib , @ie - @ib + 1 )) + ' , '
            
select   @ib = @ie + 1 , @i = @i + 2
            
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 2 )))
        
end
        
else   if   @columntype = ' nvarchar '
        
begin
            
select   @str = @str + @columnname + ' = ' + convert ( nvarchar ( 256 ), substring ( @s , @ib , @ie - @ib + 1 )) + ' , '
            
select   @ib = @ie + 1 , @i = @i + 2
            
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s , @i , 2 )))
        
end
        
set   @count = @count + 1
        
set   @lib = @lib + 1
    
end
    
set   @str = left ( @str , len ( @str ) - 1 )
   
     
IF   @operation   = ' LOP_MODIFY_ROW '  
     
BEGIN
          
set   @TUVLength = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , 3 , 2 ))) + 3
   
select   @i = 5 , @str1 = '' , @vc = 0 , @bitCount = 0
   
select   @lib = min (pid), @lie = max (pid)  from  #t  where  p = 1
   
while   @lib <= @lie
   
begin
    
select   @columnname = name, @length = length, @columntype = typename, @prec = xprec, @scale = xscale, @vc = colid - 1   from  #t  where  p = 1   and  pid = @lib
  
--         if @columntype<>'bit'
   --             print rtrim(@i)+'->'+rtrim(@length)

    
if  dbo.f_reverseBinary( substring ( @s1 , @TUVLength , 1 + (( @tc - 1 ) / 8 )))  &   power ( 2 , @vc <>   0
    
begin
     
if   @columntype <> ' bit '
      
select   @str1 = @str1 + @columnname + ' =NULL, ' , @i = @i + @length
     
else
     
begin
      
select   @str1 = @str1 + @columnname + ' =NULL, '
      
set   @bitAdd   =   case   when   @bitCount = 0   then   @i   else   @bitAdd   end
      
set   @bitCount   =  ( @bitCount   +   1 ) % 8    
      
set   @i = @i + case   @bitCount   when   1   then   1   else   0   end
  
--                 print rtrim(@bitAdd)+'->'+rtrim(@length)
      end                
    
end
    
else   if   @columntype = ' char '
     
select   @str1 = @str1 + @columnname + ' = ' + convert ( varchar ( 256 ), substring ( @s1 , @i , @length )) + ' , ' , @i = @i + @length
    
else   if   @columntype = ' nchar '
     
select   @str1 = @str1 + @columnname + ' = ' + convert ( nvarchar ( 256 ), substring ( @s1 , @i , @length )) + ' , ' , @i = @i + @length
    
else   if   @columntype = ' datetime '
     
select   @str1 = @str1 + @columnname + ' = ' + convert ( varchar , dateadd (second, convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 4 ))) / 300
      ,
dateadd ( day , convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i + 4 , 4 ))), ' 1900-01-01 ' )), 120 ) + ' , ' , @i = @i + 8
    
else   if   @columntype = ' smalldatetime '
     
select   @str1 = @str1 + @columnname + ' = ' + convert ( varchar , dateadd (minute, convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 2 )))
      ,
dateadd ( day , convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i + 2 , 2 ))), ' 1900-01-01 ' )), 120 ) + ' , ' , @i = @i + 4
    
else   if   @columntype = ' int '
     
select   @str1 = @str1 + @columnname + ' = ' + rtrim ( convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 4 )))) + ' , ' , @i = @i + 4
    
else   if   @columntype = ' decimal '
     
select   @str1 = @str1 + @columnname + ' =DECIMAL, ' , @i = @i + @length
    
else   if   @columntype = ' bit '
    
begin
     
set   @bitAdd   =   case   when   @bitCount = 0   then   @i   else   @bitAdd   end
     
set   @bitCount   =  ( @bitCount   +   1 ) % 8
     
select   @str1 = @str1 + @columnname + ' = ' + rtrim ( convert ( bit , substring ( @s1 , @bitAdd , 1 ) & power ( 2 , case   @bitCount   when   0   then   8   else   @bitCount   end - 1 ))) + ' , '
      ,
@i = @i + case   @bitCount   when   1   then   1   else   0   end
  
--             print rtrim(@bitAdd)+'->'+rtrim(@length)
     end
    
set   @lib = @lib + 1
   
end
   
set   @i = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , 3 , 2 ))) + 4 + (( @tc - 1 ) / 8 )
   
set   @lenVar = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 2 )))
   
set   @i = @i + 2
   
set   @ib = @i   +   @lenVar * 2
   
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 2 )))
   
set   @count = 0
   
select   @lib = min (pid), @lie = max (pid)  from  #t  where  p = 2
   
while   @lib <= @lie
   
begin
  
--         print rtrim(@ib)+'->'+rtrim(@ie)
     select   @columnname = name, @length = length, @columntype = typename, @vc = colid - 1   from  #t  where  p = 2   and  pid = @lib
    
if  dbo.f_reverseBinary( substring ( @s1 , @TUVLength , 1 + (( @tc - 1 ) / 8 )))  &   power ( 2 , @vc <>   0
    
begin
     
select   @str1 = @str1 + @columnname + ' =NULL, '
     
select   @ib = @ie + 1 , @i = @i + 2
     
if   @count < @lenVar
      
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 2 )))
    
end
    
else   if   @columntype = ' varchar '
    
begin
     
select   @str1 = @str1 + @columnname + ' = ' + convert ( varchar ( 256 ), substring ( @s1 , @ib , @ie - @ib + 1 )) + ' , '
     
select   @ib = @ie + 1 , @i = @i + 2
     
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 2 )))
    
end
    
else   if   @columntype = ' nvarchar '
    
begin
     
select   @str1 = @str1 + @columnname + ' = ' + convert ( nvarchar ( 256 ), substring ( @s1 , @ib , @ie - @ib + 1 )) + ' , '
     
select   @ib = @ie + 1 , @i = @i + 2
     
set   @ie = convert ( int ,dbo.f_reverseBinary( substring ( @s1 , @i , 2 )))
    
end
    
set   @count = @count + 1
    
set   @lib = @lib + 1
   
end
   
set   @str1 = left ( @str1 , len ( @str1 ) - 1 )

     
END
   
    
IF   @operation   = ' LOP_MODIFY_ROW '  
    
BEGIN
     
print     @operation + ' 修改前值: ' + @str
     
     
print     @operation + ' 修改后值: ' + @str1
     
    
END
    
ELSE
 
BEGIN
  
print   @operation + ' : ' + @str
 
END    
    
set   @lb = @lb + 1
END

drop   table  #t,#t1
GO



执行:exec p_getLog 'test';

LOP_MODIFY_ROW修改前值:id = 32 ,name =
LOP_MODIFY_ROW修改后值:id
= 100 ,name =
LOP_INSERT_ROWS:id
= 0 ,name =
LOP_INSERT_ROWS:id
= 3 ,name = ccc       
LOP_INSERT_ROWS:id
= 0 ,name =
LOP_INSERT_ROWS:id
= 2 ,name = bbb       
LOP_INSERT_ROWS:id
= 0 ,name =
LOP_INSERT_ROWS:id
= 1 ,name = aaa