Quantcast
Channel: SCN : All Content - SAP Adaptive Server Enterprise (SAP ASE) for Custom Applications
Viewing all articles
Browse latest Browse all 757

Calculate hashbytes for table

$
0
0

Sometimes it is necessary to make sure that content of two tables are the same or to monitor changes to the table.

For example for MS SQL it is possible to do that with CHECKSUM_AGG function

 

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM table

As far as I know there is no similar aggregation function for Sybase ASE, but some close functionality can be achieved with XOR + update trick

 

 

create procedure sp__hashcode
 @objectname varchar(255)
,@excludelist varchar(16384) = null
,@includelist varchar(16384) = null
,@whereclause varchar(16384) = null
,@hashalgorithm varchar(20) = 'MD5'
,@using varchar(255) = null
,@hash bigint = 0 output
,@debug bit = 1
as
begin    declare @objectid int           ,@columnlist varchar(16384)           ,@rowcount int    select @objectid = object_id(@objectname), @hash = isnull(@hash,0)    if @objectid is null begin        /* 17461, "Object does not exist in this database." */        raiserror 17461        return (1)    end    /* Create temporary table for column list */    create table #columnlist (        name varchar(255)    )    insert into #columnlist    select distinct c.name     from syscolumns c    join systypes t on (c.type = t.type)    where c.id = @objectid    and t.name not in ('image','text','unitext') -- ignore LOBs    and (isnull(c.xstatus,0) & 1) != 1 -- ignore off row    /* Delete columns which exists in exclude list */    if @excludelist is not null begin        set @excludelist = str_replace(@excludelist, '''', '''''')        set @excludelist = '''' + str_replace(@excludelist, ',', ''',''') + ''''        if @debug = 1            print 'Exclude list: %1!', @excludelist        execute ('delete from #columnlist where name in (' + @excludelist + ')')    end    /* Delete columns which not exists in include list */    if @includelist is not null begin        set @includelist = str_replace(@includelist, '''', '''''')        set @includelist = '''' + str_replace(@includelist, ',', ''',''') + ''''        if @debug = 1            print 'Include list: %1!', @includelist        execute ('delete from #columnlist where name not in (' + @includelist + ')')    end    /* Put columns into the comma separated list */    update #columnlist    set @columnlist = @columnlist + case when @columnlist is null then null else ',' end + name    if @debug = 1        print 'Column list: %1!', @columnlist    if @columnlist is not null         if @using is null            execute ( 'update ' + @objectname + ' set @hash=@hash^convert(bigint,hashbytes(''' + @hashalgorithm + ''',' + @columnlist + ')) ' + @whereclause )        else             execute ( 'update ' + @objectname + ' set @hash=@hash^convert(bigint,hashbytes(''' + @hashalgorithm + ''',' + @columnlist + ',using ' + @using + ')) ' + @whereclause )    select @rowcount = @@rowcount    if @debug = 1 begin        print 'Rows processed: %1!', @rowcount        print 'Hash: %1!', @hash    end    return (0)
end
go

Example of usage:

 

sp__hashcode sysobjects, @includelist='name,id,uid,type', @whereclause='where id < 20' 

Definitely, there is no one hundred percent guarantee that two different tables will return distinct hashes, at least because hashbytes calculates hash based on the underlying bytes, and in case of different data types with same bytes it returns the same value. This query demonstrates it

 

select hashbytes ('MD5', cast(49 as tinyint)), hashbytes ('MD5', '1') 

Also it is quite heavy, and have other limitations (like lengths of column names) but still useful for quick comparation of tables and watching for changes for relevantly small tables.

 

p.s. criticism is welcome


Viewing all articles
Browse latest Browse all 757

Trending Articles