Deterministic SQL Functions
Deterministic SQL Functions
1.概述
SQLite中的SQL函数可以是“确定性”或“非确定性”。
确定性函数具有相同的输入时始终给出相同的答案。SQLite中的大多数内置SQL函数都是确定性的。例如,只要输入X是相同的,abs(X)函数总是返回相同的答案。
即使参数总是相同,非确定性函数也可能在每次调用时给出不同的答案。以下是非确定性函数的例子:
- random()
- changes()
- last_insert_rowid()
- sqlite3_version()
random()函数显然是非确定性的,因为它每次调用时都会给出不同的答案。更改()和last_insert_rowid()的答案取决于以前的SQL语句,因此它们也是非确定性的。sqlite3_version()函数大多是不变的,但是当SQLite升级时它可以改变,所以即使它总是为任何特定的会话返回相同的答案,因为它可以在会话之间改变答案,但它仍然被认为是非确定性的。
2.限制使用非确定性功能
SQLite中有一些上下文不允许使用非确定性函数:
- 在CHECK约束的表达式中。
- 在部分索引的WHERE子句中。
- 在用作表达式索引一部分的表达式中。
在上述情况下,函数返回的值影响存储在数据库文件中的信息。CHECK约束中的函数值确定哪些条目对表有效,并且部分索引的WHERE子句中的函数或表达式的索引中的函数计算存储在索引b-tree中的值。如果这些函数中的任何一个稍后返回不同的值,那么数据库可能不再是格式良好的。因此,为了避免数据库损坏,只有确定性函数可以用在上面的上下文中。
3.日期/时间函数的特殊情况处理
SQLite的内置日期和时间函数是一个特例。这些功能通常被认为是确定性的。但是,如果这些函数使用字符串“now”作为日期,或者它们使用本地时间修饰符或utc修饰符,则它们被认为是非确定性的。由于函数输入在运行时不一定是已知的,所以如果在只允许确定性函数的上下文中遇到任何非确定性特征,日期/时间函数将抛出异常。
在SQLite 3.20.0之前(2017-08-01),所有日期/时间函数总是被认为是非确定性的。日期/时间函数有时是确定性的,而在其他时候是非确定性的,这取决于它们的参数,是为3.20.0版本添加的。
4.应用程序定义的确定性功能
默认情况下,应用程序定义的SQL函数被认为是非确定性的。但是,如果sqlite3_create_function_v2()的第4个参数与SQLITE_DETERMINISTIC进行或运算,那么SQLite会将该函数看作是确定性的。
请注意,如果使用SQLITE_DETERMINISTIC标记了非确定性函数,并且该函数最终在部分索引的WHERE子句中或表达式索引中使用,那么当函数开始返回不同的答案时,关联的索引可能会损坏。如果一个SQL函数几乎是确定性的(也就是说,如果它很少发生变化,就像sqlite_version()),并且它被用在一个损坏的索引中,那么可以通过运行REINDEX来修复损坏。
构建函数的必要接口有时是确定性的,有时是不确定的,取决于它们的输入,例如内置的日期/时间函数,不会公布。通用应用程序定义的SQL函数必须始终是确定性的或者总是非确定性的。
SQLite在公共领域。