标量表达式

大多数SQL语句可以包含从数据中计算新值的标量表达式。例如,在查询SELECT ceil(num) FROM a中,表达式ceil(num)计算列中值的四舍五入值。

标量表达式产生适合存储单个表格单元格(一行一列)中的值。它们可以与表达式和选择查询进行对比,后者产生结构化的结果。

常数

常量表达式表示一个不变的简单值。

列的引用

查询中的表达式可以通过两种方式引用当前数据源中的列:

列的名称

  • 如果列的名称也是SQL关键字,则必须适当地引用该名称。例如:SELECT "Default" FROM conf
  • 如果名称不明确(例如,在连接多个表时),可以通过在列名前加上表名来消除歧义。例如,SELECT res.num FROM res

列的序号位置

  • 例如,SELECT @1 FROM res选择res中的第一列。

一元和二元运算

以一元运算符为前缀的表达式,或由二元运算符分隔的两个表达式构成一个新表达式。

有关Hubble运算符的完整列表,以及有关它们的优先顺序以及每个运算符的有效操作数的数据类型的详细信息,请参阅函数

值比较

标准运算符<(小于)、>(大于)、<=(小于或等于)、>=(大于或等于)、=(等于)<>!=(不等于 )、(IS等于)和(IS NOT不等于) ) 可以应用于来自单一数据类型的任何一对值,以及来自不同数据类型的一些值对。

以下特殊规则适用:

  • NULL总是比其他所有值都小,甚至是它自己。
  • 要检查一个值是否是NULL,请使用IS运算符或条件表达式IFNULL(...)

多值比较

语法:

<expr> <comparison> ANY  <expr>
<expr> <comparison> SOME <expr>
<expr> <comparison> ALL  <expr>

值比较运算符<, >, =, <=,>=,<>!=以及模式匹配运算符[NOT] LIKE可用于将左侧的单个值与右侧的多个值进行比较。

这是通过使用关键字ANY/SOME/ALL或组合运算符来完成的。

比较结果为真当且仅当:

  • 对于ANY/SOME,左侧值的比较对于右侧的任何元素都是true
  • 对于ALL,对于右侧的每个元素,左侧值的比较都为真。

比如:

SELECT 1 = ANY (1, 2, 3) as bools;
 bools
---------
  true
SELECT 1 = ALL (1, 2, 3) as bools;
 bools
---------
  false
SELECT 4 = ANY ARRAY[56, 4, 10] as bools;
 bools
---------
  true

设置成员规则

语法:

<expr> IN <expr>
<expr> IN ( ... subquery ... )

<expr> NOT IN <expr>
<expr> NOT IN ( ... subquery ... )

当且仅当左操作数的值是计算右操作数的结果的一部分时才返回TRUE

select ('a') in (select * from abc);
select  a in (1, 2, 3) from test_table;

字符串模式匹配

语法:

<expr> LIKE      <expr>

<expr> NOT LIKE  <expr>

将两个表达式都计算为字符串,然后测试左侧的字符串是否与右侧给出的模式匹配。

模式可以包含_匹配任何单个字符,或%匹配任何零个或多个字符的序列。

例如:

SELECT 'tuesday' LIKE '%day' AS a, 'tursday' LIKE 'tur_day' AS b;
  a   |  b   | 
------+-------
  true| true |

使用POSIX正则表达式匹配字符串

语法:

<expr> ~   <expr>
<expr> ~*  <expr>
<expr> !~  <expr>
<expr> !~* <expr>

将两个表达式都计算为字符串,然后测试左侧的字符串是否与右侧给出的模式匹配。

带有星号的*使用不区分大小写的匹配;否则匹配区分大小写。

LIKE模式不同,正则表达式可以匹配字符串中的任何位置,而不仅仅是开头。

例如:

select 'tuesday' ~ 'day' AS x, 'tuesday' ~ 't[uU][eE]sday' AS y, 'tuesday' ~* 'T.*y' AS z;
  x   |  y   |  z
-------+------+-------
  true| true | true

使用SQL正则表达式匹配字符串

语法:

<expr> SIMILAR TO     <expr>
<expr> NOT SIMILAR TO <expr>

将两个表达式都计算为字符串,然后测试左侧的字符串是否与右侧给出的模式匹配。

该模式使用SQL标准的正则表达式定义来表示。这是 SQL中LIKE模式和 POSIX正则表达式的混合:

  • _%分别表示任何字符或任何字符串。
  • .专门匹配句点字符,不像在 POSIX中它是通配符。
  • 大多数其他 POSIX语法照常适用。
  • 该模式匹配整个字符串(如LIKE,与POSIX正则表达式不同)。

例如:

select 'tuesday' SIMILAR TO '__esday' AS x, 'tuEsday' SIMILAR TO 't[uU][eE]sday' AS y, 'tuesday' SIMILAR TO 'tu%y' AS z;
  x   |  y   |  z
-------+------+-------
  true| true | true

函数调用和SQL特殊形式

语法:

<name> ( <arguments...> )

内置函数名称后跟左括号,后跟逗号分隔的表达式列表,后跟右括号。

这会将命名函数应用于括号之间的参数。当函数的命名空间没有前缀时, 名称解析规则决定调用哪个函数。

此外,还支持以下SQL特殊形式:

特殊形式相当于
AT TIME ZONEtimezone()
CURRENT_CATALOGcurrent_catalog()
COLLATION FORpg_collation_for()
CURRENT_DATEcurrent_date()
CURRENT_ROLEcurrent_user()
CURRENT_SCHEMAcurrent_schema()
CURRENT_TIMESTAMPcurrent_timestamp()
CURRENT_USERcurrent_user()
EXTRACT(<part> FROM <value>)extract("<part>", <value>)
OVERLAY(<text1> PLACING <text2> FROM <int1> FOR <int2>)overlay(<text1>, <text2>, <int1>, <int2>)
OVERLAY(<text1> PLACING <text2> FROM <int>)overlay(<text1>, <text2>, <int>)
SESSION_USERcurrent_user()
SUBSTRING(<text> FOR <int1> FROM <int2>))substring(<text>, <int2>, <int1>)
SUBSTRING(<text> FOR <int>)substring(<text>, 1, <int>))
SUBSTRING(<text> FROM <int1> FOR <int2>)substring(<text>, <int1>, <int2>)
SUBSTRING(<text> FROM <int>)substring(<text>, <int>)
TRIM(<text1> FROM <text2>)btrim(<text2>, <text1>)
TRIM(<text2>, <text1>)btrim(<text2>, <text1>)
TRIM(FROM <text>)btrim(<text>)
TRIM(LEADING <text1> FROM <text2>)ltrim(<text2>, <text1>)
TRIM(LEADING FROM <text> )ltrim(<text>)
TRIM(TRAILING <text1> FROM <text2>)rtrim(<text2>, <text1>)
TRIM(TRAILING FROM<text> )rtrim(<text>)
USERcurrent_user()

下标表达式

例如,如果名称A引用了一个包含 10个值的数组,A[5]则将检索第5个值。第一个值的索引为 1。

如果索引小于或等于 0,或者大于数组的大小,则下标表达式的结果为NULL

条件表达式

表达式可以测试条件表达式,并根据是否满足或满足哪个条件,计算一个或多个附加操作数。

这些表达式格式共享以下属性:它们的某些操作数仅在条件为真时才被评估。当操作数否则无效时,这一点尤其重要。例如, 如果a为 0,IF(a=0, 0, x/a)则返回 0 ,否则返回x/a的值。

IF表达式

语法:

IF ( <cond>, <expr1>, <expr2> )
select IF(tb.a=0, 0, b/a) from tb;
            if
--------------------------
                       0
                       0
  0.33333333333333333333
                    0.25

CASE表达式

语法:

CASE <cond>
  WHEN <condval1> THEN <expr1>
  [ WHEN <condvalx> THEN <exprx> ] ...
  [ ELSE <expr2> ]
END

例如:

select
b,
case b
when 1 then 10
when 2 then 20
when 3 then 30
else null
end as t  
from tb;
  b   | t
-------+-----
    0 | NULL
    0 | NULL
    1 | 10
    1 | 10

搜索CASE表达式

CASE WHEN <cond1> THEN <expr1>
   [ WHEN <cond2> THEN <expr2> ] ...
   [ ELSE <expr> ]
END

例如:

select
b,
case 
when b=1 then 10
when b=2 then 20
when b=3 then 30
else null
end as t 
from tb;
  b   | t
-------+-----
    0 | NULL
    0 | NULL
    1 | 10
    1 | 10

NULLIF表达式

语法:

NULLIF ( <expr1>, <expr2> )

相当于:IF ( <expr1> = <expr2>, NULL, <expr1> )

例如:

select b,c,nullif(b,c) from tb;
   b   |  c   | nullif
-------+------+---------
     0 |    0 | NULL
     0 |    1 |      0
     1 |    0 |      1
     1 |    1 | NULL

COALESCE和IFNULL表达式

语法:

IFNULL   ( <expr1>, <expr2> )
COALESCE ( <expr1> [, <expr2> [, <expr3> ] ...] )

COALESCE首先计算第一个表达式。如果它的值不是 NULL,则直接返回它的值。否则,它返回COALESCE对剩余表达式应用的结果。如果所有表达式都是NULL,则返回NULL

IFNULL(a, b)相当于COALESCE(a, b)

例如:

select c,b, IFNULL(c,b) from tb;
 c   |  b   | coalesce
-------+------+-----------
   0 |    0 |        0
   1 |    0 |        1
   0 |    1 |        0
   1 |    1 |        1
   0 | NULL |        0
   1 | NULL |        1
  NULL | NULL |     NULL

逻辑运算符

语法:

NOT <expr>
<expr1> AND <expr2>
<expr1> OR  <expr2>

ANDOR是可交换的。此外,输入ANDOR不以任何特定顺序进行评估。如果仅使用另一个操作数就可以完全确定结果,则某些操作数甚至可能根本不求值。

聚合表达式

聚合表达式的语法与函数调用相同,但有一个特殊情况COUNT

<name> ( <arguments...> )
COUNT ( * )

聚合表达式和函数调用的区别在于前者使用聚合函数 ,并且只能出现在SELECT子句中呈现的表达式列表中。

聚合表达式根据使用的聚合函数计算当前选定的所有行的组合值。

显式类型强制

语法:

<expr> :: <type>
CAST (<expr> AS <type>)

计算表达式并将结果值转换为指定的类型。

例如:

select now(),CAST(now() AS DATE);
                now                |            now             
+----------------------------------+---------------------------+
  2022-08-09 09:27:21.158674+08:00 | 2022-08-09 00:00:00+00:00  

数组构造函数

语法:

ARRAY[ <expr>, <expr>, ... ]

计算为包含指定值的数组。

例如:

select ARRAY[6,5,1] AS a;
     a
-----------
  {6,5,1}

数组的数据类型是从提供的表达式的值推断出来的。数组中的所有位置必须具有相同的数据类型。

元组构造函数

语法:

(<expr>, <expr>, ...)
ROW (<expr>, <expr>, ...)

计算一个包含所提供表达式的值的元组。

例如:

select ('a', 13, 2.1) as a;
       a
----------------
  (a,13,2.1)

结果元组的数据类型是从值中推断出来的,元组中的每个位置都可以具有不同的数据类型。