We use either Checksum or Hashbytes for generating a value for finding changes of records when need to transfer records from one source to another and changes cannot be identified at the source end. This is specially used in data warehousing. I have written two posts on it, you can read them for getting an idea on it;
I had to implement similar with another database but it was not at the design stage. The database is already developed and being used, and it was over 1TB. The requirement was, adding a column that has Hash based on all existing columns. Since there were more than 300 tables, it was not practical to open the Design of the table and add the column. The only option I had was, form a dynamic query that alters the table by adding the column. I had to consider few things with the implementation;
- All tables should be altered.
- All columns should be used for generating the Hash.
- Tables that have records must set Hash immediately.
- Null must be replaced with blank because Hashbytes does not accept nulls.
Considering all, I wrote the following code for altering tables. You may use the same if you have the same requirement;
-- Getting table names into a table -- A temporary table or table variable can be used for this SELECT ROW_NUMBER() OVER(ORDER BY NofRecords) Id, TableName, TableId, NofRecords INTO dbo.TableNames FROM ( SELECT t.name TableName, t.object_id TableId, SUM(p.rows) NofRecords FROM sys.partitions p INNER JOIN sys.tables t ON p.object_id = t.object_id WHERE p.index_id < 2 AND t.type = 'U' GROUP BY t.name, t.object_id) AS t; -- Adding a clustered index -- This is not required if the nof tables is low CREATE CLUSTERED INDEX IX_TableNames ON dbo.TableNames (Id); GO DECLARE @Id int = 1; DECLARE @LastId int = 0; DECLARE @TableName varchar(500) DECLARE @TableId int DECLARE @Sql varchar(max) DECLARE @Columns varchar(8000) SELECT @LastId = COUNT(*) FROM dbo.TableNames; -- Iterate through all tables WHILE (@Id <= @LastId) BEGIN SELECT @TableName = TableName, @TableId = TableId FROM dbo.TableNames WHERE Id = @Id; SET @Sql = 'ALTER TABLE dbo.' + @TableName; SET @Sql += ' ADD '; SET @Sql += ' MIG_HashKey AS HASHBYTES(''MD5'', '; -- get all columns, convert them to varchar -- and replace null with blank value SELECT @Columns = STUFF((SELECT '+ IsNull(Convert(varchar(4000), ' + name + '),'''')' FROM sys.columns WHERE object_id = @TableId FOR XML PATH ('')), 1, 2, ''); SET @Sql += @Columns; SET @Sql += ') '; -- Execute the code BEGIN TRY EXEC ( @sql); END TRY BEGIN CATCH PRINT ERROR_MESSAGE() PRINT @Sql; END CATCH SET @Sql = ''; SET @Columns = '' SET @Id += 1; END GO
No comments:
Post a Comment