1 - 关键字

关键字指的是 SQL 语言中具有特别含义的字。每个 SQL 语句都包含一个或多个关键字。SQL 对关键字不区分大小写,但是通常情况下以大写字母形式出现,以保证其可读性。

保留字和关键字

许多关键字同时也是保留字。

Vertica 建议您不要使用保留字作为对象名称或标识符。包含保留字可能会导致 SQL 语句发生混淆。用作对象名称或标识符的保留字必须用双引号括住。

非保留关键字

非保留关键字在某些情况下具有特殊含义,但是在其他情况下可以用作标识符。可以将费保留关键字做为别名使用 — 例如,SOURCE

=> SELECT my_node AS SOURCE FROM nodes;

查看保留关键字和非保留关键字列表

要查看 Vertica 保留字和非保留字的当前列表,请查询系统表 KEYWORDS。Vertica 按字母顺序列出了所有的关键字,并标注其为保留 (R)或非保留 (N)。

例如,以下查询获取所有以 B 开头的保留关键字:

=> SELECT * FROM keywords WHERE reserved = 'R' AND keyword ilike 'B%';
 keyword | reserved
---------+----------
 BETWEEN | R
 BIGINT  | R
 BINARY  | R
 BIT     | R
 BOOLEAN | R
 BOTH    | R
(6 rows)

2 - 标识符

架构、表、投影、列名称等对象的标识符(名称),长度最多可以为 128 个字节。

无引号的标识符

无引号的 SQL 标识符必须用以下值开头:

  • 非 Unicode 字母:A–Z 或 a-z

  • 下划线 (_)

标识符中的后续字符可以是以下任意组合:

  • 非 Unicode 字母:A–Z 或 a-z

  • 下划线 (_)

  • 数位 (0–9)

  • Unicode 字母(字母具有发音或不属于拉丁字母表),模型名称不支持

  • 美元符号 ($),型号名称不支持

带引号的标识符

用双引号 (") 字符括住的标识符可以包含任何字符。如果要包括双引号,需要成对使用;例如 """"。您可以使用可能无效的名称,例如仅包含数字字符 ("123") 或仅包含空格字符、标点符号、SQL 或 Vertica 预留关键字。例如:

CREATE SEQUENCE "my sequence!";

对于字母数字和 SQL 关键字,例如 “1time”、“Next week”和“Select”,需要双引号。

区分大小写

标识符不区分大小写。因此,标识符 "ABC""ABc""aBc" 是同义词,类似于 ABCABcaBc.

非 ASCII 字符

Vertica 接受非 ASCII UTF-8 Unicode 字符作为表名称、列名称和其他标识符,并将忽略大写/小写区别的情况扩展到所有字母,其中包括拉丁语、斯拉夫语和希腊语。

例如,以下 CREATE TABLE 语句在表名中使用了 ß(德语 eszett):

=> CREATE TABLE straße(x int, y int);
   CREATE TABLE

标识符按创建时的形态保存

SQL 标识符未转换为小写,例如表和列名称。它们按照创建时的形态保存,使用区分大小写比较来解析对它们的引用。例如,以下语句创建表 ALLCAPS

=> CREATE TABLE ALLCAPS(c1 varchar(30));
=> INSERT INTO ALLCAPS values('upper case');

以下语句是同一个查询的变体:

=> SELECT * FROM ALLCAPS;
=> SELECT * FROM allcaps;
=> SELECT * FROM "allcaps";

三个查询都返回相同的结果:

     c1
------------
 upper case
(1 row)

请注意,如果尝试创建表 AllCaps,Vertica 会返回错误:

=> CREATE TABLE AllCaps(c1 varchar(30));
   ROLLBACK:  table "AllCaps" already exists

有关其他信息,请参阅 QUOTE_IDENT

3 - 字面量

字面量指的是 SQL 中做为常数使用的数字或字符串。选择列表中包括字面量以及表达式和内置函数,也可做为常数存在。

Vertica 支持数字类型的文本(整数和数字)、字符串字面量、VARBINARY 字符串字面量和日期/时间字面量。本章将讨论不同的字符串字面量格式。

3.1 - 数字类型字面量

Vertica 支持三种类型的数字:整数、数字和浮点数。

  • Integers 是小于 2^63 的完整数,且必须是数字。

  • Numerics 是大于 2^63 或包含具有精度和标度的小数点的完整数。Numerics 可含有指数。以 0x 开头的数字是十六进制数。

Numeric-类型值也可通过使用来自字符串的投影生成。这是一个更普遍的语法。请参阅下文的例子,以及 数据类型强制运算符 (CAST)

语法

digits 
digits.[digits] | [digits].digits
digits e[+-]digits | [digits].digits e[+-]digits | digits.[digits] e[+-]digits

参数

注意

  • 如果 e 存在,则至少有一个数字跟阶码标记符在 (e)之后。
  • 常数中不得嵌入任何空格或其他字符。
  • 前面的加号 (+) 或减号 (–) 标记不作为常数的一部分;它们是应用于常量的一元运算符。

  • 在大多数情况下,numeric-类型的常数根据上下文,自动强制转换为最合适的类型。如有必要,您可以根据 数据类型强制运算符 (CAST)所述,通过投影将 numeric 值强制转换为指定的数据类型。

  • 不支持浮点字面字面量如果您需要指定浮点数,可根据 数据类型强制运算符 (CAST)进行投影。

  • Vertica 遵循 IEEE 浮点规范,包括 NaN(非数字)和 Infinity (Inf)。

  • NaN 不大于同时也不小于任何值(甚至是本身)。换句话说,每当涉及到 NaN,比较始终返回 false。

  • 除法 INTEGERS (x / y) 生成 NUMERIC 结果。您可以使用 // 运算符将结果截断为完整数。

示例

下面是数字类型字面字面量的例子:

42
3.5
4.
.001
5e2
1.925e-3

科学记数法:

=> SELECT NUMERIC '1e10';
 ?column?
-------------
 10000000000
(1 row)

BINARY 缩放:

=> SELECT NUMERIC '1p10';
 ?column?
----------
     1024
(1 row)
=> SELECT FLOAT 'Infinity';
  ?column?
----------
 Infinity
(1 row)

下面的例子对使用 / 和 // 运算符除整数进行了说明:

=> SELECT 40/25;
 ?column?
----------------------
 1.600000000000000000
(1 row)
=> SELECT 40//25;
 ?column?
----------
        1
(1 row)

另请参阅

数据类型强制转换

3.2 - 字符串字面量

字符串字面量是使用单引号或双引号引用的字符串值。双引号字符串需使用反斜杠,单引号字符串则不要求使用反斜杠,但 \\'\\\ 除外。

您可以将单引号和反斜杠嵌入单引号字符串。

如需包含其他反斜杠(转义)序列,例如 \t (Tab),您必须使用双引号形式。

对于单引号字符串,在字符串和其前面的词语之间必须加入空格,因为单引号允许用于标识符。

另请参阅

3.2.1 - 字符字符串字面量

字符字符串字面量是由预定义字符集中的字符组成的序列,两边加上单引号。

语法

'character-seq'

参数

嵌入式单引号

如果字符字符串字面量包含单引号,则必须成对出现。例如:

=> SELECT 'Chester''s gorilla';
  ?column?
-------------------
Chester's gorilla
(1 row)

符合标准的字符串和转义字符

Vertica 按照 SQL 标准中指定的要求,使用符合标准的字符串,将反斜杠处理为字符串字面量,而不是处理为转义字符。

示例

=> SELECT 'This is a string';
  ?column?
------------------
 This is a string
(1 row)
=> SELECT 'This \is a string';
   WARNING:  nonstandard use of escape in a string literal at character 8
   HINT:  Use the escape string syntax for escapes, e.g., E'\r\n'.
     ?column?
------------------
 This is a string
(1 row)
vmartdb=> SELECT E'This \is a string';
     ?column?
------------------
 This is a string
=> SELECT E'This is a \n new line';
       ?column?
----------------------
 This is a
 new line
(1 row)
=> SELECT 'String''s characters';
      ?column?
--------------------
 String's characters
(1 row)

另请参阅

3.2.2 - 以美元为界的字符串字面量

以美元为界的字符串字面量很少使用,但为了方便起见,在此处提供了这种文本。

用来指定字符串字面量的标准语法可能很难理解。在这种情况下,为了提高查询的可读性,Vertica SQL 提供了美元界限。美元界限不是 SQL 标准的一部分,但它通常用来编写复杂的字符串字面量,比符合标准的单引号语法更方便。

语法

$$characters$$

参数

以美元为界的字符串内容被视为字面量。在以美元为界的字符串中,单引号、反斜杠和美元符号字符中没有特殊含义。

注意

关键字或标识符后面以美元为界的字符串必须与前面的单词用空格分隔;否则,美元界限分隔符将作为前面标识符的一部分。

示例

=> SELECT $$Fred's\n car$$;
     ?column?
-------------------
 Fred's\n car
(1 row)

=> SELECT 'SELECT 'fact';';
ERROR:  syntax error at or near "';'" at character 21
LINE 1: SELECT 'SELECT 'fact';';

=> SELECT 'SELECT $$fact';$$;
   ?column?
---------------
 SELECT $$fact
(1 row)

=> SELECT 'SELECT ''fact'';';
    ?column?
----------------
 SELECT 'fact';
(1 row)

3.2.3 - Unicode 字符串字面量

语法

U&'characters' [ UESCAPE '<Unicode escape character>' ]

参数

使用符合标准的字符串

启用 StandardConformingStrings 时,Vertica 支持 SQL 标准 Unicode 字符字符串字面量(字符集为仅 UTF-8)。

在输入 Unicode 字符字符串字面量之前,请通过以下方式之一启用符合标准的字符串。

另请参阅扩展的字符串字面量

示例

要以十六进制输入 Unicode 字符(例如 'thank you' 的俄语短语),请使用以下语法:

=> SET STANDARD_CONFORMING_STRINGS TO ON;
=> SELECT U&'\0441\043F\0430\0441\0438\0431\043E' as 'thank you';
 thank you
-----------
 спасибо
(1 row)

要以十六进制输入德语单词 mude(其中 u 是变元音):

=> SELECT U&'m\00fcde';
?column?
----------
müde
(1 row)
=> SELECT 'ü';
?column?
----------
ü
(1 row)

要以十六进制输入 LINEAR B IDEOGRAM B240 WHEELED CHARIOT

=> SELECT E'\xF0\x90\x83\x8C';
?column?
----------
(wheeled chariot character)
(1 row)

另请参阅

3.2.4 - VARBINARY 字符串字面量

您可以通过 VARBINARY 字符串字面量在字符串字面量中指定十六进制数字或二进制数字。

语法

X''
B''

参数

示例

=> SELECT X'abcd';
 ?column?
----------
 \253\315
(1 row)

=> SELECT B'101100';
 ?column?
----------
 ,
(1 row)

3.2.5 - 扩展字符串字面量

语法

E'characters'

参数

您可以采用扩展字符串字面量的 C 样式反斜杠序列,这是结构化查询语言 (SQL) 标准的扩展。您可以通过将字母 E 作为前缀(在开放的单引号前)来指定一个扩展字符串字面量;例如:

E'extended character string\n'

在扩展字符串内,反斜杠字符 (\\) 启动 C 样式反斜杠序列,在该序列中反斜杠组合和后面的字符或数字代表一个特别的字节值,如下表所示:任何后接反斜杠的字符都按字面理解;例如,要包含一个反斜杠字符,就输入两个反斜杠 (\\\)。

  • \\\ 是一个反斜杠

  • \b 是一个退格符

  • \f 是一个换页符

  • \n 是一个换行符

  • \r 是一个回车符

  • \t 是一个制表符

  • \x##,其中 ## 是 1 位或 2 位十六进制数;例如 \x07 是一个制表符

  • \\###,其中 ### 是 1、2 或 3 位八进制数,表示带有相应代码的字节。

当扩展的字符串字面量衔接起来跨过线时,只在首个开放的引号前输入 E

=> SELECT E'first part o'
    'f a long line';
         ?column?
---------------------------
 first part of a long line
(1 row)

将两个相邻的单引号作为一个单引号使用:

=> SELECT 'Aren''t string literals fun?';
          ?column?
-----------------------------
 Aren't string literals fun?
(1 row)

符合标准的字符串和转义字符

解释命令(例如,在 vsql 中输入的命令,或者在通过 JDBC 或 ODBC 传递的查询中输入的命令)时,Vertica 采用 SQL 标准中指定的符合标准的字符串。在符合标准的字符串中,反斜杠视作字符串字面量(普通字符),而非转义字符。

可以按照以下内容操作,但是 Vertica 建议您在发生警告后尽快使用符合标准的字符串移动您的应用程序。

  • 要将反斜杠视为转义字符,请将配置参数 StandardConformingStrings 设置为 0。

  • 要永久启用符合标准的字符串,请将 StandardConformingStrings 参数设置为 '1',如下面所述。

  • 要使每一会话均为符合标准的字符串,采用设置符合标准的字符串为开启,此设置只有在当前会话将反斜杠视为转义字符。

识别不符合标准的字符串

以下程序可以用于识别您的应用程序中不符合标准的字符串,从而您可以将这些字符串转换为符合标准的字符串:

  1. 确保 StandardConformingStrings 参数处于关闭状态,如国际化参数中所述。

    => ALTER DATABASE DEFAULT SET StandardConformingStrings = 0;
    
  2. 如有必要,请打开 EscapeStringWarning 参数。

    => ALTER DATABASE DEFAULT SET EscapeStringWarning = 1;
    

    目前,Vertica 每次在字符串字面量中遇到一个转义字符串时都会返回一项警告。例如,Vertica 在下面的示例中将 \n 解释为换行符:

    => SELECT 'a\nb';
       WARNING:  nonstandard use of escape in a string literal at character 8
       HINT:  Use the escape string syntax for escapes, e.g., E'\r\n'.
     ?column?
    ----------
     a
    b
    (1 row)
    

    StandardConformingStringsON 时,该字符串解释为四个字符:a \ n b

    通过扩展由 Vertica 标记的每个字符来对其进行修改,如以下示例中所示:

    E'a\nb'
    

    或者如果该字符串已经引用了单引号,那么使用两个单引号,例如, 'one'' double'.

  3. 为全部会话开启 StandardConformingStrings 参数:

    => ALTER DATABASE DEFAULT SET StandardConformingStrings = 1;
    

两个单引号

这节内容讨论不传递给服务器的 vsql 输入值。 Vertica 将一个字符串字面量中两个连续的单引号视为一个单引号符。例如以下输入,'You''re here!' 忽略了第二个连续引号并返回以下内容:

=> SELECT 'You''re here!';
   ?column?
--------------
 You're here!at
(1 row)

这就是 SQL 标准表示法,且在表格中多见,'You\\'re here!',因为反斜杠和之前的解析不同。您需要忽略掉反斜杠:

=> SELECT (E'You\'re here!');
   ?column?
--------------
 You're here!
(1 row)

此更改行为在使用 vsql meta-command \set 时引进一个潜在的不兼容性,这会自动将其命令行实参衔接起来。例如:

\set file  '\''  'pwd'  '/file.txt'  '\''\echo :file

vsql 接受这四个参数并输出以下内容:

'/home/vertica/file.txt'

Vertica 按如下方式解析相邻的单引号:

\set file  '\'''pwd''/file.txt''\''\echo :file
'/home/vertica/file.txt''

注意末尾额外的单引号。这是因为相邻的单引号与引用反斜杠的单引号进行了配对。

额外的引号可以被解析为上面的第一个案例或是将字面意义进行组合,如下:

\set file '\''`pwd`'/file.txt'''\echo :file
'/home/vertica/file.txt'

在这两种情况中,引用反斜杠的单引号应该改为两个单引号,如下:

\set file '''' `pwd` '/file.txt'''

其他示例

=> SELECT 'This \is a string';
     ?column?
------------------
 This \is a string
(1 row)

=> SELECT E'This \is a string';
     ?column?
------------------
 This is a string

=> SELECT E'This is a \n new line';
       ?column?
----------------------
 This is a
 new line
(1 row)

=> SELECT 'String''s characters';
      ?column?
--------------------
 String's characters
(1 row)

3.3 - 日期/时间字面量

输入的日期或时间字面量必须用单引号括起来。可接受几乎任何合理格式的输入,包括符合 ISO 8601 和 SQL 标准、传统的 POSTGRES 和其他格式。

Vertica 可以在 SQL 标准要求之上更灵活地处理日期/时间输入。日期/时间表达式 中说明了日期/时间输入和已识别文本字段(包括月份、星期和时区)的精确解析规则。

3.3.1 - 时区值

Vertica 尝试与时区的 SQL 标准定义兼容。但是,SQL 标准的日期和时间类型与功能组合较为怪异。存在以下明显问题:

  • 虽然 DATE 类型不含关联时区,但 TIME/TIMETZ 类型可以包含关联时区。除非与日期和时间相关联,否则时区在现实世界中几乎没有任何意义,因为偏移量在一年当中会随夏令时边界的变化而变化。

  • Vertica 假设本地时区适用于任何仅包含日期或时间的数据类型。

  • 默认时区指定为相对于 UTC 的偏移量常数。因此,在跨 DST 边界进行日期/时间算术时,不可能适应夏令时。

为了克服这些困难,Micro Focus 建议您在使用时区时使用包含日期和时间的日期/时间类型。Micro Focus 建议您不要使用类型 TIME WITH TIME ZONE,,即使它支持传统应用程序且符合 SQL 标准也不例外。

时区和时区约定不仅仅受地球几何形状的影响,还会受政治决策的影响。1900 年代,全球时区开始趋于标准化,但仍然会面临一些随机变化,特别是夏令时规则方面。

Vertica 目前支持从 1902 年到 2038 年这个时间段确立的夏令时规则,对应于完整传统 UNIX 系统时间。一旦时间超出该范围,则视为所选时区的“标准时间”,无论该时间处于一年当中的哪个时段。 

3.3.2 - 星期几的名称

系统将以下标记识别为星期几的名称:

3.3.3 - 月份名称

系统将以下标记识别月份名称:

3.3.4 - 间隔字面量

表示时间跨度的字面量。

语法

[ @ ] [-] { quantity subtype-unit }[...] [ AGO ]

参数

注意

  • 不同的单位数量会自动叠加。

  • 间隔常量的上下限分别为:

    • 9223372036854775807 usec‑9223372036854775807 usec

    • 296533 years 3 mons 21 days 04:00:54.775807‑296533 years ‑3 mons ‑21 days ‑04:00:54.775807

  • 间隔常量的范围是 +/– 263 – 1 微秒。

  • 在 Vertica 中,间隔字段可以增加,允许大浮点数。

示例

请参阅指定间隔输入

3.3.4.1 - 间隔子类型单位

下表列出了可在间隔字面量中指定的子类型单位,分为以下几个主要类别:

年-月子类型单位

天-时间子类型单位

处理 m 输入

Vertica 根据上下文将输入单位 m 解释为月份或分钟。例如,以下命令可创建包含间隔值的单列表:

=> CREATE TABLE int_test(i INTERVAL YEAR TO MONTH);

在以下 INSERT 语句中,Vertica 将间隔字面量 1y 6m 解释为 1 年 6 个月:

=> INSERT INTO int_test VALUES('1y 6m');
 OUTPUT
--------
      1
(1 row)
=> COMMIT;
COMMIT
=> SET INTERVALSTYLE TO UNITS;
SET
=> SELECT * FROM int_test;
        i
-----------------
 1 year 6 months
(1 row)

以下 ALTER TABLE 语句可将 DAY TO MINUTE 间隔列添加到表 int_test 中:

=>  ALTER TABLE int_test ADD COLUMN x INTERVAL DAY TO MINUTE;
ALTER TABLE

下一个 INSERT 语句将第一列和第二列分别设置为 3y 20m 和 1y 6m。在这种情况下,Vertica 通过以下两种方式解释 m 输入字面量:

  • 对于第 i 列,Vertica 将 m 输入解释为月份,显示 4 年 8 个月。

  • 对于第 x 列,Vertica 将 m 输入解释为分钟。由于间隔定义为 DAY TO MINUTE,因此将插入的输入值 1y 6m 转换为 365 天 6 分钟:

=> INSERT INTO int_test VALUES ('3y 20m', '1y 6m');
 OUTPUT
--------
      1
(1 row)

=> SELECT * FROM int_test;
        i         |        x
------------------+-----------------
 1 year 6 months  |
 4 years 8 months | 365 days 6 mins
(2 rows)

3.3.4.2 - 间隔限定符

指定如何解释输出的间隔字面量并为其设置格式,同时可选择性设置精度。间隔限定符由一或两个单元组成:

unit [ TO unit ] [ (p) ]

其中:

  • 单位指定天-时间或年-月子类型

  • p 指定精度,0 到 6 之间的整数。

如果间隔省略了间隔限定符,则默认值为 DAY TO SECOND(6)

间隔限定符分为以下两个类别:

天-时间间隔限定符

年-月间隔限定符

示例

请参阅控制间隔格式

4 - 运算符

运算符是指为求值、比较或计算值而在 SQL 中使用的逻辑、数学和等式符号。

4.1 - 位运算符

位运算符对 INTEGER 和 BINARY/VARBINARY 数据类型执行位操作:

对 BINARY/VARBINARY 数据类型无效

字符串实参处理

对于所有位运算符,必须将字符串实参显式转换为 BINARY 或 VARBINARY 数据类型。例如:

=> SELECT 'xyz'::VARBINARY & 'zyx'::VARBINARY AS AND;
 AND
-----
 xyx
(1 row)

=> SELECT 'xyz'::VARBINARY | 'zyx'::VARBINARY AS OR;
 OR
-----
 zyz
(1 row)

位运算符将所有字符串实参视为长度相同。如果实参长度不同,则运算符函数会使用一个或多个零字节右侧填充较小的字符串,使其长度与较大的字符串相同。

例如,以下语句 AND 长度不同的字符串 xyzzy。Vertica 使用一个零字节右侧填充字符串 zy。相应地,结果中的最后一个字符表示为 \000

=> SELECT 'xyz'::VARBINARY & 'zy'::VARBINARY AS AND;
  AND
--------
 xy\000
(1 row)

4.2 - 布尔运算符

Vertica 支持以下布尔运算符:

  • AND

  • OR

  • NOT

运算符 ANDOR 可交换,也就是说,可以在不影响结果的情况下切换左右操作数。但是,未定义子表达式的求值顺序。要强制执行求值顺序,请使用 CASE 构造。

逻辑

SQL 使用三值布尔逻辑,其中 NULL 表示“未知”。

4.3 - 比较运算符

只要比较有意义,比较运算符可适用于所有数据类型。所有比较运算符均为二元运算符,可返回 true、false 或 NULL 这些值。

NULL 处理

如果一个或两个操作数为 NULL,则比较运算符返回 NULL。存在一个例外: <=> 如果两个操作数都为 NULL,则返回 true;如果一个操作数为 NULL,则返回 false。

集合

当对集合进行比较时,NULL 集合排在最后。否则,逐个元素比较集合,直到出现不匹配,然后根据不匹配的元素对它们进行排序。如果所有元素的长度都依次等于较短的元素的长度,则首先排序较短的元素。

4.4 - 数据类型强制运算符 (CAST)

数据类型强制转换(转换)将表达式的值传递给输入转换例程以转换为指定的数据类型,得到指定类型的常数。在 Vertica 中,可以通过使用以下结构之一的显式转换请求来调用数据类型强制功能:

语法

SELECT CAST ( expression AS data‑type )
SELECT expression::data‑type
SELECT data‑type 'string'

参数

截断

如果将二进位值转换(隐式或显式)为较小长度的二进位类型,该值将被自动截断。例如:

=> SELECT 'abcd'::BINARY(2);
 ?column?
----------
 ab
(1 row)

类似地,如果将字符值转换(隐式或显式)为较小长度的字符值,该值将被自动截断。例如:

=> SELECT 'abcd'::CHAR(3);
 ?column?
----------
 abc
(1 row)

二进制转换和调整大小

Vertica 仅支持以下转换和调整大小操作:

  • 从 BINARY 转换到和转换自 VARBINARY

  • 从 VARBINARY 转换到和转换自 LONG VARBINARY

  • 从 BINARY 转换到和转换自 LONG VARBINARY

对于包含少于目标列字节的值的二进位数据,零字节 '\0' 的值向右扩展为整个列宽。可变长度的二进位值的尾随零不能向右扩展:

=> SELECT 'ab'::BINARY(4), 'ab'::VARBINARY(4), 'ab'::LONG VARBINARY(4);
  ?column?  | ?column? | ?column?
------------+----------+----------
 ab\000\000 | ab       | ab
(1 row)

自动强制

如果常数类型明确,可以忽略显式类型转换。例如,直接分配常数到一列中,该常数会自动强制转换为该列的数据类型。

示例

=> SELECT CAST((2 + 2) AS VARCHAR);
 ?column?
----------
 4
(1 row)

=> SELECT (2 + 2)::VARCHAR;
 ?column?
----------
 4
(1 row)

=> SELECT INTEGER '123';
 ?column?
----------
      123
(1 row)

=> SELECT (2 + 2)::LONG VARCHAR
 ?column?
----------
 4
(1 row)

=> SELECT '2.2' + 2;
   ERROR:  invalid input syntax for integer: "2.2"

=> SELECT FLOAT '2.2' + 2;
 ?column?
----------
      4.2
(1 row)

另请参阅

4.4.1 - 转换失败

当您通过显式转换调用数据类型转换(转换),但该转换失败时,结果将返回错误或 NULL。当您尝试进行冲突的转换时,如尝试将包含字母的 VARCHAR 表达式转换为整数,通常就会发生转换失败。

当转换失败时,返回的结果取决于数据类型。

启用严格的时间转换

您可以使所有转换失败产生错误,包括针对日期/时间数据类型的转换。这样做将使您能查看某些或所有转换失败的原因。要返回错误而不是 NULL,请将配置参数 EnableStrictTimeCasts 设置为 1:

ALTER SESSION SET EnableStrictTimeCasts=1;

默认情况下,EnableStrictTimeCasts 设置为 0。因此,以下尝试将 VARCHAR 转换为 TIME 数据类型的行为返回 NULL:


==> SELECT current_value from configuration_parameters WHERE parameter_name ilike '%EnableStrictTimeCasts%';
 current_value
---------------
 0
(1 row)

=> CREATE TABLE mytable (a VARCHAR);
CREATE TABLE
=> INSERT INTO mytable VALUES('one');
OUTPUT
--------
1
(1 row)

=> INSERT INTO mytable VALUES('1');
OUTPUT
--------
1
(1 row)

=> COMMIT;
COMMIT
=> SELECT a::time FROM mytable;
 a
---


(2 rows)

如果启用 EnableStrictTimeCasts,则转换失败返回错误:


=> ALTER SESSION SET EnableStrictTimeCasts=1;
ALTER SESSION
=> SELECT a::time FROM mytable;
ERROR 3679:  Invalid input syntax for time: "1"

使所有转换失败返回 NULL

要将某一表达式显式转换为请求的数据类型,请使用以下结构:

SELECT expression::data-type

使用此命令将任何值转换为冲突的数据类型,将返回以下错误:

=> SELECT 'one'::time;
ERROR 3679:  Invalid input syntax for time: "one"

Vertica 也支持使用强制转换运算符 ::!,当希望返回以下结果时很有用:

  • 对于非日期/时间数据类型,返回 NULL 而不是错误

  • 在设置 EnableStrictTimeCasts 后,返回 NULL 而不是错误

使所有转换失败返回 NULL 可使在转换期间成功的表达式显示在结果中。但在转换期间失败的表达式将产生 NULL 值。

以下示例使用强制转换运算符 ::! 查询 mytable。查询返回 NULL,其中列 a 包含字符串 one;返回 1,其中列包含 1。无论如何设置 EnableStrictTimeCasts,查询结果都相同:

=> SELECT current_value FROM configuration_parameters WHERE parameter_name ilike '%EnableStrictTimeCasts%';
 current_value
---------------
 0
(1 row)

=> SELECT a::!int FROM mytable;
a
---

1
(2 rows)

ALTER SESSION SET EnableStrictTimeCasts=1;
ALTER SESSION
=> SELECT a::!int FROM mytable;
 a
---

 1
(2 rows)

您可以使用 ::! 转换数组和集合。转换单独解析每个元素,为无法转换的元素生成 NULL。

4.5 - 日期/时间运算符

语法

[ + | – | * | / ]

参数

+  Addition
–  Subtraction
*  Multiplication
/  Division

注意

  • 下文描述的 TIMETIMESTAMP 输入运算符其实有两种变体:一种是 TIME WITH TIME ZONETIMESTAMP WITH TIME ZONE;另一种是 TIME WITHOUT TIME ZONETIMESTAMP WITHOUT TIME ZONE。简洁起见,这些变体不单独显示。

  • +* 运算符以交换对的形式出现(例如 DATE + INTEGER INTEGER + DATE);每个交换对仅显示其中一个运算符。

4.6 - 数学运算符

为很多数据类型提供数学运算符。

阶乘运算符支持

Vertica 支持对正负浮点 (DOUBLE PRECISION) 数和整数使用阶乘运算符。例如:

=> SELECT 4.98!;
   ?column?
------------------
 115.978600750905
(1 row)

阶乘在 gamma 函数的术语中定义,其中 (-1) = 无限,其他负整数未定义。例如:

(–4)! = NaN
–(4!) = –24

对于所有复数 z,阶乘定义如下:

z! = gamma(z+1)

有关详细信息,请参阅 Abramowitz 和 Stegun:数学函数手册

4.7 - NULL 运算符

要检查某个值是否为 NULL,请使用以下构造:

[expression IS NULL | expression IS NOT NULL]

或者,使用等效(但非标准)构造:

[expression ISNULL | expression NOTNULL]

不要写入 expression = NULL,因为 NULL 表示未知值,两个未知值不一定相等。此行为遵守 SQL 标准。

4.8 - 字符串串联运算符

要串联同一行的两个字符串,请使用串联运算符(两条连续的竖线)。

语法

string || string

参数

注意

  • || 用于串联表达式和常量.表达式应尽可能投射至 VARCHAR ,否则就投射至 VARBINARY,而且必须投射至其中一个。

  • 单个 SQL 语句中的两个连续字符串在不同行会自动串联

示例

以下示例是位于两行的单个字符串:

=> SELECT E'xx'-> '\\';
 ?column?
----------
 xx\
(1 row)

以下示例显示两个串联的字符串:

=> SELECT E'xx' ||-> '\\';
 ?column?
----------
 xx\\
(1 row)

=> SELECT 'auto' || 'mobile';
 ?column?
----------
 automobile
(1 row)

=> SELECT 'auto'-> 'mobile';
 ?column?
----------
 automobile
(1 row)

=> SELECT 1 || 2;
 ?column?
----------
 12
(1 row)

=> SELECT '1' || '2';
 ?column?
----------
 12
(1 row)
=> SELECT '1'-> '2';
 ?column?
----------
 12
(1 row)

5 - 表达式

SQL 表达式是将某个值或多个值与其他值进行比较的查询的组件。它们还可以执行计算。在任何 SQL 命令中发现的表达式通常采用条件语句的形式。

运算符优先级

下表按递减(由高到低)顺序显示运算符优先级。

表达式求值规则

未定义子表达式的求值顺序。特别是,不必由左到右或以任何其他固定顺序对运算符或函数输入进行求值。要强制按特定顺序进行求值,请使用 CASE 构造。例如,这是一种在 WHERE 子句中尝试避免除数为零的不受信任方式:

=> SELECT x, y WHERE x <> 0 AND y/x > 1.5;

但这种方式比较安全:

=> SELECT x, y
   WHERE
     CASE
       WHEN x <> 0 THEN y/x > 1.5
       ELSE false
     END;

此方式中使用的 CASE 构造会导致优化尝试失败,因此仅在必要时使用。(在这个特定示例中,最好改为写入 y > 1.5*x 以避免相关问题。)

SQL 表达式的限制

对于您可在表达式中使用的修饰符和递归的数量,存在一些限制。您应该注意以下两项限制:

  • 第一项限制基于可供表达式使用的堆栈。Vertica 需要至少 100kb 的可用堆栈。如果超出此限制,则可能引发错误“查询包含的表达式过于复杂而无法分析 (The query contains an expression that is too complex to analyze)”。额外增加物理内存和/或增大 ulimit -s max 值可增加可用堆栈并防止错误。

  • 第二项限制为分析表达式中可能的递归数。上限为 2000。如果超出此限制,则可能引发错误“查询包含的表达式过于复杂而无法分析 (The query contains an expression that is too complex to analyze)”。此限制无法提高。

5.1 - 聚合表达式

聚合表达式在查询选定的各个行或行组中应用聚合函数。

聚合表达式只能出现在选择列表中或 HAVING 语句的 SELECT 子句中。它在其他子句(如 WHERE)中无效,因为这些子句是在聚合结果形成之前进行评估的。

语法

聚合表达式的格式如下:

aggregate‑function ( [ * ] [ ALL | DISTINCT ] expression )

参数

示例

AVG 聚合函数返回 customer_dimension 表中的平均收入:

=> SELECT AVG(annual_income) FROM customer_dimension;
 AVG
--------------
 2104270.6485
(1 row)

以下示例显示了如何使用具有 DISTINCT 关键字的 COUNT 聚合函数返回对所有 inventory_fact 记录计算表达式 x+y 得到的所有不同值。

=> SELECT COUNT (DISTINCT date_key + product_key) FROM inventory_fact;
COUNT
-------
21560
(1 row)

5.2 - CASE 表达式

CASE 表达式是一个通用条件表达式,可在表达式有效的情况下使用。它与其他语言的 CASEIF/THEN/ELSE 语句相似。

语法(第一种形式)

CASE
  WHEN condition THEN result
  [ WHEN condition THEN result ]
  ...
  [ ELSE result ]
END

参数

语法(第二种形式)

CASE expression
 WHEN value THEN result
 [ WHEN value THEN result ]
 ...
 [ ELSE result ]
END

参数

注意

所有 result 表达式的数据类型必须可转换为一个输出类型。

示例

以下示例显示了 CASE 语句的两种使用方法。

=> SELECT * FROM test;
 a
---
 1
 2
 3
=> SELECT a,
     CASE WHEN a=1 THEN 'one'
          WHEN a=2 THEN 'two'
          ELSE 'other'
     END
   FROM test;
 a | case
---+-------
 1 | one
 2 | two
 3 | other
=> SELECT a,
     CASE a WHEN 1 THEN 'one'
            WHEN 2 THEN 'two'
            ELSE 'other'
     END
   FROM test;
 a | case
---+-------
 1 | one
 2 | two
 3 | other

特殊示例

CASE 表达式不会对无需确定结果的子表达式求值。您可以使用此行为来避免被零除错误:

=> SELECT x FROM T1 WHERE
      CASE WHEN x <> 0 THEN y/x > 1.5
      ELSE false
    END;

5.3 - 列引用

语法

[[[database.]schema.]table-name.]column-name

参数

限制

列引用不能包含任何空格。

5.4 - 注释

注释为任意字符序列,以两个连续的连字符开头并延伸到行的结尾。例如:

   -- This is a standard SQL comment

先从输入流中移除注释再执行进一步的语法分析,并有效替换为空格。

或者,也可以使用 C 样式块注释,其中注释以 /* 开头并延伸到匹配出现的 */

   /* multiline comment
    * with nesting: /* nested block comment */
    */

这些块注释根据 SQL 标准中指定的方法嵌套。与 C 不同,您可以注释掉可能包含现有块注释的较大代码块。

5.5 - 日期/时间表达式

Vertica 将内部启发式解析器用于全部日期/时间输入支持。日期和时间以字符串输入,通过初步确定字段中可能存在的信息种类,拆分为不同字段。每个字段均被解释并分配数值,或者被忽略或拒绝。解析器包含所有文本字段的内部查询表,包括月份、星期和时区。

Vertica 解析日期/时间类型输入内容如下:

  1. 将输入字符串拆分为标记,并将每个标记分类为字符串、时间、时区或数字。

  2. 数字标记包含:

    • 冒号 (:)- 解析为时间字符串,包括所有后续数字和冒号。

    • 破折号 (-)、斜杠 (/) 或者两个或更多的点 (.)- 解析为日期字符串,可能包含文本月份。

    • 仅数字 - 解析为单一字段或 ISO 8601 串联日期(19990113 表示 1999 年 1 月 13 日)或时间(141516 表示 14:15:16)。

  3. 以加号 (+) 或减号 (–) 作为开头的标记:解析为时区或特殊字段。

  4. 标记是文本字符串:与可能的字符串相匹配。

    • 使用二分搜索表查找标记,特殊字符串(例如今日)、星期(例如星期四)、月份(例如一月)或干扰词(例如 at、on)。

    • 设置字段的字段值和位掩码。例如,设置今日对应的年、月、日,还有当前的小时、分钟、秒钟。

    • 如果未找到,进行类似的二分搜索表查询,将标记与时区进行匹配。

    • 如果仍未找到,则会收到错误消息。

  5. 标记可以是一个数字或数字字段:

    • 如果是 8 位或 6 位数,且之前没有读取其他日期字段,则解释为“串联日期”(19990118 或 990118)。此解释为 YYYYMMDD YYMMDD

    • 如果标记是三位数,并且已经读取了年份,则解释为一年中的第几日。

    • 如果标记是四位或六位数,并且已经读取了年份,则解释为时间(HHMMHHMMSS)。

    • 如果是三位或更多位数,且未找到日期字段,则解释为年份(这样会强制剩余的日期字段按“年-月-日”的格式排序)。

    • 否则,假定日期字段排序遵循 DateStyle 设置:月-日-年、日-月-年或年-月-日。如果发现月份或日期字段超出范围,则会收到错误消息。

  6. 如果已指定 BC:忽略年份并添加一个用于内部存储。(在 Vertica 实施中,1 BC = 元年。)

  7. 如果未指定 BC,且年份字段是两位长度:将年份调整为四位数。如果字段小于 70,则添加 2000,否则添加 1900。

年月日排序

对于某些格式,年、月、日的日期输入排序不明确,可支持指定这些字段的预期排序。

特殊日期/时间值

为了方便起见,Vertica 支持数个特殊日期/时间值,如下所示。当用作 SQL 语句中的常数时,所有这些值在书写时都需要加单引号。

INFINITY-INFINITY 在系统中以特殊形式表示,并以相同方式显示。其他值为读取时转换为普通日期/时间值的简写符号。(尤其是,NOW 和相关字符串在读取后立即转换为特定时值。)

以下兼容 SQL 的函数也可用于获取相应数据类型的当前时间值。

后四个接受可选的精度要求。(请参阅日期/时间函数。)然而,这些函数是 SQL 函数,不能识别为数据输入字符串。

5.6 - NULL 值

NULL 是一个保留关键字,用于表示未知的数据值。它是 NULL 字符 (\0) 的 ASCII 缩写。

表达式中的使用情况

Vertica 不会将空字符串视为 NULL 值。表达式必须指定 NULL 才能表示列值未知。

以下注意事项适用于在表达式中使用 NULL:

  • NULL 不大于、小于、等于或不等于任何其他表达式。使用 布尔谓词 确定一个表达式的值是否为 NULL。

  • 您可以通过含有 NULL=NULL 联接的 <=> 运算符的表达式编写查询。请参阅等联接和非等联接

  • Vertica 接受常量字符串中的 NULL 字符 ('\0'),且并未从输入或输出的 VARCHAR 字段移除 NULL 字符。

NULL 数据的投影排序

Vertica 对投影列中的 NULL 值进行排序,如下所示:

另请参阅

NULL 处理函数

6 - 谓词

谓词为事实测试。如果谓词测试为 true,则返回一个值。按行对每个谓词进行求值,因此当谓词是完整表 SELECT 语句的一部分时,该语句可以返回多个结果。

谓词由一组参数和实参组成。例如,在以下示例 WHERE 子句中:

WHERE name = 'Smith';
  • name = 'Smith' 为谓词

  • 'Smith' 为表达式

6.1 - BETWEEN 谓词

为方便使用,提供特殊的 BETWEEN 谓词。

语法

WHERE a BETWEEN x AND y

示例

WHERE a BETWEEN x AND y 

等效于:

WHERE a >= x AND a <= y

同样:

WHERE a NOT BETWEEN x AND y

等效于:

WHERE a < x OR a > y

可以为日期范围使用 BETWEEN 谓词:

=> CREATE TABLE t1 (c1 INT, c2 INT, c3 DATE);
=> COPY t1 FROM stdin DELIMITER '|';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 1 | 2 | 2014-07-26
>> 2 | 3 | 2014-07-27
>> 3 | 4 | 2014-07-28
>> 4 | 5 | 2014-07-29
>> 5 | 6 | 2014-07-30
>> 6 | 7 | 2014-07-31
>> 7 | 8 | 2014-08-01
>> 8 | 9 | 2014-08-02
>> \.

=> SELECT* FROM t1 WHERE c3 BETWEEN DATE('2014-07-26') AND DATE('2014-07-30');
 c1 | c2 |     c3
----+----+------------
  1 |  2 | 2014-07-26
  2 |  3 | 2014-07-27
  3 |  4 | 2014-07-28
  4 |  5 | 2014-07-29
  5 |  6 | 2014-07-30
(5 rows)

也可以使用 NOW 和 INTERVAL 关键字从日期范围中选择:

=> SELECT * FROM t1 WHERE c3 BETWEEN NOW()-INTERVAL '1 week' AND NOW();
 c1 | c2 |     c3
----+----+------------
  7 |  8 | 2014-08-01
  1 |  2 | 2014-07-26
  2 |  3 | 2014-07-27
  3 |  4 | 2014-07-28
  4 |  5 | 2014-07-29
  5 |  6 | 2014-07-30
  6 |  7 | 2014-07-31
(7 rows)

6.2 - 布尔谓词

检索表达式的值为 true、false 或 unknown (null) 的行。

语法

expression IS [NOT] TRUE
expression IS [NOT] FALSE
expression IS [NOT] UNKNOWN

注意

  • 一个 null 输入被视为值 UNKNOWN

  • IS UNKNOWNIS NOT UNKNOWN 实际上与 NULL 谓词 相同,不过输入表达式不必是单个列值。要检查 NULL 的单个列值,使用 NULL 谓词。

  • 不要将布尔谓词与 布尔运算符布尔数据类型相混淆,后者只有两个值:true 和 false。

6.3 - 列值谓词

语法

column-name comparison-op constant-expression

参数

注意

要检查某一列值是否是 NULL,请使用 NULL 谓词

示例

table.column1 = 2
table.column2 = 'Seafood'
table.column3 IS NULL

6.4 - IN 谓词

语法

(column‑list) [ NOT ] IN ( values‑list )

参数

示例

以下 SELECT 语句可查询表 t11 中的所有数据。

=> SELECT * FROM t11 ORDER BY pk;
 pk | col1 | col2 | SKIP_ME_FLAG
----+------+------+--------------
  1 |    2 |    3 | t
  2 |    3 |    4 | t
  3 |    4 |    5 | f
  4 |    5 |    6 | f
  5 |    6 |    7 | t
  6 |      |    8 | f
  7 |    8 |      | t
(7 rows)

以下查询可指定 IN 谓词,以查找 t11 中的所有行,其中 col1col2 列包含 (2,3)(6,7) 的值:


=> SELECT * FROM t11 WHERE (col1, col2) IN ((2,3), (6,7)) ORDER BY pk;
 pk | col1 | col2 | SKIP_ME_FLAG
----+------+------+--------------
  1 |    2 |    3 | t
  5 |    6 |    7 | t
(2 rows)

6.5 - INTERPOLATE

使用某些有序属性将两个 事件序列联接在一起,通过联接事件序列,您可以直接比较两个序列的值,而不是将这些序列都标准化为相同的度量间隔。

语法

expression1 INTERPOLATE PREVIOUS VALUE expression2

参数

描述

  • 事件序列联接是常规外联接的扩展。事件序列联接不会在找不到匹配时用 NULL 值填充非保留侧,而是用表中的前一个值填充非保留侧。

  • 常规外联接与事件序列联接表达式的不同之处在于 ON 子句中使用的 INTERPOLATE 谓词。请参阅“注释和限制”下方的示例 部分。另请参阅 事件序列联接

  • 根据其他 ON 子句等同谓词将表中数据按照逻辑分区。

  • 插值来源于包含 null 值的表,而不是其他表。

  • Vertica 无法保证输出中不存在 null 值。如果不匹配行之前没有值,则用 null 填充该行。

  • 事件序列联接需要两个表的列均按照等同谓词以任何顺序进行排序,然后接 INTERPOLATED 列。如果数据已经按照这个顺序排序,则可以避免显式排序,从而提升查询性能。例如,给定下表:

    ask: exchange, stock, ts, pricebid: exchange,
    stock, ts, price
    

    在接下来的查询中

    • askexchange, stock 排序(或相反), ts

    • bidexchange, stock 排序(或相反), ts

    SELECT ask.price - bid.price, ask.ts, ask.stock, ask.exchange
    FROM ask FULL OUTER JOIN bid
       ON ask.stock = bid.stock AND ask.exchange =
       bid.exchange AND ask.ts INTERPOLATE PREVIOUS
       VALUE bid.ts;
    

限制

  • 每个联接仅可使用 INTERPOLATE 表达式一次。

  • INTERPOLATE 表达式仅使用 ANSI SQL-99 语法 (ON 子句),其支持全外联接。

  • INTERPOLATE 仅可使用等同谓词。

  • 支持 AND 运算符,但不支持 OR 和 NOT 运算符。

  • 不支持表达式以及隐式转换和显式转换,但可以使用子查询。

示例

接下来的示例中使用了此简单架构。

CREATE TABLE t(x TIME);
CREATE TABLE t1(y TIME);
INSERT INTO t VALUES('12:40:23');
INSERT INTO t VALUES('14:40:25');
INSERT INTO t VALUES('14:45:00');
INSERT INTO t VALUES('14:49:55');
INSERT INTO t1 VALUES('12:40:23');
INSERT INTO t1 VALUES('14:00:00');
COMMIT;

常规全外联接

=> SELECT * FROM t FULL OUTER JOIN t1 ON t.x = t1.y;

请注意来自非保留表的 null 行。

    x     |    y
----------+----------
 12:40:23 | 12:40:23
 14:40:25 |
 14:45:00 |
 14:49:55 |
          | 14:00:00
(5 rows)

带插值的全外联接

=> SELECT * FROM t FULL OUTER JOIN t1 ON t.x INTERPOLATE
PREVIOUS VALUE t1.y;

在本例中,没有入口点的行用前一行的值进行填充。

    x     |    y
----------+----------
 12:40:23 | 12:40:23
 12:40:23 | 14:00:00
 14:40:25 | 14:00:00
 14:45:00 | 14:00:00
 14:49:55 | 14:00:00
(5 rows)

常规左外联接

=> SELECT * FROM t LEFT OUTER JOIN t1 ON t.x = t1.y;

同样,非保留表中有 null

    x     |    y
----------+----------
 12:40:23 | 12:40:23
 14:40:25 |
 14:45:00 |
 14:49:55 |
(4 rows)

带插值的左外联接

=> SELECT * FROM t LEFT OUTER JOIN t1 ON t.x INTERPOLATE
   PREVIOUS VALUE t1.y;

用插值填充 null。

    x     |    y
----------+----------
 12:40:23 | 12:40:23
 14:40:25 | 14:00:00
 14:45:00 | 14:00:00
 14:49:55 | 14:00:00
(4 rows)

内联接

对于内联接,常规内联接与事件序列内联接没有差别。因为结果集中没有 null 值,所以无需插值操作。

常规内联接仅返回唯一匹配行 12:40:23:

=> SELECT * FROM t INNER JOIN t1 ON t.x = t1.y;
    x     |    y
----------+----------
 12:40:23 | 12:40:23
(1 row)

事件序列内联接也找到了相同的唯一匹配行 12:40:23:

=> SELECT * FROM t INNER JOIN t1 ON t.x INTERPOLATE
PREVIOUS VALUE t1.y;
    x     |    y
----------+----------
 12:40:23 | 12:40:23
(1 row)

语义

如果要编写事件序列联接以取代常规联连,则按下列方式来评估值(使用上述示例中的架构):

  • t 是外部保留表

  • t1 是内部非保留表

  • 对于外部表 t 中的每一行,针对内部表 t1 中每一行的每个组合来评估 ON 子句谓词。

  • 如果针对任意的行组合的 ON 子句谓词评估为真,则在输出中生成组合行。

  • 如果针对所有组合的 ON 子句为假,则生成一个单独的输出行,其中包含t 中行的值,以及 t1 中的列,其选自 t1 中具有最大 t1.y 值的行,以使得 t1.y < t.x;如果没有找到这样的行,则用 null 填充。

在全外联接的情况下,两个表中的所有值都被保留。

另请参阅

6.6 - 联接谓词

指定联接两个或两个以上表中的记录的列。您可以使用逻辑运算符 ANDORNOT 连接多个联接谓词。

语法

ON column-ref = column-ref [ {AND | OR | NOT } column-ref = column-ref ]...

参数

6.7 - LIKE 谓词

当某列的字符串值与指定模式匹配时,检索该行。该模式可能包括一个或多个通配符 (*)。

语法

string‑expression [ NOT ] { LIKE | ILIKE | LIKEB | ILIKEB } 'pattern' [ESCAPE 'escape‑character' ]

参数

替换符号

可将以下符号替换为 LIKE 及其变体:

模式匹配

LIKE 要求整个字符串表达式与 patten 匹配。要与字符串中的任意一序列字符匹配, patten 开头和结尾必须使用百分比符号。

LIKE 不会忽略尾部空格字符。如果要匹配的数据值以不确定量的空格结尾,请将通配符 % 附加到 pattern

LIKE 变体比较

LIKE 谓词符合 SQL 标准。Vertica 还支持多种非标准变体,特别是 ILIKE,该变体等同于 LIKE,但可执行不区分大小写的搜索。以下差异与 LIKE 及其变体有关:

  • LIKE 对 UTF-8 字符字符串执行操作。精确行为取决于排序规则参数,如强度。特殊情况下,ILIKE 在当前会话语言环境下设置 S=2 (不计大小写)。

  • LIKEILIKE 对字符字符串 稳定,但对二进制字符串 不可变,而 LIKEBILIKEB 在两种情况下都不可变。

  • LIKEBILIKEB 谓词挨个字节进行 ASCII 比较。

区域设置依赖关系

默认语言环境设置下,LIKEILIKE 挨个 UTF-8 字符进行比较,比较不区分语言环境设置。 ILIKE 将独立语言转换为小写。

在非默认区域设置下,LIKEILIKE 将字符串做对比,区分语言环境设置,包括为 VARCHAR 类型使用与 "=" 相同的算法进行自动标准化。

ESCAPE 对于非默认语言环境设置,表达式的求值结果恰好为一个八位字节或一个 UTF-8 字符。

示例

以下示例显示了区域的模式匹配。

\locale default=> CREATE TABLE src(c1 VARCHAR(100));
=> INSERT INTO src VALUES (U&'\00DF'); --The sharp s (ß)
=> INSERT INTO src VALUES ('ss');
=> COMMIT;

默认区域下查询 src 表返回 ss 和 sharp s。

=> SELECT * FROM src;
 c1
----
 ß
 ss
(2 rows)

下列查询结合了参数匹配谓词来返回 c1 列的结果:

=> SELECT c1, c1 = 'ss' AS equality, c1 LIKE 'ss'
   AS LIKE, c1 ILIKE 'ss' AS ILIKE FROM src;
 c1 | equality | LIKE | ILIKE
----+----------+------+-------
 ß  | f        | f    | f
 ss | t        | t    | t
(2 rows)

下一个查询指定 c1 的 unicode 格式。

=> SELECT c1, c1 = U&'\00DF' AS equality,
   c1 LIKE U&'\00DF' AS LIKE,
   c1 ILIKE U&'\00DF' AS ILIKE from src;
 c1 | equality | LIKE | ILIKE
----+----------+------+-------
 ß  | t        | t    | t
 ss | f        | f    | f
(2 rows)

将区域改为德文,强度为 1(忽略大小写和口音):

\locale LDE_S1
=> SELECT c1, c1 = 'ss' AS equality,
c1 LIKE 'ss' as LIKE, c1 ILIKE 'ss' AS ILIKE from src;
 c1 | equality | LIKE | ILIKE
----+----------+------+-------
 ß  | t        | t    | t
 ss | t        | t    | t
(2 rows)

该例说明使用模式匹配谓词二进制数据类型:

=> CREATE TABLE t (c BINARY(1));
=> INSERT INTO t values(HEX_TO_BINARY('0x00'));
=> INSERT INTO t values(HEX_TO_BINARY('0xFF'));
=> SELECT TO_HEX(c) from t;
 TO_HEX
--------
 00
 ff
(2 rows)
select * from t;
  c
------
 \000
 \377
(2 rows)
=> SELECT c, c = '\000', c LIKE '\000', c ILIKE '\000' from t;
  c   | ?column? | ?column? | ?column?
------+----------+----------+----------
 \000 | t        | t        | t
 \377 | f        | f        | f
(2 rows)
=> SELECT c, c = '\377', c LIKE '\377', c ILIKE '\377' from t;
  c   | ?column? | ?column? | ?column?
------+----------+----------+----------
 \000 | f        | f        | f
 \377 | t        | t        | t
(2 rows)

6.8 - NULL 谓词

null 值测试。

语法

value_expression IS [ NOT ] NULL

参数

示例

列名称:

=> SELECT date_key FROM date_dimension WHERE date_key IS NOT NULL;
 date_key
----------
        1
      366
     1462
     1097
        2
        3
        6
        7
        8
...

函数:

=> SELECT MAX(household_id) IS NULL FROM customer_dimension;
 ?column?
----------
 f
(1 row)

字面量:

=> SELECT 'a' IS NOT NULL;
 ?column?
----------
 t
(1 row)

7 - 提示

提示是您嵌入到查询或 定向查询中的指令。这些指令符合以下语法:

/*+hint-name[, hint-name]...*/

用注释字符 /*+*/ 括住提示,这种方式可以括住多个用逗号分隔的提示。例如:

SELECT /*+syntactic_join,verbatim*/

限制

在查询中嵌入提示时,请注意以下限制:

  • 不要在注释字符 /**/ 中嵌入空格。

  • 通常,允许在加号 (+) 字符和 hint‑name 前后使用空格;但是,某些第三方工具不支持在 /*+ 中嵌入空格。

支持的提示

Vertica 支持以下提示:

一般提示

Eon 模式提示

联接提示

投影提示

定向查询提示

以下提示仅通过定向查询提供支持:

7.1 - :c

在定向查询中,标记必须包含在输入查询中的查询常量;否则,将取消该输入查询使用定向查询的资格。

语法

/*+:c*/

使用

默认情况下,优化器生成的定向查询集忽略谓词常量的常量 (:v) 提示。您可以通过在不得忽略的输入查询常量上设置 :c 提示来覆盖此行为。例如,以下语句创建了一个定向查询,该查询只能用于联接谓词常量与原始输入查询相同的输入查询 — 8

=> CREATE DIRECTED QUERY OPTIMIZER simpleJoin_KeepPredicateConstant SELECT * FROM S JOIN T ON S.a = T.b WHERE S.a = 8 /*+:c*/;
CREATE DIRECTED QUERY
=> ACTIVATE DIRECTED QUERY simpleJoin_KeepPredicateConstant;

另请参阅

保留定向查询中的谓词常量

7.2 - :v

在定向查询中,标记优化器在考虑是否对给定查询使用定向查询时忽略的输入查询常量。使用此提示创建可对输入查询的多个变体使用的定向查询。

Vertica 还支持将 IGNORECONST 作为 :v 的别名。优化器生成的定向查询会自动在输入和带注释的查询中标记谓词常量并附带 :v 提示。

有关详细信息,请参阅忽略定向查询中的常量

语法

/*+:v(arg)*/
/*+IGNORECONST(arg)*/
arg
为将每个输入查询 :v 提示与一个或多个带注释的查询 :v 提示配对而在定向查询中使用的整数实参。

示例

请参阅忽略定向查询中的常量

7.3 - ALLNODES

限定 EXPLAIN 语句请求假设所有节点均处于活动状态的查询计划。如果忽略此提示,EXPLAIN 语句将生成一个查询计划,将当前处于关闭状态的任何节点考虑在内。

语法

EXPLAIN /*+ALLNODES*/

示例

在以下示例中,ALLNODES 提示将请求假设所有节点均处于活动状态的查询计划。

QUERY PLAN DESCRIPTION:
 ------------------------------

 Opt Vertica Options
 --------------------
 PLAN_ALL_NODES_ACTIVE


 EXPLAIN /*+ALLNODES*/ select * from Emp_Dimension;

 Access Path:
 +-STORAGE ACCESS for Emp_Dimension [Cost: 125, Rows: 10K (NO STATISTICS)] (PATH ID: 1)
 |  Projection: public.Emp_Dimension_b0
 |  Materialize: Emp_Dimension.Employee_key, Emp_Dimension.Employee_gender, Emp_Dimension.Courtesy_title, Emp_Dimension.Employee_first_name, Emp_Dimension.Employee_middle_initial, Emp_Dimension.Employee_last_name, Emp_Dimension.Employee_age, Emp_Dimension.Employee_birthdate, Emp_Dimension.Employee_street, Emp_Dimension.Employee_city, Emp_Dimension.Employee_state, Emp_Dimension.Employee_region, Emp_Dimension.Employee_position
 |  Execute on: All Nodes

7.4 - DEPOT_FETCH

仅限 Eon 模式

当存储库缺少此查询的数据时,指定查询是否从公共存储将数据提取到存储库中。此提示会覆盖配置参数 DepotOperationsForQuery

语法

SELECT /*+DEPOT_FETCH (option)*/

参数

可选
指定当存储库不包含查询的文件数据时的行为,为以下之一:
  • ALL (默认值):从公共存储中提取文件数据,如有必要,通过将现有文件从存储库中逐出来替换它们。

  • FETCHES:仅当空间可用时才从公共存储中提取文件数据;否则,直接从公共存储中读取查询的数据。

  • NONE:请勿将文件数据提取到存储库,而应直接从公共存储中读取查询的数据。

示例

SELECT /*+DEPOT_FETCH(All)*/ count(*) FROM bar;
SELECT /*+DEPOT_FETCH(FETCHES)*/ count(*) FROM bar;
SELECT /*+DEPOT_FETCH(NONE)*/ count(*) FROM bar;

7.5 - DISTRIB

指定优化器如何分发联接键以实施联接。

语法

JOIN /*+DISTRIB(outer-join, inner-join)*/

参数

外联接
内联接
指定如何分发外联接和内连接上的数据:
  • L (当地):在各节点上对内联接键和外联接键进行相同分段,本地联接。

  • R (重新分段):内部和外部联接键没有进行相同分段。实施联接前对联接键数据进行重新分段。

  • B (广播):内部和外部联接键没有进行相同分段。实施联接前将此联接键的数据广播至其他节点。

  • F (筛选):联接表未分段。实施联接前根据需要按其他联接键筛选数据。

  • A (任意):让优化器自行选择最有效的分发方法。

描述

DISTRIB 提示指定优化器如何按顺序分发联接键以实施联接。如果指定的分发方法不可行,优化器会忽略提示并发出警告。

需要满足以下要求:

  • 包含 DISTRIB 提示的查询必须也包含 SYNTACTIC_JOIN 提示。否则,优化器会忽略 DISTRIB 提示并抛出一条警告。

  • 联接语法必须符合 ANSI SQL-92 联接约定。

示例

在以下查询中,联接受 DISTRIB 的提示 /*+DISTRIB(L,R)*/ 限定。此提示指示优化器先对联接键 stores.store_key 的数据进行重新分段,然后再将其联接至 sales.store_key 数据:

SELECT /*+SYNTACTIC_JOIN*/ sales.store_key, stores.store_name, sales.product_description, sales.sales_quantity, sales.sale_date
FROM (store.storeSales AS sales JOIN /*+DISTRIB(L,R),JTYPE(H)*/ store.store_dimension AS stores ON (sales.store_key = stores.store_key))
WHERE (sales.sale_date = '2014-12-01'::date) ORDER BY sales.store_key, sales.sale_date;

7.6 - EARLY_MATERIALIZATION

为当前查询指定表的早期实体化。一个查询可以针对任意数量的表包含这项提示。通常,查询优化器会将实体化延迟到查询执行流程后期。此提示会覆盖优化器通过其他方式做出的任何选择。

如果后续实体化联接输入会妨碍其他优化 — 例如,将聚合下推到联接,或使用实时聚合投影,此提示可能会非常有用。在这些情况下,使用 EARLY_MATERIALIZATION 限定联接输入可以启用优化。

语法

table-name [ [AS] alias ] /*+EARLY_MATERIALIZATION*/

7.7 - ECSMODE

仅限 Eon 模式

设置优化器在订户节点之间划分分片数据处理职责时使用的 ECS 策略。仅当子群集使用弹性处理调整 (ECS) 时才会应用此提示。

语法

SELECT /*+ECSMODE(option)*/

参数

可选
指定在其订阅节点之间划分分片数据时使用的策略,为以下之一:
  • AUTO:优化器选择要使用的策略,仅当在会话级别设置 ECS 模式时才有用(请参阅为会话或数据库设置 ECS 策略)。

  • IO_OPTIMIZED:使用 I/O 优化策略。

  • COMPUTE_OPTIMIZED:使用计算优化策略。

  • NONE:对此查询禁用 ECS。只有参与节点才会涉及查询执行;协作节点不会涉及。

示例

以下示例显示了简单的单表查询(被强制使用计算优化策略)的查询计划:

=> EXPLAIN SELECT /*+ECSMode(COMPUTE_OPTIMIZED)*/ employee_last_name,
             employee_first_name,employee_age
             FROM employee_dimension
             ORDER BY employee_age DESC;

                                   QUERY PLAN
--------------------------------------------------------------------------------
 ------------------------------
 QUERY PLAN DESCRIPTION:
 The execution of this query involves non-participating nodes.
 Crunch scaling strategy preserves data segmentation
 ------------------------------
. . .

7.8 - ENABLE_WITH_CLAUSE_MATERIALIZATION

启用当前 WITH 子句中所有查询的实体化。否则,实体化由配置参数 WithClauseMaterialization 设置,默认设置为 0(禁用)。如果禁用 WithClauseMaterialization,则 WITH 子句的主查询返回时会自动清除实体化。有关详细信息,请参阅WITH 子句的实体化

语法

WITH /*+ENABLE_WITH_CLAUSE_MATERIALIZATION*/

7.9 - GBYTYPE

指定 Vertica 查询优化器应使用哪一种算法(GROUPBY HASH 或 GROUPBY PIPELINED)实施 GROUP BY 子句。如果两种算法对此查询都有效,则查询优化器会优先选择指定的算法,而不是查询优化器可能通过其他方式在其查询计划中选择的算法。

语法

GROUP BY /*+GBYTYPE( HASH | PIPE )*/

参数

HASH | PIPE
指定要使用的 GROUP BY 算法:
  • HASH:GROUPBY HASH 算法

  • PIPE:GROUPBY PIPELINED 算法

有关两种算法的详细信息,请参阅 GROUP BY 实施选项

示例

请参阅控制 GROUPBY 算法选项

7.10 - JFMT

指定联接这些列中的表时如何调整 VARCHAR 列数据的大小并相应缓冲数据。JFMT 提示覆盖由配置参数 JoinDefaultTupleFormat 设置的默认行为,可在数据库和会话级别进行设置。

有关详细信息,请参阅联接可变长度字符串数据

语法

JOIN /*+JFMT(format-type)*/

参数

format‑type
指定联接这些列中的表时如何设置 VARCHAR 列数据的格式并相应缓冲数据。设置为以下值之一:
  • f (固定):使用联接列元数据将列数据的大小调整为固定长度,并相应地进行缓冲。

  • v (变量):使用联接列数据的实际长度,因此每个联接的缓冲区大小不同。

例如:

SELECT /*+SYNTACTIC_JOIN*/ s.store_region, SUM(e.vacation_days) TotalVacationDays
   FROM public.employee_dimension e
   JOIN /*+JFMT(f)*/ store.store_dimension s ON s.store_region=e.employee_region
   GROUP BY s.store_region ORDER BY TotalVacationDays;

要求

  • 包含 JFMT 提示的查询必须也包含 SYNTACTIC_JOIN 提示。否则,优化器会忽略 JFMT 提示并抛出一条警告。

  • 联接语法必须符合 ANSI SQL-92 联接约定。

7.11 - JTYPE

指定联接算法是哈希联接还是合并联接。

使用 JTYPE 提示以指定优化器用来联接表数据的算法。如果指定算法不可行,优化器将忽略提示并发出警告。

语法

JOIN /*+JTYPE(join-type)*/

参数

联接类型
以下几项之一:
  • H:哈希联接

  • M:合并联接仅在联接列的输入均排序的情况下有效,否则 Vertica 会忽略并发出警告。优化器依靠查询或 DDL 来验证输入数据是否已排序,而不是依靠数据的实际运行时顺序。

  • FM:强制合并联接合并前,优化器会重新针对联接输入进行排序。联接列必须是相同的类型、精度或小数位数,但字符串列可以是不同的长度。

FM 的值仅对简单的联接状态有效。例如:

=> SELECT /*+SYNTACTIC_JOIN*/ * FROM x JOIN /*+JTYPE(FM)*/ y ON x.c1 = y.c1;

要求

  • 包含 JTYPE 提示的查询必须也包含 SYNTACTIC_JOIN 提示。否则,优化器会忽略 JTYPE 提示并抛出一条警告。

  • 联接语法必须符合 ANSI SQL-92 联接约定。

7.12 - LABEL

为语句分配标签,以便轻松识别标签,评估性能和调试问题。

LABEL 提示在以下语句中有效:

语法

statement-name /*+LABEL (label‑string)*/

参数

标签字串
最长为 128 个八位字节的字符串。如果用单引号括起,label-string 可以包含嵌入空格。

示例

请参阅标记语句

7.13 - PROJS

指定要用于查询的表的一个或多个投影。

语法

FROM table-name /*+PROJS( [[database.]schema.]projection[,...] )*/

参数

[database.]schema

数据库和架构。默认架构为 public。如果指定一个数据库,它必须是当前数据库。

projection
要使用的投影。可以指定逗号分隔投影的列表。

描述

PROJS 提示可指定多个投射;优化器指定了哪些有效并使用已查询表中最低成本的一个。如果没有有效的已提示投影,则查询将返回警告并忽略投影提示。

示例

employee_dimension 表包含两个投影:分段的超投影public.employee_dimension,包括所有表列;未分段的投影 public.employee_dimension_rep,包括列的子集:


=> SELECT export_objects('','employee_dimension');
                                                      export_objects
--------------------------------------------------------------------------------------------------------------------------

CREATE TABLE public.employee_dimension
(
    employee_key int NOT NULL,
    employee_gender varchar(8),
    courtesy_title varchar(8),
    employee_first_name varchar(64),
    employee_middle_initial varchar(8),
    employee_last_name varchar(64),
    employee_age int,
    hire_date date,
    employee_street_address varchar(256),
    employee_city varchar(64),
    employee_state char(2),
    employee_region char(32),
    job_title varchar(64),
    reports_to int,
    salaried_flag int,
    annual_salary int,
    hourly_rate float,
    vacation_days int,
    CONSTRAINT C_PRIMARY PRIMARY KEY (employee_key) DISABLED
);

CREATE PROJECTION public.employee_dimension
...
AS
 SELECT employee_dimension.employee_key,
        employee_dimension.employee_gender,
        employee_dimension.courtesy_title,
        employee_dimension.employee_first_name,
        employee_dimension.employee_middle_initial,
        employee_dimension.employee_last_name,
        employee_dimension.employee_age,
        employee_dimension.hire_date,
        employee_dimension.employee_street_address,
        employee_dimension.employee_city,
        employee_dimension.employee_state,
        employee_dimension.employee_region,
        employee_dimension.job_title,
        employee_dimension.reports_to,
        employee_dimension.salaried_flag,
        employee_dimension.annual_salary,
        employee_dimension.hourly_rate,
        employee_dimension.vacation_days
 FROM public.employee_dimension
 ORDER BY employee_dimension.employee_key
SEGMENTED BY hash(employee_dimension.employee_key) ALL NODES KSAFE 1;

CREATE PROJECTION public.employee_dimension_rep
...
AS
 SELECT employee_dimension.employee_key,
        employee_dimension.employee_gender,
        employee_dimension.employee_first_name,
        employee_dimension.employee_middle_initial,
        employee_dimension.employee_last_name,
        employee_dimension.employee_age,
        employee_dimension.employee_street_address,
        employee_dimension.employee_city,
        employee_dimension.employee_state,
        employee_dimension.employee_region
 FROM public.employee_dimension
 ORDER BY employee_dimension.employee_key
UNSEGMENTED ALL NODES;

SELECT MARK_DESIGN_KSAFE(1);

(1 row)

以下查询从 employee_dimension 选择所有表列并包含 PROJS 提示,指定两个投影。 public.employee_dimension_rep 未包含查询表中的所有列,因此优化器无法使用它。分段的投影包含了所有表列,因此优化器可以使用它,已经以下查询计划验证:

=> EXPLAIN SELECT * FROM employee_dimension /*+PROJS('public.employee_dimension_rep', 'public.employee_dimension')*/;

QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN SELECT * FROM employee_dimension /*+PROJS('public.employee_dimension_rep', 'public.employee_dimension')*/;

 Access Path:
 +-STORAGE ACCESS for employee_dimension [Cost: 177, Rows: 10K (NO STATISTICS)] (PATH ID: 1)
 |  Projection: public.employee_dimension_b0

7.14 - SKIP_PROJS

指定要避免用于查询的表的投影。如果 SKIP_PROJS 不包括对查询有效的所有可用投影,则优化器会发出警告并忽略投影提示。

语法

FROM table-name /*+SKIP_PROJS( [[database.]schema.]projection[,...] )*/

参数

[database.]schema

数据库和架构。默认架构为 public。如果指定一个数据库,它必须是当前数据库。

projection
要跳过的投影。可以指定逗号分隔投影的列表。

示例

在此示例中,EXPLAIN 输出显示优化器使用了给定查询的投影 public.employee_dimension_b0


QUERY PLAN DESCRIPTION:
------------------------------

 EXPLAIN SELECT employee_last_name, employee_first_name, employee_city, job_title FROM employee_dimension;

 Access Path:
 +-STORAGE ACCESS for employee_dimension [Cost: 59, Rows: 10K (NO STATISTICS)] (PATH ID: 1)
 |  Projection: public.employee_dimension_b0
 |  Materialize: employee_dimension.employee_first_name, employee_dimension.employee_last_name, employee_dimension.employee_city, employee_dimension.job_title
 |  Execute on: All Nodes

您可使用 SKIP_PROJS 提示避免使用此投射。如果有对此查询有效的其他投影,优化器将改用此投影:


QUERY PLAN DESCRIPTION:
------------------------------

EXPLAIN SELECT employee_last_name, employee_first_name, employee_city, job_title FROM employee_dimension /*+SKIP_PROJS('public.employee_dimension')*/;

 Access Path:
 +-STORAGE ACCESS for employee_dimension [Cost: 156, Rows: 10K (NO STATISTICS)] (PATH ID: 1)
 |  Projection: public.employee_dimension_super
 |  Materialize: employee_dimension.employee_first_name, employee_dimension.employee_last_name, employee_dimension.emplo
yee_city, employee_dimension.job_title
 |  Execute on: Query Initiator

7.15 - SKIP_STATISTICS

指示优化器生成仅包含由 ANALYZE_ROW_COUNT 收集的最少统计信息的查询计划。优化器会忽略由 ANALYZE_STATISTICSANALYZE_STATISTICS_PARTITION 使用和生成的其他统计信息。当用于对小型表执行查询时,此提示尤其有用,其中收集完整统计信息所需的时间量通常大于实际执行时间。

语法

SELECT /*+SKIP_STAT[ISTIC]S*/

EXPLAIN 输出

EXPLAIN 为包含 SKIP_STATISTICS(使用其缩写形式 SKIP_STATS)的查询返回以下输出:


=> EXPLAIN SELECT /*+ SKIP_STATS*/ customer_key, customer_name, customer_gender, customer_city||', '||customer_state, customer_age
    FROM customer_dimension WHERE customer_region = 'East' AND customer_age > 60;

 QUERY PLAN DESCRIPTION:
 ------------------------------

 EXPLAIN SELECT /*+ SKIP_STATS*/ customer_key, customer_name, customer_gender, customer_city||', '||customer_state,
 customer_age FROM customer_dimension WHERE customer_region = 'East' AND customer_age > 60;

 Access Path:
 +-STORAGE ACCESS for customer_dimension [Cost: 2K, Rows: 10K (STATISTICS SKIPPED)] (PATH ID: 1)
 |  Projection: public.customer_dimension_b0
 |  Materialize: public.customer_dimension.customer_age, public.customer_dimension.customer_key, public.customer_dimensi
on.customer_name, public.customer_dimension.customer_gender, public.customer_dimension.customer_city, public.customer_di
mension.customer_state
 |  Filter: (public.customer_dimension.customer_region = 'East')
 |  Filter: (public.customer_dimension.customer_age > 60)
 |  Execute on: All Nodes
...

7.16 - SYNTACTIC_JOIN

强制执行联接顺序并启用其他联接提示。

语法

SELECT /*+SYN[TACTIC]_JOIN*/

描述

为了实现最佳性能,优化器经常覆盖查询的指定联接顺序。通过包括 SYNTACTIC_JOIN 提示,可以确保优化器严格按规定强制执行查询的联接顺序。一个要求适用:联接语法必须符合 ANSI SQL-92 惯例。

SYNTACTIC_JOIN 提示必须紧跟在 SELECT 后面。如果带注释查询包含的另一个提示也必须跟在 SELECT 后面(例如 VERBATIM),则将这两个提示组合在一起。例如:

SELECT /*+ syntactic_join,verbatim*/

示例

在以下示例中,优化器为两个查询产生不同的计划,区别就在于包括或排除了 SYNTACTIC_JOIN 提示。

排除 SYNTACTIC_JOIN

EXPLAIN SELECT sales.store_key, stores.store_name, products.product_description, sales.sales_quantity, sales.sale_date
FROM (store.store_sales sales JOIN products ON sales.product_key=products.product_key)
JOIN store.store_dimension stores ON sales.store_key=stores.store_key
WHERE sales.sale_date='2014-12-01' order by sales.store_key, sales.sale_date;

 Access Path:
 +-SORT [Cost: 14K, Rows: 100K (NO STATISTICS)] (PATH ID: 1)
 |  Order: sales.store_key ASC, sales.sale_date ASC
 |  Execute on: All Nodes
 | +---> JOIN HASH [Cost: 11K, Rows: 100K (NO STATISTICS)] (PATH ID: 2) Outer (RESEGMENT)(LOCAL ROUND ROBIN) Inner (RESEGMENT)
 | |      Join Cond: (sales.product_key = products.product_key)
 | |      Materialize at Input: sales.store_key, sales.product_key, sales.sale_date, sales.sales_quantity
 | |      Execute on: All Nodes
 | | +-- Outer -> JOIN HASH [Cost: 1K, Rows: 100K (NO STATISTICS)] (PATH ID: 3)
 | | |      Join Cond: (sales.store_key = stores.store_key)
 | | |      Execute on: All Nodes
 | | | +-- Outer -> STORAGE ACCESS for sales [Cost: 1K, Rows: 100K (NO STATISTICS)] (PATH ID: 4)
 | | | |      Projection: store.store_sales_b0
 | | | |      Materialize: sales.store_key
 | | | |      Filter: (sales.sale_date = '2014-12-01'::date)
 | | | |      Execute on: All Nodes
 | | | |      Runtime Filter: (SIP1(HashJoin): sales.store_key)
 | | | +-- Inner -> STORAGE ACCESS for stores [Cost: 34, Rows: 250] (PATH ID: 5)
 | | | |      Projection: store.store_dimension_DBD_10_rep_VMartDesign_node0001
 | | | |      Materialize: stores.store_key, stores.store_name
 | | | |      Execute on: All Nodes
 | | +-- Inner -> STORAGE ACCESS for products [Cost: 3K, Rows: 60K (NO STATISTICS)] (PATH ID: 6)
 | | |      Projection: public.products_b0
 | | |      Materialize: products.product_key, products.product_description
 | | |      Execute on: All Nodes

包括 SYNTACTIC_JOIN

EXPLAIN SELECT /*+SYNTACTIC_JOIN*/ sales.store_key, stores.store_name, products.product_description, sales.sales_quantity, sales.sale_date
FROM (store.store_sales sales JOIN products ON sales.product_key=products.product_key)
JOIN store.store_dimension stores ON sales.store_key=stores.store_key
WHERE sales.sale_date='2014-12-01' order by sales.store_key, sales.sale_date;

 Access Path:
 +-SORT [Cost: 11K, Rows: 100K (NO STATISTICS)] (PATH ID: 1)
 |  Order: sales.store_key ASC, sales.sale_date ASC
 |  Execute on: All Nodes
 | +---> JOIN HASH [Cost: 8K, Rows: 100K (NO STATISTICS)] (PATH ID: 2)
 | |      Join Cond: (sales.store_key = stores.store_key)
 | |      Execute on: All Nodes
 | | +-- Outer -> JOIN HASH [Cost: 7K, Rows: 100K (NO STATISTICS)] (PATH ID: 3) Outer (BROADCAST)(LOCAL ROUND ROBIN)
 | | |      Join Cond: (sales.product_key = products.product_key)
 | | |      Execute on: All Nodes
 | | |      Runtime Filter: (SIP1(HashJoin): sales.store_key)
 | | | +-- Outer -> STORAGE ACCESS for sales [Cost: 2K, Rows: 100K (NO STATISTICS)] (PATH ID: 4)
 | | | |      Projection: store.store_sales_b0
 | | | |      Materialize: sales.sale_date, sales.store_key, sales.product_key, sales.sales_quantity
 | | | |      Filter: (sales.sale_date = '2014-12-01'::date)
 | | | |      Execute on: All Nodes
 | | | +-- Inner -> STORAGE ACCESS for products [Cost: 3K, Rows: 60K (NO STATISTICS)] (PATH ID: 5)
 | | | |      Projection: public.products_b0
 | | | |      Materialize: products.product_key, products.product_description
 | | | |      Execute on: All Nodes
 | | +-- Inner -> STORAGE ACCESS for stores [Cost: 34, Rows: 250] (PATH ID: 6)
 | | |      Projection: store.store_dimension_DBD_10_rep_VMartDesign_node0001
 | | |      Materialize: stores.store_key, stores.store_name
 | | |      Execute on: All Nodes

7.17 - UTYPE

指定如何组合 UNION ALL 输入。

语法

UNION ALL /*+UTYPE(union-type)*/

参数

union‑type
以下实参之一:
  • U:连接 UNION ALL 输入(默认)。

  • M:合并 UNION ALL 输入,排序顺序与源查询结果相同。此选项要求来自源查询的所有输入均采用相同的排序顺序;否则,Vertica 将发出警告并连接 UNION ALL 输入。

要求

包含 UTYPE 提示的查询必须也包含 SYNTACTIC_JOIN 提示。否则,优化器会忽略 UTYPE 提示并抛出一条警告。

7.18 - VERBATIM

完全按编写强制执行带注释查询。

VERBATIM 指示优化器创建一个包含某带注释查询中所有提示的查询计划。而且,它指示优化器不将其自身的计划开发处理用于与这些提示相关的查询计划组件。

此提示的用法在 optimizer-generatedcustom 定向查询之间有所不同,如下所述。

语法

SELECT /*+ VERBATIM*/

要求

VERBATIM 提示必须紧跟在 SELECT 后面。如果带注释查询包含的另一个提示也必须跟在 SELECT 后面(例如 SYNTACTIC_JOIN),则将这两个提示组合在一起。例如:

SELECT /*+ syntactic_join,verbatim*/

优化器生成的定向查询

在优化器为定向查询生成的带注释查询中,始终包含 VERBATIM 提示。例如,对于以下 CREATE DIRECTED QUERY OPTIMIZER 语句:


=> CREATE DIRECTED QUERY OPTIMIZER getStoreSales SELECT sales.store_key, stores.store_name, sales.product_description, sales.sales_quantity, sales.sale_date FROM store.storesales sales JOIN store.store_dimension stores ON sales.store_key=stores.store_key WHERE sales.sale_date='2014-12-01' /*+IGNORECONST(1)*/ AND stores.store_name='Store1' /*+IGNORECONST(2)*/ ORDER BY sales.store_key, sales.sale_date;
CREATE DIRECTED QUERY

优化器将生成包含 VERBATIM 提示的带注释查询:

=> SELECT query_name, annotated_query FROM V_CATALOG.DIRECTED_QUERIES WHERE query_name = 'getStoreSales';
-[ RECORD 1 ]---+------
query_name      | getStoreSales
annotated_query | SELECT /*+ syntactic_join,verbatim*/ sales.store_key AS store_key, stores.store_name AS store_name, sales.product_description AS product_description, sales.sales_quantity AS sales_quantity, sales.sale_date AS sale_date
FROM (store.storeSales AS sales/*+projs('store.storeSales')*/ JOIN /*+Distrib(L,L),JType(H)*/ store.store_dimension AS stores/*+projs('store.store_dimension_DBD_10_rep_VMartDesign')*/  ON (sales.store_key = stores.store_key))
WHERE (sales.sale_date = '2014-12-01'::date /*+IgnoreConst(1)*/) AND (stores.store_name = 'Store1'::varchar(6) /*+IgnoreConst(2)*/)
ORDER BY 1 ASC, 5 ASC

当优化器使用此定向查询时,将生成一个查询计划,该查询计划与其生成此定向查询时所使用的查询计划相等同:

=> ACTIVATE DIRECTED QUERY getStoreSales;
ACTIVATE DIRECTED QUERY

=> EXPLAIN SELECT sales.store_key, stores.store_name, sales.product_description, sales.sales_quantity, sales.sale_date FROM store.storesales sales JOIN store.store_dimension stores ON sales.store_key=stores.store_key WHERE sales.sale_date='2014-12-04' AND stores.store_name='Store14' ORDER BY sales.store_key, sales.sale_date;

 QUERY PLAN DESCRIPTION:
 ------------------------------

 EXPLAIN SELECT sales.store_key, stores.store_name, sales.product_description, sales.sales_quantity, sales.sale_date FROM store.storesales sales JOIN store.store_dimension stores ON sales.store_key=stores.store_key WHERE sales.sale_date='2014-12-04' AND stores.store_name='Store14' ORDER BY sales.store_key, sales.sale_date;

 The following active directed query(query name: getStoreSales) is being executed:
 SELECT /*+syntactic_join,verbatim*/ sales.store_key, stores.store_name, sales.product_description, sales.sales_quantity, sales.sale_date
FROM (store.storeSales sales/*+projs('store.storeSales')*/ JOIN /*+Distrib('L', 'L'), JType('H')*/store.store_dimension stores
/*+projs('store.store_dimension_DBD_10_rep_VMartDesign')*/ ON ((sales.store_key = stores.store_key))) WHERE ((sales.sale_date = '2014-12-04'::date)
AND (stores.store_name = 'Store14'::varchar(7))) ORDER BY sales.store_key, sales.sale_date

 Access Path:
 +-JOIN HASH [Cost: 463, Rows: 622 (NO STATISTICS)] (PATH ID: 2)
 |  Join Cond: (sales.store_key = stores.store_key)
 |  Materialize at Output: sales.sale_date, sales.sales_quantity, sales.product_description
 |  Execute on: All Nodes
 | +-- Outer -> STORAGE ACCESS for sales [Cost: 150, Rows: 155K (NO STATISTICS)] (PATH ID: 3)
 | |      Projection: store.storeSales_b0
 | |      Materialize: sales.store_key
 | |      Filter: (sales.sale_date = '2014-12-04'::date)
 | |      Execute on: All Nodes
 | |      Runtime Filter: (SIP1(HashJoin): sales.store_key)
 | +-- Inner -> STORAGE ACCESS for stores [Cost: 35, Rows: 2] (PATH ID: 4)
 | |      Projection: store.store_dimension_DBD_10_rep_VMartDesign_node0001
 | |      Materialize: stores.store_name, stores.store_key
 | |      Filter: (stores.store_name = 'Store14')
 | |      Execute on: All Nodes

自定义定向查询

只有当您为定向查询编写的带注释查询中显式包含 VERBATIM 提示时,自定义定向查询才会包含该提示。当优化器使用该定向查询时,会遵循 VERBATIM 提示,相应地创建查询计划。

如果您在创建自定义定向查询时忽略了 VERBATIM 提示,则不会将该提示与带注释查询一起存储起来。当优化器使用该定向查询时,会将其自身的计划开发处理应用于带注释查询,然后再生成查询计划。相比于此查询计划,若优化器针对创建定向查询时所使用的 Vertica 版本生成查询计划,则后者可能与之不等同。