更新时间:2024-03-06 GMT+08:00

概述

背景信息

在SQL语言中,每个数据都与一个决定其行为和用法的数据类型相关。GaussDB(DWS)提供一个可扩展的数据类型系统,该系统比其它SQL实现更具通用性和灵活性。因而,GaussDB(DWS)中大多数类型转换是由通用规则来管理的,这种做法允许使用混合类型的表达式。

GaussDB(DWS)扫描/分析器只将词法元素分解成五个基本种类:整数、浮点数、字符串、标识符和关键字。大多数非数字类型首先表现为字符串。SQL语言的定义允许将常量字符串声明为具体的类型。例如:

1
2
3
4
5
SELECT text 'Origin' AS "label", point '(0,0)' AS "value";
 label  | value
--------+-------
 Origin | (0,0)
(1 row)

示例中有两个文本常量,类型分别为text和point。如果没有为字符串文本声明类型,则该文本首先被定义成一个unknown类型。

GaussDB(DWS)分析器里,有四种基本的SQL结构需要独立的类型转换规则:

  • 函数调用

    多数SQL类型系统是建筑在一套丰富的函数上的。函数调用可以有一个或多个参数。因为SQL允许函数重载,所以不能通过函数名直接找到要调用的函数,分析器必须根据函数提供的参数类型选择正确的函数。

  • 操作符

    SQL允许在表达式上使用前缀或后缀(单目)操作符,也允许表达式内部使用双目操作符(两个参数)。像函数一样,操作符也可以被重载,因此操作符的选择也和函数一样取决于参数类型。

  • 值存储

    INSERT和UPDATE语句将表达式结果存入表中。语句中的表达式类型必须和目标字段的类型一致或者可以转换为一致。

  • UNION,CASE和相关构造

    因为联合SELECT语句中的所有查询结果必须在一列里显示出来,所以每个SELECT子句中的元素类型必须相互匹配并转换成一个统一类型。类似地,一个CASE构造的结果表达式必须转换成统一的类型,这样整个case表达式会有一个统一的输出类型。同样的要求也存在于ARRAY构造以及GREATEST和LEAST函数中。

系统表PG_CAST存储了有关数据类型之间的转换关系以及如何执行这些转换的信息。

语义分析阶段会决定表达式的返回值类型并选择适当的转换行为。数据类型的基本类型分类,包括:boolean,numeric,string,bitstring,datetime,timespan,geometric和network。每种类型都有一种或多种首选类型用于解决类型选择的问题。根据首选类型和可用的隐含转换,就可能保证有歧义的表达式(那些有多个候选解析方案的)得到有效的方式解决。

所有类型转换规则需遵循以下基本原则:

  • 隐含转换不能有奇怪的或不可预见的输出。
  • 如果一个查询不需要隐含的类型转换,分析器和执行器不应该进行更多的额外操作。即任何一个类型匹配、格式清晰的查询不应该在分析器里耗费更多的时间,也不应该向查询中引入任何不必要的隐含类型转换调用。
  • 如果一个查询在调用某个函数时需要进行隐式转换,当用户定义了一个有正确参数的函数后,解释器应该选择使用新函数。

TD兼容模式下,空串转换为数值类型的处理

  • TD数据库不同于Oracle,Oracle将空串当做NULL进行处理,TD在将空串转换为数值类型的时候,默认将空串转换为0进行处理,因此查询空串会查询到数值为0的数据。同样地,在TD兼容模式下,字符串转换数值的过程中,也会将空串默认转换为相应数值类型的0值进行处理。除此之外,' - '、' + '、' '这些字符串也都会在TD兼容模式下默认转换为0进行处理,但是小数点字符串' . '会报错。例如:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    CREATE TABLE t1(no int,col varchar);
    INSERT INTO t1 values(1,'');
    INSERT INTO t1 values(2,null);
    SELECT * FROM t1 WHERE col is null;
     no | col
    ----+-----
      2 |
    (1 row)
    
    SELECT * FROM t1 WHERE col='';
     no | col
    ----+-----
     1  |
    (1 row)
    
  • MySQL兼容模式下对空串转换为数值类型的处理和TD兼容模式相同。