Детерминированные функции SQL
1. Обзор
Функции SQL в SQLite могут быть либо "детерминированными", либо "недетерминированными".
Детерминированная функция всегда возвращает тот же результат при одинаковых входных данных. Большинство встроенных функций SQL в SQLite являются детерминированными. Например, функция abs(X) всегда возвращает тот же результат, если ее входной параметр X одинаков.
Недетерминированные функции могут возвращать разные результаты при каждом вызове, даже если аргументы всегда одинаковые. Ниже приведены примеры недетерминированных функций:
Функция random() очевидно недетерминирована, так как она возвращает другой результат при каждом вызове. Результаты функций changes() и last_insert_rowid() зависят от предыдущих SQL-запросов, поэтому они также недетерминированные. Функция sqlite3_version() в основном постоянна, но может измениться при обновлении SQLite, и, хотя она всегда возвращает тот же результат для любой конкретной сессии, поскольку может менять результат между сессиями, она все равно считается недетерминированной.
2. Ограничения на использование недетерминированных функций
В некоторых контекстах в SQLite запрещено использование недетерминированных функций:
- В выражении ограничения CHECK.
- В операторе WHERE частичного индекса.
- В выражении, используемом как часть индекса по выражению.
- В выражении сгенерированного столбца.
В приведенных выше случаях значения, возвращаемые функцией, влияют на информацию, хранящуюся в файле базы данных. Значения функций в ограничениях CHECK определяют, какие записи допустимы для таблицы, а функции в операторе WHERE частичного индекса или в индексе по выражению вычисляют значения, хранящиеся в индексе дерева B. Если в дальнейшем любая из этих функций вернет другое значение, база данных может перестать быть корректной. Для предотвращения повреждения базы данных в указанных контекстах могут использоваться только детерминированные функции.
3. Обработка функций даты и времени
Встроенные функции даты и времени SQLite являются особым случаем. Эти функции обычно считаются детерминированными. Однако, если эти функции используют строку "now" как дату, или если они используют модификатор localtime или модификатор utc, то они считаются недетерминированными. Поскольку входные данные функции не обязательно известны во время выполнения, функции даты и времени будут вызывать исключение, если они столкнутся с любыми недетерминированными функциями в контексте, где разрешены только детерминированные функции.
До версии SQLite 3.20.0 (2017-08-01) все функции даты и времени всегда считались недетерминированными. Возможность того, что функции даты и времени будут иногда детерминированными, а иногда недетерминированными, в зависимости от их аргументов, была добавлена в релизе 3.20.0.
3.1. Исправление ошибки в версии 3.35.2
При внесении улучшения в SQLite 3.20.0, в результате которого функции даты и времени считались детерминированными, так как они не зависят от текущего времени, был упущен один случай: многие функции даты и времени могут вызываться без аргументов. Эти функции даты и времени без аргументов ведут себя так, как будто у них есть один аргумент "'now'". Таким образом, "datetime()" и "datetime('now')" оба возвращают текущую дату и время. Однако только второй вариант был распознан как недетерминированный. Это означало, что разработчики могли незаметно ввести недетерминированный "datetime()" вариант в ограничения CHECK, выражения индексов, выражения сгенерированных столбцов и аналогичные места, где недетерминированные функции не имеют смысла. Эта ошибка была исправлена в версии 3.35.2 (2021-03-17). Однако могут существовать устаревшие базы данных, созданные SQLite с версии 3.20.0 по 3.35.1, которые содержат недетерминированные функции даты и времени в своих схемах.
4. Детерминированные функции, определенные приложением
По умолчанию функции SQL, определенные приложением, считаются недетерминированными. Однако, если 4-й параметр функции sqlite3_create_function_v2() побитово ИЛИ с SQLITE_DETERMINISTIC, SQLite будет обрабатывать эту функцию как детерминированную.
Обратите внимание, что если недетерминированная функция помечена как SQLITE_DETERMINISTIC, а эта функция используется в операторе WHERE частичного индекса или в индексе по выражению, то когда функция начнет возвращать разные значения, связанный индекс может быть поврежден. Если функция SQL почти детерминирована (то есть, если она меняется очень редко, например, sqlite_version()), и она используется в индексе, который повреждается, повреждение можно исправить, выполнив REINDEX.
Интерфейсы, необходимые для создания функции, которая может быть иногда детерминированной, а иногда недетерминированной, в зависимости от входных данных, например, встроенные функции даты и времени, не публикуются. Общие функции SQL, определенные приложением, должны быть всегда детерминированными или всегда недетерминированными.
Эта страница была последняя обновлена 08.01.2022 05:02:57 UTC
SQLite is in the Public Domain.
https://sqlite.org/deterministic.html