CHECKSUM: примеры (SQL)

Использование CHECKSUM в SQL Server на практике
Раздел: Функции хэширования
CHECKSUM( * | expression [ ,n ] ): int

Основы функции CHECKSUM

Функция CHECKSUM в MS SQL Server предназначена для вычисления хеш-значения (контрольной суммы) на основе одного или нескольких аргументов. Она возвращает целочисленное значение типа int.

Функция часто используется для создания хеш-индексов, быстрого сравнения строк или обнаружения изменений в данных. Её результатом является числовое значение, вычисленное на основе входных данных.

Синтаксис: CHECKSUM ( expression [ ,...n ] )

Аргументы:

  • expression — любое выражение, за исключением типов, эквивалентных image, ntext, text, xml или не являющееся псевдонимом типа. Количество аргументов не ограничено.

Возвращаемое значение: Целое число типа int в диапазоне от -2^31 (-2 147 483 648) до 2^31-1 (2 147 483 647). Для идентичных наборов входных выражений функция всегда возвращает одно и то же значение. Однако существует ненулевая вероятность возникновения коллизии — ситуации, когда разные входные данные дают одинаковую контрольную сумму.

Если в списке аргументов есть хотя бы один NULL, результат функции также будет NULL.

Простые примеры использования

Вычисление контрольной суммы для строкового значения.

SELECT CHECKSUM('Пример текста') AS CheckSumValue;
CheckSumValue
-2024084040

Вычисление контрольной суммы для числового значения.

SELECT CHECKSUM(12345) AS CheckSumValue;
CheckSumValue
12345

Использование нескольких аргументов.

SELECT CHECKSUM('Hello', 'World', 2024) AS CheckSumValue;
CheckSumValue
-116897617

Реакция на значение NULL.

SELECT CHECKSUM('Data', NULL) AS CheckSumValue;
CheckSumValue
NULL

Похожие функции в MS SQL

В MS SQL Server существуют другие функции для вычисления хешей и контрольных сумм.

BINARY_CHECKSUM: Работает аналогично CHECKSUM, но вычисляет сумму на основе двоичного представления данных. Менее устойчива к перестановкам столбцов в таблице при сравнении строк, но более чувствительна к изменению типа данных. Часто используется для обнаружения изменений в строке таблицы.

CHECKSUM_AGG: Агрегатная функция, которая возвращает контрольную сумму для набора значений в группе. Полезна для быстрой проверки, изменился ли набор строк, например, в кэше. Применяется с предложением GROUP BY.

HASHBYTES: Более криптографически стойкая функция, поддерживающая алгоритмы MD5, SHA1, SHA2_256, SHA2_512. Возвращает значение типа varbinary. Используется, когда требуется минимизировать вероятность коллизий, например, для создания уникальных идентификаторов на основе данных.

Выбор функции зависит от задачи: для быстрого сравнения строк или построения хеш-индексов часто достаточно CHECKSUM. Для задач, связанных с безопасностью или где критично отсутствие коллизий, предпочтительнее HASHBYTES.

Аналоги в других СУБД и языках

MySQL: Функции CRC32() (возвращает 32-битную циклическую избыточную сумму) и MD5() (возвращает 128-битный хеш в виде шестнадцатеричной строки). CRC32 похожа на CHECKSUM по скорости и вероятности коллизий.

-- MySQL
SELECT CRC32('Пример текста');
3150408114

Oracle: Стандартной функции CHECKSUM нет. Часто используют ORA_HASH (быстрая хеш-функция) или функции из пакета DBMS_CRYPTO (например, HASH).

-- Oracle
SELECT ORA_HASH('Пример текста') FROM dual;
3865009934

PostgreSQL: Функция HASHTEXT (или hashchar) для типа text, возвращает integer. Также есть широкий набор функций в модуле pgcrypto (например, digest).

-- PostgreSQL
SELECT hashtext('Пример текста');
-138020914

SQLite: Встроенной функции нет. Для вычисления хешей используют определяемые пользователем функции (UDF), вызывающие, например, алгоритмы из библиотек C.

Общие языки программирования: В C# используется метод GetHashCode(), в Java — hashCode(). Важно помнить, что алгоритмы и результаты будут отличаться от SQL Server CHECKSUM.

Распространенные ошибки

1. Ожидание уникальности результата: CHECKSUM может генерировать одинаковые значения для разных входных данных (коллизии). Это нормальное поведение, а не ошибка функции.

SELECT CHECKSUM('test'), CHECKSUM('tset');
-982168958
-982168958

2. Сравнение CHECKSUM от разных типов данных без приведения: Разные типы могут давать одинаковое значение для разных данных.

SELECT CHECKSUM(123), CHECKSUM('123');
123
-1106732814

3. Игнорирование NULL: Если хотя бы один аргумент NULL, результат NULL. Это может привести к неожиданным результатам при сравнении.

-- Ожидается число, но получается NULL
SELECT CHECKSUM('A', NULL) AS Result;
Result
NULL

4. Использование для защиты данных: Функция не является криптографической и не должна использоваться для задач безопасности, таких как хеширование паролей.

Изменения в последних версиях

В документации Microsoft SQL Server не отмечается существенных изменений в работе или синтаксисе функции CHECKSUM на протяжении многих версий (включая SQL Server 2012, 2014, 2016, 2017, 2019, 2022).

Важным аспектом остается зависимость результата от параметров сортировки (collation) сервера или базы данных для строковых аргументов. Изменение параметров сортировки между версиями или при переносе базы данных теоретически может привести к изменению вычисляемых контрольных сумм для одних и тех же строковых литералов. Это следует учитывать при разработке миграций.

Функция остается стабильным и предсказуемым инструментом в рамках одной и той же среды с неизменными настройками.

Расширенные примеры применения

Использование CHECKSUM для быстрого сравнения строк таблицы.

Пример sql
-- Создание вычисляемого столбца для контроля изменений
ALTER TABLE dbo.Products ADD RowChecksum AS CHECKSUM(Name, Price, CategoryId);

-- Поиск строк, где данные изменились с момента последнего сохранения контрольной суммы
SELECT p.*
FROM dbo.Products p
WHERE CHECKSUM(p.Name, p.Price, p.CategoryId) <> p.SavedChecksum;

Применение CHECKSUM_AGG для определения изменений в группе строк.

Пример sql
-- Контрольная сумма всех цен в категории
SELECT CategoryId,
       CHECKSUM_AGG(CHECKSUM(Price)) AS AggChecksum
FROM dbo.Products
GROUP BY CategoryId;

-- Сравнение с сохраненным значением позволяет понять, менялись ли цены в категории

Использование в условиях соединения (JOIN) для упрощения сравнения сложных ключей (с осторожностью из-за коллизий).

Пример sql
-- Сравнение данных из двух таблиц по нескольким полям
SELECT *
FROM SourceTable s
FULL OUTER JOIN TargetTable t
    ON CHECKSUM(s.Field1, s.Field2, s.Field3) = CHECKSUM(t.Field1, t.Field2, t.Field3)
WHERE s.ID IS NULL OR t.ID IS NULL; -- Находит расхождения

Генерация псевдослучайного числа из строкового ключа для равномерного распределения.

Пример sql
-- Использование CHECKSUM и ABS для получения неотрицательного числа
SELECT UserName,
       ABS(CHECKSUM(UserName)) % 100 AS RandomBucket -- Число от 0 до 99
FROM dbo.Users;

Создание индекса на вычисляемом столбце для ускорения поиска дубликатов.

Пример sql
-- Добавление индексированного вычисляемого столбца
ALTER TABLE dbo.Orders
ADD OrderHash AS CHECKSUM(CustomerId, OrderDate, Amount) PERSISTED;

CREATE INDEX IX_Orders_Hash ON dbo.Orders(OrderHash);

-- Поиск потенциальных дубликатов
SELECT o1.*, o2.*
FROM dbo.Orders o1
INNER JOIN dbo.Orders o2
    ON o1.OrderHash = o2.OrderHash
    AND o1.OrderId < o2.OrderId -- Чтобы избежать пар (A,B) и (B,A)
WHERE CHECKSUM(o1.CustomerId, o1.OrderDate, o1.Amount) =
      CHECKSUM(o2.CustomerId, o2.OrderDate, o2.Amount); -- Окончательная проверка из-за риска коллизий

MS SQL CHECKSUM function comments

En
CHECKSUM Returns the checksum value computed over a row of a table or over a list of expressions