3 查询语言
3.6 条件表达式
以下章节描述可以用在 WHERE 或 HAVING 语句内的条件表达式的语法结 构。
在可移植的应用中,不要在条件表达式中使用那些映射为序列化形式或作为
blob
的状态字段。(注:不期望持久化实现能够在内存中执行带有这种字段的查 询语句,而是要在数据库中执行)3.6.1 语法
字符串是用单引号‘’括住的——例如,‘literal’。带有单引号的字符串需 要用单引号转义——例如,‘literal’’s’。在查询中的字符串类似于 Java 的 String 使用 unicode 字符集编码。在查询的字符串语法中不支持 java 的转义符。
精确数值支持 java 的整型和 SQL 的整型数值语法。
近似数值支持 java 的浮点数以及 SQL 的近似数值语法。
枚举支持 java 的枚举语法。但必须指定枚举类。
为了和 java 语言规范保持一致,可以在数值后使用用适当的后缀来表示特 定的数值类型。在本规范中不要求支持十六进制和八进制。
Booolean 是 TRUE 和 FALSE。
所有预定义的保留字都是不区分大小写的。
3.6.2 标识变量
正如在 3.4.2 章节中所述,所有在 SELECT 或 DELECT 语句内的 WHERE 或 HAVING 语句中使用的标识变量必须在 FROM 语句内声明。同样,在 UPDATE 语句内的 WHERE 语句中使用的标识变量也必须在 UPDATE 语句内声明。
在 WHERE 和 HAVING 语句内使用的标识变量必需是可量化的。意思是,
这个标识变量代表的是实体抽象 Schema 类型实例或是一个集合的成员。标识变 量从来都不会指向一个集合。
3.6.3 路径表达式
除 了 在 empty_collection_comparison_expression 、 collection_memeber_expression 或作为 SIZE 操作的参数外,不能在 WHERE 和 HAVING 的条件表达式中使用 collection_valued_path_expression。
3.6.4 输入参数(入参)
可以使用位置和命名参数。在同一个查询语句内不可以同时使用位置参数和 命名参数。
入参只能在查询语句的 WHERE 或 HAVING 语句内使用。
注意:如果入参的值是
null
,涉及到入参的比较运算或数学运算将返回一个 不知道的值。参见3.11
。3.6.4.1 位置参数
位置参数需遵循以下规则:
z 在整数前使用?表示入参。如,?1。
z 入参的序号从 1 开始。
注意:同一个参数可以在查询语句内使用多次,而且参数的使用顺序可以和 位置参数的顺序不一致。
3.6.4.2 命名参数
命名参数以“:”为前缀。它遵循在 3.4.1 章节中描述的规则。命名参数是大 小写敏感的。
例如:
SELECT c
FROM Customer c WHERE c.status = :stat
在 2.6.1 章节内讲述了绑定当命名参数的 API。
3.6.5 组合条件表达式
条件表达是可以由其他条件表达式、比较操作、逻辑操作、结果值是 boolean 值的路径表达式、布尔语法和布尔入参组成。
在比较表达式中可以使用算术表达式。算术表达式由其他的算术表达式、算 术操作、结果值是数值的路径表达式和数值入参组成。
算术操作使用数值提升。
支持用“()”来改变表达式的计算顺序。
条件表达式的语法如下:
conditional_expression ::= conditional_term | conditional_expressionOR conditional_term
conditional_term ::= conditional_factor | conditional_termAND conditional_factor
conditional_factor ::= [NOT ] conditional_primary
conditional_primary ::= simple_cond_expression | (conditional_expression) simple_cond_expression ::=
comparison_expression | between_expression | like_expression | in_expression |
null_comparison_expression |
empty_collection_comparison_expression | collection_member_expression |
exists_expression
合计函数只能用在 HAVING 语句的条件表达式中,参见 3.7 章节。
3.6.6 操作符和操作优先级
下面列出的操作符的优先级是依次降低的:
z 导航操作符(.) z 数学运算符
+,- 一元运算符
*,/
+,- 两元的加和减
z 比较运算符:=,>,>=,<,<=,<>,[NOT] BETWEEN,[NOT] LIKE,[NOT]
IN,IS [NOT] NULL,IS [NOT] EMPTY,[NOT] MEMBER [OF]
z 逻辑运算符
NOT
AND
OR
下面的章节介绍在特定表达式内使用的操作符。
3.6.7 Between 表达式
在条件表达式内使用的[NOT] BETWEEN 操作符的语法如下:
arithmetic_expression [NOT]BETWEEN arithmetic_expressionAND arithmetic_expression |
string_expression [NOT]BETWEEN string_expressionAND string_expression |
datetime_expression [NOT]BETWEEN datetime_expressionAND datetime_expression
BETWEEN 表达式:x BETWEEN y AND z 等同于 y<=x AND x<=z。
对未知值和 NULL 值的规则在比较操作中同样适用。参加 3.11 章节。
例如:
p.age BETWEEN 15 and 19 is equivalent top.age >= 15 AND p.age <= 19 p.age NOT BETWEEN 15 and 19 is equivalent top.age < 15 OR p.age > 19
3.6.8 IN 表达式
在条件表达式中的[NOT] IN 操作符的语法如下:
in_expression ::=
state_field_path_expression [NOT]IN( in_item {, in_item}* | subquery) in_item ::= literal | input_parameter
State_field_path_expression 必须有一个字符串、数值或枚举值。
literal 和 input_paramter 的值的类型必须和 State_field_path_expression 的抽象 Schema 类型在类型上相对应。(参见 3.12)
子查询的结果必须和 State_field_path_expression 的抽象 Schema 类型在类型 上相对应。子查询在 3.6.15 章节“子查询”中描述。
例子:
o.country IN (‘UK’,’US’,’France’) is true for UK and false for Peru,and is equivalent to the expression (o.country=‘UK’) OR (o.country=‘US’) OR (o.country=’France’).
o.country NOT IN(‘UK’,’US’,’Frank’) is false for UK and true for Peru,and is equivalent to the expression NOT ((o.country=‘UK’) OR (o.country=‘US’ (o.country
= ‘France’)).
为 IN 操作符定义的用逗号分开的值的列表中至少有一个元素。
如果在 IN 或 NOT IN 表达式内的 state_field_path_expression 的值是 NULL 或未知,那么整个表达式的值就是未知的。
3.6.9 Like 表达式
在条件表达式中的[NOT] LIKE 操作符的语法如下:
string_expression [NOT] LIKE pattern_value [ESCAPE escape_character]
String_expression 必须是字符串。Pattern_value 是一个字符串或值是字符串 的入参,在这个字符串中,“_”代表任意单个字符,“%”代表字符串(包括空 串),其他字符的字符代表自己。Escape_character 是可选的,它是单个字符或值
是单个字符的入参(也就是,char 或 Character),用于转义在 pattern_value 内的 下划线和百分号特殊字符。(参考《数据库语言 SQL.ANSI X3.135-1992 或 ISO/IEC 9075:1992》,它对这些规则有精确的定义)
例如:
z address.phone LIKE ‘12%3’ is true for ‘123’ ‘12993’ and false for
‘1234’
z asentence.word LIKE ‘l_se’ is true for ‘lose’ and false for ‘loose’
z aword.underscored LIKE ‘\_%’ ESCAPE ‘\’ is true for ‘_foo’ and false for ‘bar’
z address.phone NOT LIKE ‘12%3’ is false for ‘123’ and ‘12993’ and true for ‘1234’
如果 string_expression 或 pattern_value 的值是 NULL 或未知,那么 LIKE 表 达式的值就是未知的。如果指定 escape_character 但它的值是 NULL,那么 LIKE 表达式的值就是未知的。
3.6.10 NULL 比较表达式
在条件表达式中的 [NOT] IS NULL 表达式的语法如下:
{single_valued_path_expression | input_parameter } IS [NOT] NULL 空比较表达式用于检查单值路径表达式或入参是否是 NULL 值。
3.6.11 EMPTY 集合比较表达式
在 empty_collection_comparison_expression 中使用 IS EMPTY 的语法如下:
collection_valued_path_expression IS [NOT] EMPTY
这个表达式用于检查值是集合的路径表达式的值集合是否是空的(没有元 素)。
例如:
SELECT o
FROM Order o
WHERE o.lineItems IS EMPTY
如果在一个空集合比较表达式中的值是集合的路径表达式的值是未知的,那 么空比较表达式的值就是未知的。
3.6.12 集合成员表达式
在 collection_member_expression 中使用 MEMBER OF(注:OF 是可选的)
的语法如下:
entity_expression[NOT] MEMBER [OF]collection_valued_path_expression entity_expression ::=
single_valued_association_path_expression | simple_entity_expression simple_entity_expression ::=identification_variable |input_parameter 这个表达式用于检查指定的值是否是路径表达式集合值的成员。
如果路径表达式集合值是空集合,那么 MEMBER OF 表达式就是 FALSE,
但 NOT MEMBER OF 表达式就是 TRUE。否则,如果集合值的路径表达式或单 值关联字段路径表达式的值是 NULL 或未知,那么这个集合成员表达式的值也 是未知的。
3.6.13 EXISTS 表达式
EXISTS 是一个谓词。只有当子查询结果由一个或多个值组成时,EXISTS 表达式的值是 TRUE,否则就是 FALSE。
语法如下:
exists_expression::= [NOT]EXISTS (subquery) 例如:
SELECT DISTINCT emp FROM Employee emp WHERE EXISTS (
SELECT spouseEmp
FROM Employee spouseEmp WHERE EXISTS (
SELECT spouseEmp
FROM Employee spouseEmp WHERE spouseEmp = emp.spouse)
上例中查询的结果由所有职员的配偶也是职员的记录组成。
和 ALL 或 ANY 条件表达式一起使用的比较操作符有:=,<,<=,>,>=,<>。子 查询的结果必须和比较操作符的其他参数的结果在类型上相对应。参见 3.12 章 节。
ALL 或 ANY 表达式的语法如下:
all_or_any_expression ::= {ALL |ANY |SOME}(subquery) 例子:
SELECT emp
FROM Employee emp WHERE emp.salary > ALL ( SELECT m.salary
FROM Manager m
WHERE m.department = emp.department)
3.6.15 子查询
可以在 WHERE 或 HAVING 语句内使用子查询。(注:子查询在这个规范版 本中被限定到 WHERE 和 HAVING 语句。将在以后的版本中考虑在 FROM 子句 中支持子查询)
子查询的语法如下:
subquery ::= simple_select_clause subquery_from_clause [where_clause]
[groupby_clause] [having_clause]
simple_select_clause ::=SELECT [DISTINCT] simple_select_expression subquery_from_clause ::=
FROM subselect_identification_variable_declaration {, subselect_identification_variable_declaration}*
subselect_identification_variable_declaration ::=
identification_variable_declaration |
association_path_expression [AS] identification_variable | collection_member_declaration
simple_select_expression::=
single_valued_path_expression | aggregate_expression |
identification_variable 例子:
SELECT DISTINCT emp FROM Employee emp WHERE EXISTS ( SELECT spouseEmp
FROM Employee spouseEmp WHERE spouseEmp = emp.spouse) SELECT c
FROM Customer c
WHERE (SELECT COUNT(o) FROM c.orders o) > 10
注意:在某些上下文中一个子查询可以用于要求子查询是标量子查询(也就 是说,产生一个单一结果)。在下面的例子中来解释说明,这个例子有一个数值 比较操作:
SELECT goodCustomer
FROM Customer goodCustomer
WHERE goodCustomer.balanceOwed < (
SELECT avg(c.balanceOwed) FROM Customer c)
3.6.16 函数表达式
Java 持久化查询语言有以下内置的函数,这些函数可以在 WHERE 或 HAVING 语句内使用。
如果函数表达式的参数值是 null 或未知,那么函数的值就是未知的。
3.6.16.1 字符串函数
functions_returning_strings ::=
CONCAT(string_primary, string_primary) | SUBSTRING(string_primary,
simple_arithmetic_expression,simple_arithmetic_expression) | TRIM(
[[trim_specification] [trim_character]FROM] string_primary) | LOWER(string_primary) |
UPPER(string_primary)
trim_specification ::=LEADING | TRAILING | BOTH functions_returning_numerics::=
LENGTH(string_primary)|
LOCATE(string_primary,string_primary[, simple_arithmetic_expression]) |
如果没有提供剪切规范(trim_specification),则假定是 BOTH。TRIM 函数返回 被剪切后的字符串。
ABS(simple_arithmetic_expression) | SQRT(simple_arithmetic_expression)|
MOD(simple_arithmetic_expression, simple_arithmetic_expression) | SIZE(collection_valued_path_expression)
ABS 函数有一个数值参数,返回一个和参数同样类型的数值(integer,float
或 double)。求绝对值。
SQRT 函数参数是数值参数,返回值是 double。
MOD 函数有两个整型参数,返回一个整数。
SIZE 函数返回一个整型值,集合内元素的个数。如果集合是空,那么 SIZE 函数返回 0.
在这些函数内的数值参数可以对应到 java 的对象数值类型,也对应 java 的 原始数值类型。
3.6.16.3 时间函数
functions_returning_datetime:=
CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP
时间函数返回数据库服务器的当前日期、时间和时间戳。