Skip to content

4. SQL 语言中的表达式

4.1. Introduction

在大多数 SQL 命令中,可以使用表达式。以 SELECT 命令为例:

syntaxe
SELECT expr1, expr2, ... from table
WHERE expression

SELECT 筛选满足 expression 条件的行,并为每行显示 expri 的值。

示例

SQL> select prix*1.186 from biblio
SQL> select titre from biblio where prix between 100 and 150

本节旨在阐明表达式的概念。一个基本表达式具有如下形式:

操作数1 opérateur 操作数2

函数(参数)

示例

在表达式 中,GENRE = 'ROMAN'

  • GENRE 是操作数1
  • 'ROMAN' 是操作数2
  • = 是运算符

在表达式 upper(genre)

  • upper 是一个函数
  • 类型是该函数的参数。

我们将首先处理包含运算符的表达式,然后介绍 Firebird 中可用的函数。

4.2. 包含运算符的表达式

我们将根据操作数的类型对包含运算符的表达式进行分类:

  • 数值
  • 字符串
  • 日期
  • 布尔值或逻辑值

4.2.1. 操作数为数值类型的表达式

4.2.1.1. 运算符列表

nombre1nombre2nombre3 为若干数字。可使用的运算符如下:

关系运算符

nombre1 > nombre2
:数1 大于 数2
nombre1 >= nombre2
: 数字1 大于或等于数字2
nombre1 < nombre2
: 数值1小于数值2
nombre1 <= nombre2
: 数值1小于或等于数值2
nombre1 = nombre2 
: 数值1 等于 数值2
nombre1 != nombre2 
: 数值1 不同于 数值2
nombre1 <> nombre2
: 同上
nombre1 BETWEEN nombre2 AND nombre3
: 数值1在区间内[nombre2,nombre3]
nombre1 IN (liste de nombres)
: 数字1属于数字列表
nombre1 IS NULL
: 数字1没有值
nombre1 IS NOT NULL
: 数值1有值

算术运算符

nombre1 + nombre2
: 加法
nombre1 - nombre2
: 减法
nombre1 * nombre2
: 乘法
nombre1 / nombre2
: 除法

4.2.1.2. 关系运算符

一个关系表达式表示一种关系,该关系为真或假。因此,此类表达式的结果是一个布尔值或逻辑值。

示例

SQL> select titre,prix from biblio where prix between 100 and 150

Image

SQL> select titre,prix from biblio where prix not between 100 and 150

Image

SQL> select titre,prix from biblio where prix in (200,210)

Image

4.2.1.3. 算术运算符

算术表达式对我们来说并不陌生。它表示对数值数据进行的计算。 我们之前已经遇到过此类表达式:假设文件 BIBLIO 中记录的价格为不含税价格。我们希望以 18.6% 的税率 TVA 显示每只股票及其价格 TTC:

    SELECT TITRE, PRIX*1.186 FROM BIBLIO

如果价格需要上涨3%,则命令应为

    UPDATE BIBLIO SET PRIX = PRIX*1.03

一个表达式中可能包含多个算术运算符,此外还有函数和括号。这些元素根据不同的优先级进行处理:

1
fonctions
<---- 优先级更高
2
()
 
3
* et /
 
4
+ et -
<---- 优先级较低

当表达式中存在两个优先级相同的运算符时,将首先计算表达式中最左侧的那个。

示例

表达式 PRIX*TAUX+TAXES 将被计算为 (PRIX*TAUX)+TAXES。实际上,乘法运算符将首先被应用。 表达式 PRIX*TAUX/100 将被计算为 (PRIX*TAUX)/100。

4.2.2. 具有字符类型操作数的表达式

4.2.2.1. 运算符列表

可用的运算符如下:

字符串1、字符串2、字符串3为字符串示例

chaine1 > chaine2
:字符串1大于字符串2
chaine1 >= chaine2
: 字符串1大于等于字符串2
chaine1 < chaine2
: 字符串1小于字符串2
chaine1 <= chaine2
: 字符串1 小于或等于字符串2
chaine1 = chaine2 
: 字符串1 等于 字符串2
chaine1 != chaine2
: 字符串1 不同于 字符串2
chaine1 <> chaine2
: 同上
chaine1 BETWEEN chaine2 AND chaine3
: 字符串1在区间内[chaine2,chaine3]
chaine1 IN liste de chaines
: 字符串1属于字符串列表
chaine1 IS NULL
: 字符串1没有值
chaine1 IS NOT NULL
: 字符串1有值
chaine1 LIKE modèle
: 字符串1 符合模板

连接运算符

字符串1 || 字符串2 : chaine2chaine1 连接

4.2.2.2. 关系运算符

使用 <、<= 等运算符比较字符串意味着什么?

每个字符都由一个整数编码。比较两个字符时,实际上是比较它们的整数编码。所采用的编码遵循字典的自然顺序:

blanc<..< 0 < 1 < ...< 9 < ...< A < B <... < Z < ... < a < b < ... < z

数字排在字母之前,大写字母排在小写字母之前。

4.2.2.3. 两个字符串的比较

假设关系 'CHAT' < 'CHIEN'。该关系是真还是假?为了进行此比较,SGBD 会基于整数编码对两个字符串进行逐字符比较。 一旦发现两个字符不同,则拥有较小字符的字符串被视为小于另一个字符串。在我们的示例中,'CHAT' 与 'CHIEN' 进行比较。我们得到以下连续结果:

     'CHAT    ' 'CHIEN'
----------------------------
    'C'    =    'C'
    'H'    =    'H'
     'A    '     < 'I'

经过最后一次比较,字符串 'CHAT' 被判定比字符串 'CHIEN' 更短。因此,关系 'CHAT' < 'CHIEN' 为真。

现在比较 'CHAT' 和 'chat'。

     'CHAT    ' 'chat'
--------------------------
     'C    '     < 'c'

经过此比较,关系 'CHAT' < 'chat' 被判定为真。

示例

SQL> select titre from biblio

Image

SQL> select titre from biblio where upper(titre) between 'L' and 'M'

Image

4.2.2.4. 运算符 LIKE

运算符 LIKE 的使用方法如下:chaîne LIKE modèle

chaînemodèle 匹配,则该关系成立。后者是一个字符串,其中可能包含两个通配符:

%
它表示任意字符序列
_
表示任意 1 个字符

示例

SQL> select titre from biblio

Image

SQL> select titre from biblio where titre like 'M%';

Image

SQL> select titre from biblio where titre like 'L_ %';

Image

4.2.2.5. 连接运算符

SQL > select '[' || titre || ']' from biblio where upper(titre) LIKE 'L_ %'

Image

4.2.3. 包含日期类型操作数的表达式

date1、date2、date3 均为日期。可使用的运算符如下:

关系运算符

date1 < date2
若 date1 早于 date2,则为真
date1 <= date2
若 date1 小于或等于 date2,则为真
date1 > date2
如果 date1 晚于 date2,则为真
date1 >= date2
当日期1大于等于日期2时,该条件成立
date1 = date2
当 date1 和 date2 相同时为真
date1 <> date2
如果 date1 和 date2 不同,则为真。
date1 != date2
同上
date1 BETWEEN date2 AND date3
如果 date1 位于 date2 和 date3 之间,则为真
date1 IN (liste de dates)
如果 date1 在日期列表中,则为真
date1 IS NULL
如果 date1 没有值,则为真
date1 IS NOT NULL
如果 date1 有值,则为真
date1 LIKE modèle
如果 date1 符合模式,则为真
ALL,ANY,EXISTS
 

算术运算符

date1 - date2
:date1 与 date2 之间的天数
date1 - nombre
: 满足 date1-date2=n 的 date2
date1 + nombre
: 满足 date2-date1=n 的 date2

示例

SQL> select achat from biblio

Image

SQL>select achat from biblio
   where achat between '01.01.1988' and '31.12.1988';

Image

SQL> select titre, achat from biblio
where cast(achat as char(10)) like '1988'

Image

图书馆藏书的年代?

SQL> select titre, cast('now' as date)-achat "age(jours)" from biblio

Image

4.2.4. 布尔运算符表达式

需要提醒的是,布尔值或逻辑值只有两种可能的取值:真或假。逻辑操作数通常是关系表达式的结果。

booléen1booléen2 为两个布尔值。有三种可能的运算符,其优先级顺序如下:


booléen1 AND booléen2
booléen1 booléen2 均为真时,该表达式为真。

booléen1 OR booléen2
booléen1 booléen2 为真时,该表达式为真。

NOT booléen1
的值为 booléen1 值的反值。

示例

SQL> select titre,genre,prix from biblio order by prix desc

Image

搜索价格介于以下两个数值之间的书籍:

SQL> select titre,genre,prix from biblio
     where prix>=130 and prix <=170

Image

反向搜索:

SQL> select titre,genre,prix from biblio
     where prix<130 or prix >170
     order by prix asc

Image

请注意运算符的优先级!

SQL> select titre,genre,prix from biblio
  where genre='ROMAN' and prix>200 or prix<100
  order by prix asc

Image

使用括号来控制运算符的优先级:

SQL> select titre,genre,prix from biblio
  where genre='ROMAN' and (prix>200 or prix<100)
  order by prix asc

Image

4.3. Firebird 的预定义函数

Firebird 提供了预定义函数。这些函数无法直接在 SQL 命令中使用。 首先需执行脚本 SQL <firebird>\UDF\ib_udf.sql,其中 <firebird> 指 Firebird 的安装目录:

Image

对于 IBExpert,我们按以下步骤操作:

  • 我们使用通过 [Tools/ Script Executive] 选项生成的 [Script Excecutive] 工具:

Image

  • 工具准备就绪后,我们加载脚本 <firebird>\UDF\ib_udf.sql:

Image

  • 然后执行脚本:

Image

完成上述操作后,Firebird 的预定义函数即可在脚本执行时所连接的数据库中使用。要查看这一点,只需进入数据库浏览器,并点击导入函数的数据库中的 [UDF] 节点:

Image

上图显示了该数据库中可用的函数。为了测试这些函数,创建一个单行表会比较方便。我们将该表命名为 TEST:

Image

并按以下方式定义(右键单击“Tables”/“New Table”):

在该表中添加一行:

Image

Image

现在进入编辑器 SQL(F12),并发出以下命令 SQL:

SQL> select cos(0) from test

该命令使用了预定义函数 cos(余弦)。上述命令会对表 TEST 的每一行计算 cos(0),实际上仅针对一行。因此,最终仅显示 cos(0) 的值

Image

UDF(用户定义函数)是用户可以创建的函数,因此可以在网上找到 UDF 函数库。本文仅介绍 Firebird 可下载版本(2005)中提供的一部分函数。 我们将这些函数按其参数的主要类型或功能进行分类:

  • 具有数值型参数的函数
  • 字符串类型参数函数

4.3.1. 具有数值类型参数的函数


abs(nombre)
数的绝对值
abs(-15)=15

ceil(nombre)
不小于 nombre 的最小整数
ceil(15.7)=16

floor(nombre)
不大于 nombre 的最大整数
floor(14.3)=14

div(nombre1,nombre2)
nombre1 除以 nombre2 的整数商(商为整数)
div(7,3)=2

mod(nombre1,nombre2)
nombre1 除以 nombre2 的整数除法余数(商为整数)
mod(7,3)=1

sign(nombre)
-1,若 nombre<0
若 nombre=0,则为 0
nombre>0,则为 +1
sign(-6)=-1

sqrt(nombre)
nombre 的平方根,若 nombre ≥ 0
-1,若 nombre<0
sqrt(16)=4

4.3.2. 带字符串参数的函数

ascii_char(数字)
字符代码 ASCII nombre
ascii_char(65)='A'
lower(字符串)
chaine 转换为小写
lower('INFO')='info'
ltrim(字符串)
左截取 - 删除 chaine 文本前面的空格:
ltrim(' 小猫')='小猫'
replace(字符串1,字符串2,字符串3)
chaine2 替换为 chaine3,位于 chaine1 中。
replace('猫和狗','猫','**')='**和**'
rtrim(字符串1,字符串2)
右截断 - 与 ltrim 相同,但从右侧截断
rtrim('猫 ')='猫'
substr(字符串,p,q)
chaine 的子字符串,起始位置为 p,结束位置为 q.
substr('chaton',3,5)='ato'
ascii_val(字符)
ASCII 的代码(源自 caractère)
ascii_val('A')=65
strlen(字符串)
chaine的字符数
strlen('chaton')=6