SQLServerのテーブルのハッシュまたはチェックサムを計算する
SQL Server 2008でテーブル全体のチェックサムまたはハッシュを計算しようとしています。発生している問題は、テーブルにXML列のデータ型が含まれていることです。これは、チェックサムでは使用できず、nvarcharに変換する必要があります。最初。だから私はそれを2つの問題に分解する必要があります:
- 行のチェックサムを計算します。実行前にスキーマが不明です。
- すべての行のチェックサムを計算して、完全なテーブルチェックサムを取得します。
CHECKSUM_AGG を使用できます。引数は1つだけなので、CHECKSUM_AGG(CHECKSUM(*))
を実行できますが、これはXMLデータ型では機能しないため、動的SQLを使用する必要があります。
INFORMATION_SCHEMA.COLUMNS
から列リストを動的に生成してから、intをテンプレートに挿入できます。
SELECT @column_list = COALESCE(@column_list + ', ', '')
+ /* Put your casting here from XML, text, etc columns */ QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table_name
AND TABLE_SCHEMA = @schema_name
DECLARE @template AS varchar(MAX)
SET @template = 'SELECT CHECKSUM_AGG(CHECKSUM({@column_list})) FROM {@schema_name}.{@table_name}'
DECLARE @sql AS varchar(MAX)
SET @sql = REPLACE(REPLACE(REPLACE(
'{@column_list}', @column_list),
'{@schema_name}', @schema_name),
'{@table_name}', @table_name)
EXEC ( @sql )
スクリプトを変更して、データベース内の関連するすべてのテーブルのクエリを生成しました。
USE myDatabase
GO
DECLARE @table_name sysname
DECLARE @schema_name sysname
SET @schema_name = 'dbo'
DECLARE myCursor cursor
FOR SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES T
WHERE T.TABLE_SCHEMA = @schema_name
AND T.TABLE_TYPE = 'BASE TABLE'
AND T.TABLE_NAME NOT LIKE 'MSmerge%'
AND T.TABLE_NAME NOT LIKE 'sysmerge%'
AND T.TABLE_NAME NOT LIKE 'tmp%'
ORDER BY T.TABLE_NAME
OPEN myCursor
FETCH NEXT
FROM myCursor
INTO @table_name
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @column_list nvarchar(MAX)
SET @column_list=''
SELECT @column_list = @column_list + CASE WHEN DATA_TYPE IN ('xml','text','ntext','image sql_variant') THEN 'CONVERT(nvarchar(MAX),'
ELSE ''
END
+ QUOTENAME(COLUMN_NAME)
+ CASE WHEN DATA_TYPE IN ('xml','text','ntext','image sql_variant') THEN ' /* ' + DATA_TYPE + ' */)'
ELSE ''
END + ', '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @Table_name
ORDER BY ORDINAL_POSITION
SET @column_list = LEFT(@column_list, LEN(@column_list)-1) -- remove trailing comma
DECLARE @sql AS nvarchar(MAX)
SET @sql = 'SELECT ''' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + ''' table_name,
CHECKSUM_AGG(CHECKSUM(' + @column_list + ')) CHECKSUM
FROM ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@Table_name) + ' WITH (NOLOCK)'
PRINT @sql
FETCH NEXT
FROM myCursor
INTO @table_name
IF @@FETCH_STATUS = 0
PRINT 'UNION ALL'
END
CLOSE myCursor
DEALLOCATE myCursor
GO