--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,1into #t1
    
from::fn_dblog (nullnull)
    
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