数据类型支持

与大多数 SQL 数据库不同,Adobe AIR SQL 数据库引擎不要求或强制表列包含某种类型的值。相反,运行时使用两个概念(存储类和列关联)来控制数据类型。本部分介绍存储类和列关联,以及如何在各种情况下解决数据类型差异:

存储类

存储类表示用于在数据库中存储值的实际数据类型。下列存储类由数据库使用:

NULL
值为 NULL 值。

INTEGER
值为带符号的整数。

REAL
值为浮点数值。

TEXT
值为文本字符串(限制为 256 MB)。

BLOB
值为二进制大型对象 (BLOB);换句话说,为原始二进制数据(限制为 256 MB)。

对于作为嵌入在 SQL 语句中的文本或使用参数绑定到准备的 SQL 语句的值提供给数据库的所有值,都在执行 SQL 语句之前为其分配存储类。

如果属于 SQL 语句的文本括在单引号或双引号中,则为其分配存储类 TEXT;如果文本被指定为没有小数点或指数的不带引号数字,则分配 INTEGER;如果文本是带有小数点或指数的不带引号数字,则分配 REAL;如果值为 NULL,则分配 NULL。具有存储类 BLOB 的文本是使用 X'ABCD' 表示法指定的。有关详细信息,请参阅表达式中的字面值。

对于作为使用 SQLStatement.parameters 关联数组的参数提供的值,为其分配与绑定的本机数据类型最紧密匹配的存储类。例如,int 值作为 INTEGER 存储类绑定,为 Number 值分配 REAL 存储类,为 String 值分配 TEXT 存储类,为 ByteArray 对象分配 BLOB 存储类。

列关联

列的 关联 是存储在该列中的数据的建议类型。一个值存储在列中(通过 INSERT 或 UPDATE 语句)时,运行时尝试将该值从其数据类型转换为指定的关联。例如,如果将 Date 值(ActionScript 或 JavaScript Date 实例)插入到一个其关联为 TEXT 的列中,则 Date 值在存储于数据库中之前将转换为 String 表示形式(等效于调用对象的 toString() 方法)。如果该值无法转换为指定的关联,则出现错误,且不执行操作。使用 SELECT 语句从数据库中检索值时,它作为对应于关联的类的实例返回,而不管它在被存储时是否已从不同数据类型转换。

如果一个列接受 NULL 值,则 ActionScript 或 JavaScript 值 null 可用作参数值在该列中存储 NULL。当 NULL 存储类值在 SELECT 语句中检索时,它始终作为 ActionScript 或 JavaScript 值 null 返回,而不管列的关联如何。如果一个列接受 NULL 值,则在尝试将值转换成不可为 Null 的类型(如 Number 或 Boolean)之前,始终检查从该列检索的值以确定它们是否为 null。

为数据库中的每个列分配以下类型关联之一:

  • TEXT(或 String)

  • NUMERIC

  • INTEGER(或 int)

  • REAL(或 Number)

  • Boolean

  • Date

  • XML

  • XMLLIST

  • Object

  • NONE

TEXT(或 String)

具有 TEXT 或 String 关联的列使用存储类 NULL、TEXT 或 BLOB 存储所有数据。如果将数字值插入到具有 TEXT 关联的列中,则在存储它之前将它转换为文本形式。

NUMERIC

具有 NUMERIC 关联的列包含使用存储类 NULL、REAL 或 INTEGER 的值。将文本数据插入到 NUMERIC 列中时,在存储它之前,会尝试将它转换为整数或实数。如果转换成功,则使用 INTEGER 或 REAL 存储类存储值(例如,值 '10.05' 在被存储之前转换为 REAL 存储类)。如果无法执行转换,则出现错误。不会尝试转换 NULL 值。从 NUMERIC 列检索的值作为该值适合的最具体数字类型的实例返回。换句话说,如果该值是一个正整数或 0,则它作为 uint 实例返回。如果它是一个负整数,则它作为 int 实例返回。最后,如果它具有浮点部分(它不是一个整数),则它作为 Number 实例返回。

INTEGER(或 int)

使用 INTEGER 关联的列的行为方式与具有 NUMERIC 关联的列相同,但有一处不同。如果要存储的值是一个没有浮点部分的实数值(如 Number 实例),或者该值是可转换为没有浮点部分的实数值的文本值,则将它转换为整数并使用 INTEGER 存储类存储它。如果尝试存储具有浮点部分的实数值,则出现错误。

REAL(或 Number)

具有 REAL 或 NUMBER 关联的列的行为与具有 NUMERIC 关联的列类似,但是它将整数值强制为浮点表示形式。REAL 列中的值始终作为 Number 实例从数据库返回。

Boolean

具有 Boolean 关联的列存储 true 或 false 值。Boolean 列接受作为 ActionScript 或 JavaScript Boolean 实例的值。如果代码尝试存储字符串值,则将长度大于零的字符串视为 true,将空字符串视为 false。如果代码尝试存储数字数据,则任何非零值作为 true 存储,而 0 作为 false 存储。使用 SELECT 语句检索 Boolean 值时,它作为 Boolean 实例返回。非 NULL 值是使用 INTEGER 存储类存储的(0 表示 false,1 表示 true),并在检索数据时转换为 Boolean 对象。

Date

具有 Date 关联的列存储日期和时间值。Date 列用于接受作为 ActionScript 或 JavaScript Date 实例的值。如果尝试在 Date 列中存储 String 值,则运行时会尝试将该 String 值转换为罗马儒略历日期。如果转换失败,则出现错误。如果代码尝试存储 Number、int 或 uint 值,则不会尝试验证数据,而假定它是有效的罗马儒略历日期值。使用 SELECT 语句检索的 Date 值将自动转换为 Date 实例。使用 REAL 存储类将 Date 值存储为罗马儒略历日期值,因此排序和比较操作可以如预期的那样进行。

XML 或 XMLList

使用 XML 或 XMLList 关联的列存储 XML 结构。当代码尝试使用 SQLStatement 参数在 XML 列中存储数据时,运行时会尝试使用 ActionScript XML() 或 XMLList() 函数转换和验证值。如果该值无法转换为有效的 XML,则出现错误。如果存储数据的尝试使用 SQL 文本字面值(例如 INSERT INTO (col1) VALUES ('Invalid XML (no closing tag)')),则不分析或验证该值 — 而是假定它的格式正确。如果存储了无效值,则在检索它时,它作为空的 XML 对象返回。XML 和 XMLList 数据是使用 TEXT 存储类或 NULL 存储类存储的。

Object

具有 Object 关联的列存储 ActionScript 或 JavaScript 复杂对象,其中包括 Object 类实例以及 Object 子类的实例(如 Array 实例),甚至还包括自定义类实例。Object 列数据以 AMF3 格式进行序列化,并使用 BLOB 存储类进行存储。在检索一个值时,它从 AMF3 进行反序列化,并在被存储时作为类的实例返回。请注意,某些 ActionScript 类(尤其是显示对象)无法反序列化为其原始数据类型的实例。在存储自定义类实例之前,必须使用 flash.net.registerClassAlias() 方法(或者在 Flex 中,通过向类声明添加 [RemoteObject] 元数据)为该类注册一个别名。此外,在检索该数据之前,必须为类注册相同的别名。无法正确进行反序列化的任何数据(因为类本身无法进行反序列化,或者因为缺少类别名或类别名不匹配),在被存储时作为具有对应于原始实例的属性和值的匿名对象(Object 类实例)返回。

NONE

对于具有关联 NONE 的列,使用任何存储类都是等效的。它不尝试在插入数据之前将其转换。

确定关联

列的类型关联由在 CREATE TABLE 语句中声明的列类型确定。在确定类型时,可应用以下规则(不区分大小写):

  • 如果列的数据类型包含字符串“CHAR”、“CLOB”、“STRI”或“TEXT”中的任一个,则该列具有 TEXT/String 关联。请注意,类型 VARCHAR 包含字符串“CHAR”,因此为其分配 TEXT 关联。

  • 如果列的数据类型包含字符串“BLOB”,或者未指定数据类型,则该列具有关联 NONE。

  • 如果列的数据类型包含字符串“XMLL”,则该列具有 XMLList 关联。

  • 如果数据类型是字符串“XML”,则列具有 XML 关联。

  • 如果数据类型包含字符串“OBJE”,则列具有 Object 关联。

  • 如果数据类型包含字符串“BOOL”,则列具有 Boolean 关联。

  • 如果数据类型包含字符串“DATE”,则列具有 Date 关联。

  • 如果数据类型包含字符串“INT”(包括“UINT”),则为其分配 INTEGER/int 关联。

  • 如果列的数据类型包含字符串“REAL”、“NUMB”、“FLOA”或“DOUB”中的任一个,则该列具有 REAL/Number 关联。

  • 否则,关联为 NUMERIC。

  • 如果表使用 CREATE TABLE t AS SELECT... 语句创建的,则所有列都未指定数据类型,将为它们分配关联 NONE。

数据类型与比较运算符

支持以下二元比较运算符 =、<、<=、>= 和 !=,以及测试集合成员身份的运算符 IN 和三元比较运算符 BETWEEN。有关这些运算符的详细信息,请参阅“运算符”。

比较的结果取决于所比较的两个值的存储类。在比较两个值时,可应用以下规则:

  • 将具有存储类 NULL 的值视为小于其他任何值(包括具有存储类 NULL 的其他值)。

  • INTEGER 或 REAL 值小于任何 TEXT 或 BLOB 值。对 INTEGER 或 REAL 与其他 INTEGER 或 REAL 进行比较时,将执行数字比较。

  • TEXT 值小于 BLOB 值。对两个 TEXT 值进行比较时,将执行二元比较。

  • 对两个 BLOB 值进行比较时,结果始终是使用二元比较确定的。

始终将三元运算符 BETWEEN 重新转换为等效的二元表达式。例如,a BETWEEN b AND c 将重新转换为 a >= b AND a <= c,即使这意味着在计算表达式所需的每个比较中将不同的关联应用于 a。

a IN (SELECT b ....) 类型的表达式由先前为二元比较列举的三个规则处理,即以与 a = b 类似的方式。例如,如果 b 是一个列值,a 是一个表达式,则在进行任何比较之前,将 b 的关联应用于 a。将表达式 a IN (x, y, z) 重新转换为 a = +x OR a = +y OR a = +z。IN 运算符右侧的值(此示例中为 x、y 和 z 值)被视为表达式,即使它们碰巧是列值。如果 IN 左侧的值是一个列,则使用该列的关联。如果该值是一个表达式,则不发生转换。

执行比较的方式也会受到使用 COLLATE 子句的影响。有关详细信息,请参阅 COLLATE。

数据类型与数学运算符

对于每个支持的数学运算符(*、/、%、+ 和 -),在计算表达式之前,会将数字关联应用于每个操作数。如果任一操作数无法成功转换为 NUMERIC 存储类,则表达式的计算结果将为 NULL。

如果使用了串联运算符 ||,则在计算表达式之前将每个操作数转换为 TEXT 存储类。如果任一操作数无法转换为 TEXT 存储类,则表达式的结果为 NULL。在两种情况下可能发生无法转换值的此问题:操作数的值为 NULL,或者它是包含非 TEXT 存储类的 BLOB。

数据类型与排序

通过 ORDER BY 子句对值排序时,具有存储类 NULL 的值排在最前面。它们后跟按数字顺序散布的 INTEGER 和 REAL 值,再后跟按二进制顺序或基于指定排序规则(BINARY 或 NOCASE)的 TEXT 值。最后是按二进制顺序的 BLOB 值。在排序之前,不发生存储类转换。

数据类型与分组

使用 GROUP BY 子句对值分组时,将具有不同存储类的值视为非重复。例外是 INTEGER 和 REAL 值,如果它们在数值上相等,则认为它们相等。GROUP BY 子句不会导致将关联应用于任何值。

数据类型与复合 SELECT 语句

复合 SELECT 运算符 UNION、INTERSECT 和 EXCEPT 执行值之间的隐式比较。在执行这些比较之前,可能会将关联应用于每个值。相同的关联(如果有)将应用于在复合 SELECT 结果集的单个列中可能返回的所有值。所应用的关联是在该位置中具有列值(而不是其他某种表达式)的第一个构成性 SELECT 语句所返回的列的关联。如果对于给定的复合 SELECT 列,构成性 SELECT 语句都不返回列值,则在对该列中的值进行比较之前,不将关联应用于这些值。