数据类型转换

类型系统是一组规则和转换,Nuodb在查询编译期间适用于数据类型。该过程的目标是:

  1. 在查询执行过程中尽早检测和纠正数据类型中的不匹配

  2. 为了防止由查询语言的错误造成的用户应用程序中的错误。

本节中使用的术语“类型”的所有引用都有关“数据类型”。

Data type conversions are necessary because many operators and functions expect each of their arguments to be of a certain data type which allows for proper reconciliation of scale, precision, length, collation, etc. during comparisons and computations. In addition, data type conversions are necessary to choose a single data type for the results of conditional expressions and the items in the 选择 list 联盟 or 联盟 ALL.

隐式与显式数据类型转换

NuoDB avoids implicit data conversions (coercions) that could lead to loss of precision and issues an error message in such cases. The user can use the CAST operator to allow a conversion that could lead to loss of precision or for overriding the implicit conversion behavior. Refer to the 数据类型转换表 in this section.

数据类型转换的含义

数据类型转换可以改变比较操作的语义。考虑以下示例:

  • '00001'= 1是真的,如果字符串'00001'被转换为数值1,则为真,但如果1转换为字符串'1'则为false。

  • '100'<如果字符串'100'被转换为数值100,则为2是假的,但如果2转换为字符串'2',则为true。

由于在比较运算符中的列上应用数据转换时,不能使用索引。 这是因为索引数据类型的自然排序可能与比较所需的顺序不同。

LOB数据类型(CLOB或BLOB)的隐式转换需要值的内存内存副本,并且可能具有负性效增。

类型信息的来源

NuodB使用两个来源获取类型信息:表列定义和查询常量。

Nuodb支持布尔,字符串,数字,二进制和时间常数

布尔常数

Nuodb为特殊单词创建了一个布尔常量,而是假的。有关更多详细信息,请阅读 sql-boolematepes..

字符串常数

Nuodb为查询字符串中的引用文字创建字符串类型的常量。 NuodB不提供创建VARCHAR或CHAR常量的方法。

有关Nuodb中的字符串类型的更多信息,请参阅 SQLString和字符类型

数字常数

有3种格式称为NOODB中的数字常量:

  • 整数类型(例如1230)

  • 数字数字(例如12.30)

  • 科学符号(例如123E1)

NuoDB selects the smallest type in which the value can be stored. For example, the constant 100 will have a type SMALLINT while the constant 40001 will be of type INTEGER. For more information on numbers, see SQL数字类型.

Constants using the scientific notation will be integer types if they have a zero fractional part (e.g. 1e1 is interpreted as a SMALLINT). They will have a NUMERIC type if the fractional part is non-zero (e.g. 1e-1 is a NUMERIC(2, 1))

二元常数

NuoDB creates a constant with type BINARY for hexadecimal constants. For more information on binary constants, please read SQL二进制类型

颞常数

时间常量是以timtestamp,时间或日期关键字前缀的常量,后跟时间值的文本表示。有关时间常数的更多信息,请阅读 SQL日期和时间类型

表列

The type for table columns is defined when the column is created and can be altered with 改变表 statements.

功能和运营商

对于类型系统,Nuodb实现了两类功能和运算符:

  • Signature operators and functions (e.g. SUBSTRING, YEAR, etc. - see SQL函数和操作 综合清单)

  • Common Type operators and functions (e.g. COALESCE, IFNULL, etc. - see SQL函数和操作 对于全面的清单)。

签名函数和运营商

每个签名函数或运算符都有一个签名列表,具体取决于它接受的参数数及其类型。作为在查询编译期间的单独步骤,Nuodb Defuces基于运算符或函数的参数应用哪些签名。如果有没有’T完全匹配,Nuodb使用类型推断推断最接近的匹配签名,然后在参数上应用隐式转换(胁迫)以将它们转换为所需类型。如果在参数的类型和签名所需的类型之间不允许使用胁迫,Nuodb返回错误。下表显示了支持的隐式转换。

数据类型转换表

下表介绍了NOODB中支持的数据类型转换: 标量数据类型转换表

例子

The SUBSTRING function has the following two signatures:

(String, Integer) -> String
(String, Integer, Integer) -> String

对于以下查询:

select substring(123456, 1.0, '2') s1, substring('aaaa', '3') s2 from dual;

类型系统将以以下方式使用签名:

  • 对于S1,不能使用第一个签名,因为参数的数量不匹配。唯一的其他选项是第二个签名,因此每个参数将转换为它指定的类型。

  • 类似地,对于S2,由于参数的数量,并且剩下唯一的选项是使用第一个签名而无法应用第二个签名。

应用签名后,将查询重写为:

select
     substring(coerce(123456 as string), coerce (1.0 as integer), coerce('2' as integer)) s1,
     substring('aaaa', coerce('3' as integer)) s2
from dual;

常见类型

使用公共类型方法处理的操作符和函数在相同类型的参数上运行。在编译时,Nuodb使用以下常见类型转换表介绍了分数的通用类型:

类型

过渡

细绳

字符串→布尔值→字节→数字→双→时间→时间戳

char

char →Varchar→弦→布尔值→字节→数字→双→时间→时间戳

varchar.

varchar→串→布尔值→字节→数字→双→时间→时间戳

small

Smallint→整数→Bigint→数字→Float→Double

整数

整数→Bigint→数字→Float→Double

big

Bigint→数字→双倍

漂浮

float→双倍

双倍的

双倍的

日期

日期→时间戳

时间戳

时间戳

时间

时间→时间戳

斑点

斑点 →字节

cl

CLOB→字符串→字节

数字

数字→双倍

数字

数字→数字→双倍

字节

字节→Bigint→数字

二进制

二进制→varbinary→bytes

varbinary.

varbinary→字节

布尔基

布尔→Smallint→整数→Bigint→数字→Float→Double

通过在它们各自的转换类型上迭代来计算任意两种类型的通用类型并在两个共同的转换类型处停止。在对多个参数上应用公共类型算法时,Nuodb首先评估每个参数的类型。然后,Nuodb计算所有参数的公共类型。通过计算当前参数和下一个参数之间的公共类型,从左到右,从左到右进行,直到没有更多的参数。请注意,在这种情况下,规则不关联;生成的类型取决于参数出现在运营商或函数中的顺序。

例子

COALESCE 采用可变数量的参数,并返回第一个(从左到右),它不是null的。要确定此函数的返回类型,Nuodb计算所有参数的常用类型,隐式地将它们中的所有类型转换为公共类型,并将其设置为函数的返回类型:

select coalesce('1', 1, cast(2 as double)) from dual;

在这种情况下,CapeSce被调用类型字符串,SmallInt和Double。字符串和Smallint之间的常用类型是数字(转换表中的第一匹配项)。数字和双倍之间的通用类型是双倍。因此,CooleSce函数将返回双倍,所有参数将被转换为双倍。 NOODB内部将查询重写为:

select coalesce(coerce('1' as double), coerce (1 as double), cast(2 as double)) from dual;

胁迫运营商

The COERCE operator performs the implicit conversions decided by the Type System.

在查询计划中存在此运算符表示初始查询包含类型差异,并且由NOODB查询编译器自动纠正此类差异。

Functionally, the COERCE operator is similar to the CAST operator, but COERCE is not available as a separate call (it is only used internally). While the CAST operator performs truncation or rounding in cases when the value to be converted does not fit in the target type, the COERCE operator, throws an error instead if the conversion would require truncation or rounding.

To understand the difference between CAST and COERCE consider the following example:

SQL>create table t(col decimal(4, 2));
SQL>insert into t(col) values(2.1);
SQL>insert into t(col) values(2.6);
SQL>explain select substring('nuodb', col) from t;
Select
  List
   Alias:SUBSTR
     Substr
       "nuodb"
          Coerce T.COL
            as integer
Table Scan T  [cost: 33.00, rows: 11.00]

The second argument is wrapped in a COERCE operator because the type of this argument is decimal(4, 2) while SUBSTR expect an integer. If we were to execute this query, we would get an error because the value 2.1 cannot be converted to an integer without the loss of the decimal part:

SQL>select substring('nuodb', col) from t;
 数字  overflow converting integer of scale 1 to integer of scale 0

在这种情况下,为了实现从列Col到整数的所需行为,用户必须将该值显式转换为整数:

SQL>explain select substring('nuodb', cast(col as integer)) from t;
        Select
          List
            Alias:SUBSTR
              Substr
               "nuodb"
                Cast
                  T.COL
                   as integer
          Table Scan T  [cost: 33.00, rows: 11.00]

SQL>select col, substring('nuodb', cast(col as integer)) from t;
        COL  SUBSTR
        ---- -------
        2.10  uodb
        2.60  odb

笔记 that in this case the query plan does not contain a COERCE operator (since CAST already returns an integer type), and the decimal column is rounded to an integer.

Another important difference between the COERCE and CAST operators is that the COERCE operator can be removed automatically as NuoDB replaces expressions containing constants with their results (the so called "constant folding" optimization), while CAST is never optimized this way. This means that coercions might have been performed on constants at compile time and not be visible in the query plan. Using SUBSTRING as an example again:

SQL>explain (object_types on) select 1 const, substring(string_col, 1) from t1 ;
         Select
           List
            Alias:CONST
              "1" (smallint)
            Alias:SUBSTR
              Substr
                Field T1.STRING_COL
                "1" (integer)
Table Scan T1  [cost: 117.00, rows: 13.00]

输出显示常量1作为类型的Smallint在单独使用时,但用作子字符串的参数时是类型的整数。出现这种情况,因为子字符串表达式被重写为子字符串(String_col,强制(1为整数)),然后将第二个参数进行优化到整数1。

算术表达式

算术表达式(+, - ,%,*和/)的签名定义为(数字,数字)→数字可以是任何NOODB编号类型的数字。

签名以两步应用。在第一步中,基于公共类型转换表将每个参数强制到数字类型之一。在第二步中,基于更新的参数计算公共类型,此类型将是表达式的返回类型。如果生成的通用类型是一个smallint或整数,则nuodb将其升级到下一个更大的类型以允许溢出的空间。如果常用类型是smallint,则返回类型将是整数;如果公共类型是整数,则结果类型将是BigInteger。

例子

对于查询:

select '1.1' + 1 from dual;

第一步决定字符串常量'1.1'的类型数字,因为这是从字符串到数字类型的唯一可用转换。在步骤2中,确定表达式的返回类型基于数字和SmallInt之间的公共类型为数字。查询内部重写为:

select coerce('1.1' as numeric) + 1 from dual;

数字参数的操作精度和比例

当应用于数字操作时,Nuodb计算使用下表的算法(“LHS”表示左参数,“RHS”右侧)使用算法计算。:

表达

精确

规模

LHS + RHS.

1 + max(lhs.precision,rhs.precision)

Max(LHS.Scale,RHS.Scale)

LHS - RHS.

1 + max(lhs.precision,rhs.precision)

Max(LHS.Scale,RHS.Scale)

LHS%RHS.

min(lhs.precision - lhs.scale,rhs.precision - lhs.scale)+结果。商标

Max(LHS.Scale,RHS.Scale)

LHS * RHS.

lhs.precision + Rhs.Precision.

LHS.Scale + RHS.Cale.

LHS / RHS.

lhs.precision - lhs.scale + Rhs.scale +结果.scale

Max(6,LHS.Scale + RHS.Precision + 1)

注意,相同的算法也应用于这些表达式的功能变体(例如div,mod等)。

查询参数

SQL标准不提供在编译时指定查询参数的类型的方法。 Nuodb考虑查询参数是类型字符串,允许常规算法决定应将其胁迫的类型。这种方法允许在各种情况下获得正确的结果:

SQL>select 1 / 1 as consts, 1 / ? query_parameters from dual;
Enter value: 1

CONSTS  query_parameters
------- ----------
1        1.000000

Because the type of the variable is string, the result of the second expression is Numeric. In additional, a default scale and precision are computed for it. The CAST operator can be used to overcome this limitation.

比较运算符

比较运算符也使用公共类型签名方法。在查询编译期间,在比较的参数之间决定了一个通用类型。仅当操作员无法比较两个参数时才会应用胁迫。这意味着例如,当比较整数TOA十进制(10,3)时,将在不执行胁迫。但是,当将整数与字符串进行比较时,字符串将被强制到数字类型。

查询优化器无法正确决定何时可以执行索引扫描,如果从索引中的列包裹在胁迫操作员中。因此,Nuodb在这种情况下避免了不必要的胁迫。

启用类型检查时,当列数据类型和比较表达式是不同的数据类型时,无法使用索引。在比较不同类型的数量时,Nuodb将使用索引。在诸如将字符串列与数字表达式进行比较的情况下不会使用索引。键入铸造表达式值以同意列数据类型将利用可用的索引。

在运营商中

在运营商中 applies the comparison common type algorithm in two steps. First, it determines the common type between the elements in the IN list and then the common type between the left-hand argument and the common type of the IN list. The common type of the arguments on the right-hand side is computed from left to right by computing the common type between the currently computed common type and the next argument.

有条件的表达

The conditional expressions (CASE, COALESCE, LEAST, GREATEST, IFNULL) are defined on a list of arguments (and search conditions, in the case of CASE) and return one of these arguments. The NuoDB Type System must make sure that all of the arguments have the same type (and precision and scale in case of decimal or numeric arguments) so that the type of the value computed during query evaluation is consistent across all the rows of the returned result.

例子:

SQL>create table t1(s smallint, i int, d1 decimal (10, 4), d2 decimal(14, 3));
SQL>insert into t1 values(1, 2, 3, 4);
SQL>insert into t1 values(2, 1, 3, 4);
SQL>insert into t1 values(2, 3, 1, 4);
SQL>insert into t1 values(2, 3, 4, 1);
SQL>explain select least(s, i, d1, d2) from t1;
Select
  List
    Alias:LEAST
      Least
        Coerce
          T1.S
            as numeric(15,4)
        Coerce
          T1.I
            as numeric(15,4)
        Coerce
          T1.D1
            as numeric(15,4)
        Coerce
          T1.D2
            as numeric(15,4)
Table Scan T1  [cost: 168.00, rows: 14.00]

在上面的示例中,最不表达式的参数都被强制到相同的精度和比例,以便在多行中强制一致的结果,如下所示:

SQL>select s, i, d1, d2, least(s, i, d1, d2) from t1;
S  I    D1    D2   LEAST
-- -- ------ ----- ------
1  2  3.0000 4.000 1.0000
2  1  3.0000 4.000 1.0000
2  3  1.0000 4.000 1.0000
2  3  4.0000 1.000 1.0000

案例和案例搜索

对于两个版本的情况,Nuodb为案例表达式的所有分支执行相同类型,精度和比例。考虑上面的表T1,返回列I或列D1的案例表达式将具有以下查询计划:

SQL>explain select case when i = 1 then i when d1 = 1 then d1 end from t1;
Select
  List
   Case
     Eql
      T1.I
      "1"
     Coerce
       T1.I
       as numeric(13,4)
     Eql
       T1.D1
       "1"
     Coerce
       T1.D1
       as numeric(13,4)
Table Scan T1  [cost: 168.00, rows: 14.00]

并返回以下结果:

SQL>select i, d1, case when i = 1 then i when d1 = 1 then d1 end from t1;
I    D1
-- ------ ------
2  3.0000 <null>
1  3.0000 1.0000
3  1.0000 1.0000
3  4.0000 <null>

搜索条件的类型与返回值的分支的公共类型单独确定。对于案例的更常规版本,在隔离中对每个条件强制执行正确性:

SQL>explain select case when s < 2 then 2 when s < '3' then 3 end from t1;
Select
  List
    Case
      Lss
       Coerce
         T1.S
         as numeric
       "2"
      "2"
      Lss
        T1.S
       "3"
      "3"
Table Scan T1  [cost: 30.00, rows: 10.00]

在第一条件下,S和常数“2”与数字进行比较。在第二个条件下,将S和常数“3”与字符串进行比较。

对于案例搜索变体,在第一个参数和所有返回的值上强制强制执行公共类型:

SQL>explain select case s when 2 then 2 when '3' then 3 end from t1;
Select
  List
    CaseSearch
      Coerce
        T1.S
        as numeric
        "2"
        "2"
        "3"
        "3"
Table Scan T1  [cost: 30.00, rows: 10.00]

在上面的示例中,所有比较都是对数字执行的。

联盟

Nuodb使用公共类型来决定每个列的类型,精度和比例,在与Union分支的查询结果中,并将每个分支中的列胁迫到公共类型。通用类型通过分支计算,并不换向。

例子:

SQL>create table t1(i int, d date);
SQL>create table t2(dec decimal(7, 2), tm timestamp);
SQL>select i, d from t1 union select dec, tm from t2;
SQL>explain select i, d from t1 union select dec, tm from t2;
Select
  *** union fields ***
    Union
      Select
       List
        Alias:I
         Coerce
          T1.I
          as numeric(9,2)
         Alias:D
          Coerce
          T1.D
          as timestamp
       Table Scan T1  [cost: 60.00, rows: 10.00]
     Select
       List
         Alias:DEC
          Coerce
            T2.DEC
            as numeric(9,2)
          T2.TM
       Table Scan T2  [cost: 60.00, rows: 10.00]

在上面的例子中,返回列的类型是十进制(9,2)和时间戳,并且胁迫已经放置在最初没有正确类型的所有列上。 T2.TM列未被胁迫,因为它已经是时间戳。