web-dev-qa-db-ja.com

SQLServerのテーブルのハッシュまたはチェックサムを計算する

SQL Server 2008でテーブル全体のチェックサムまたはハッシュを計算しようとしています。発生している問題は、テーブルにXML列のデータ型が含まれていることです。これは、チェックサムでは使用できず、nvarcharに変換する必要があります。最初。だから私はそれを2つの問題に分解する必要があります:

  1. 行のチェックサムを計算します。実行前にスキーマが不明です。
  2. すべての行のチェックサムを計算して、完全なテーブルチェックサムを取得します。
27
Gabe Brown

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 )
23
Cade Roux

スクリプトを変更して、データベース内の関連するすべてのテーブルのクエリを生成しました。

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
2