sqlite 中如何进行隐式转换?

How does implicit conversions occur in sqlite?

在 SQLite 中,使用动态类型并在表达式中完成隐式转换。例如

SELECT (3 < 2); -- false
SELECT (3 < '2'); -- true (what's happning here?)
SELECT ('3' < '2'); -- false

SELECT (3 < 20); -- true
SELECT (3 < '20'); -- true (what's happning here?)
SELECT ('3' < '20'); -- false

但是 official documentation and the O'REILLY book Using SQLite 没有说明 如何在隐式转换中转换 操作数。

在 C++ 中,Standard 严格定义(即明确解释)隐式转换如何发生。例如,如果任一操作数的类型为 long double,则另一个操作数将转换为 long double.

SQLite中有这样的规则吗?

来自 Datatypes In SQLite Version 3/4.1. Sort Order:

An INTEGER or REAL value is less than any TEXT or BLOB value.

显然:

SELECT TYPEOF(3);

returns integer

SELECT TYPEOF('2');
SELECT TYPEOF('20');

return text.
所以这里没有转换:

SELECT 3 < '2';

其中 returns true.
但是在这样的表达式中有一个隐式转换:

SELECT 3 < '2' + 0;

which returns false 并且此转换是由运算符 + 强制执行的,该运算符将数字运算应用于 '2',从而将其转换为 integer.

编辑澄清: 此行为仅适用于 3'2'.
等字面值 当涉及到表达式或列值时,会发生隐式转换
因此,如果您定义一个 table,例如:

create table test(id integer); 
insert into test(id) values (1), (2), (3); 

像这样的语句:

select * from test where id > '1'

将return:

| id  |
| --- |
| 2   |
| 3   |

查看 demo.

隐式转换有时会发生,有时不会。 4.2. Type Conversions Prior To Comparison 中描述了确定是否在比较之前完成转换的条件。根据栏目,

Affinity is applied to operands of a comparison operator prior to the comparison according to the following rules in the order shown:

  • If one operand has INTEGER, REAL or NUMERIC affinity and the other operand has TEXT or BLOB or no affinity then NUMERIC affinity is applied to other operand.

  • If one operand has TEXT affinity and the other has no affinity, then TEXT affinity is applied to the other operand.

  • Otherwise, no affinity is applied and both operands are compared as is.

但是表达式(包括文字)的类型亲和性是如何定义的?在3.2. Affinity Of Expressions中解释为

Every table column has a type affinity (one of BLOB, TEXT, INTEGER, REAL, or NUMERIC) but expressions do no necessarily have an affinity.

Expression affinity is determined by the following rules:

  • The right-hand operand of an IN or NOT IN operator has no affinity if the operand is a list and has the same affinity as the affinity of the result set expression if the operand is a SELECT.

  • When an expression is a simple reference to a column of a real table (not a VIEW or subquery) then the expression has the same affinity as the table column.

    1. Parentheses around the column name are ignored. Hence if X and Y.Z are column names, then (X) and (Y.Z) are also considered column names and have the affinity of the corresponding columns.

    2. Any operators applied to column names, including the no-op unary "+" operator, convert the column name into an expression which always has no affinity. Hence even if X and Y.Z are column names, the expressions +X and +Y.Z are not column names and have no affinity.

  • An expression of the form "CAST(expr AS type)" has an affinity that is the same as a column with a declared type of "type".

  • A COLLATE operator has the same affinity as its left-hand side operand.

  • Otherwise, an expression has no affinity.

因此,对于 OP 中的示例,文字没有亲和力,因此按原样进行比较。自

An INTEGER or REAL value is less than any TEXT or BLOB value.

3 < '2' returns true.

中指出

这些规则正确描述了 中提到的明显奇怪的行为。 CAST ('1' AS INTEGER) 是否具有类型亲和力 INTEGER,因此 >= '1' 被解释为 >= 1,因此 CAST ('1' AS INTEGER) >= '1' returns true1 >= '1' returns false.