EJB3持久化规范(第四章)

Java持久化查询语言用于根据实体和他们的字段定义查询。EJB QL使得开发人员能够以跨平台的方式指定查询元语,而不依赖于特定的数据库。
Java持久化查询语言是对EJBQL(在《企业JavaBean》中定义)的扩展。Java持久化查询语言增加了操作,包括批更新和批删除,连接操作,GROUP BY,HAVING,投影(projection),以及子查询;并且支持动态查询和命名参数查询。整个语言既可以用在静态查询,也可以用于动态查询。
本章对java持久化查询语言做了全面的定义。
Java持久化查询语言是一个使用元语描述动态和静态查询的查询规范语言。它用于定义使用本规范中定义的实体和它们的持久化字段及其关系的查询。
Java持久化查询语可以被编译成本地语言,如数据库的SQL或其他持久化存储的语言。这样,查询就可以方便地切换到数据库提供的本地语言,而不要需要在运行时切换。这样的话,查询的方法可以被很好的优化。
查询语言使用实体(包括关系)的抽象持久化schema,并且基于数据模型定义操作和表达式。它使用类似SQL的语法基于实体抽象schema和它们的关系来查询对象或值。这样可以做到在实体被部署前可以解析和验证查询。
术语“抽象持久化schema ”指的是java 持久化查询操作的持久化schema 抽象(持久化实体,它们的状态,以及它们的关系)。使用这些持久化schema 抽象的查询被转换成使用目标数据库schema (实体对应的schema )的查询。参见3.3 章节。
查询可以定义在注释符中,也可以定义在XML描述符中。如果查询和实体定义在同一个持久化单元内,可以在一个查询内使用多个实体的抽象schema。路径表达式可以遍历在同一个持久化单元内的关系。
一个持久化单元定义了应用相关的或分组的所有类,并且这些类必须被映射到同一个数据库中。
一个java持久化语言语句可以是一个select语句、更新语句、或者是一个删除语句。
本章把所有这些语句都称为“查询”。这样,在提到特殊的语句类型时,能区分出特殊的语句类型。
用BNF语法,查询语句被定义为:
QL_statement :: = select_statement | update_statement | delete_statement
一个持久化查询语言语句可以动态的构造,也可以静态的定义在注解符中或XML配置文件的元素内。
所有的查询语句都可以有参数。
一个select语句由以下语句组成:
l 一个SELECT语句,它决定了将要选择的对象或值的类型。
l 一个FROM语句,它提供了一些声明,这些声明用于指派域(译者注:领域对象)到查询语句内其他语句中特定的表达式上。
l 一个可选的WHERE语句,用于限定查询返回的结果。
l 一个可选的GROUP BY语句,它用于按照分组方式组织返回查询结果。
l 一个可选的HAVING语句,用于过滤组。
l 一个可选的ORDER BY语句,用于排序返回的结果。
用BNF语法,select语句被定义为:
select_statement :: = select_clause from_clause [where_clause] [groupby_clause][having_clause] [orderby_clause]
一个select语句必须有一个SELECT和一个FROM语句。“[]”表示其内的语句是可选的。
1.2.2    Update和Delete语句
更新和删除语句提供了对实体集合的批量操作。
用BNF语法,更新和删除操作定义为:
update_statement :: = update_clause [where_clause]
delete_statement :: = delete_clause [where_clause]
更新和删除语句决定了实体被更新还是被删除的类型。WHERE语句用于限定更新或删除的范围。
更新和删除语句在3.10中作进一步的描述。
1.3    抽象Schema类型和查询域
Java持久化语言是类型语言,他的每一个表达式都有一个类型。表达式的类型来自表达式的结构、标识变量声明的抽象Schema类型、可以与持久化字段和关系进行计算的类型、以及文字类型。
实体的抽象Schema类型来自实体类和由java注解符(或XML配置)提供的元语信息。
非正式情况下,实体的抽象Schema类型可以有以下特征:
l 对实体类的每一个持久化字段或者getter方法(对于持久化属性)来说,它有一个字段(“状态字段”),这个字段的抽象Schema类型和这个字段类型或getter方法的返回值的类型一致。
l 对实体类的每一个持久化关系字段或它的getter方法来说(对于持久化关系属性),它有一个字段(“关联字段”),这个关联字段的类型是关联实体的抽象Schema类型(或者,如果关系是一对多或多对多,那么它的类型是相关实体的抽象Schema类型的集合)。
抽象Schema类型是数据模型专有的类型。所以持久化提供商可以不实现它,否则需要持久化提供商需要具体化一个抽象Schema类型。
一个EJB QL查询的域由定义在同一个持久化单元内的所有实体的抽象Schema类型组成。
查询的域可以通过实体的关系navigability来限定。一个实体的抽象Schema类型的关系字段决定了navigability。如果使用关系字段和他们的值,那么查询可以查询相关的实体,以及可以在查询中使用他们的抽象Schema类型。
通过实体的名字可以在查询语句内指派实体。通过Entity注释符的name元素可以定义实体的名字(或者通过XML的entity-name元素),缺省是实体类的简单名字。实体的名字在持久化单元内必须唯一。
这个例子假定应用开发者提供了几个实体类,分别是订单、产品、订单明细、托运地址和账单地址。他们的抽象Schema类型分别是Order、Product、LineItem、ShippingAddress和BillingAddress。这些实体逻辑上在同一个持久化单元内,如下图所示:
上图的几个实体和抽象持久化Schema一起定义在同一个持久化单元内。
实体ShippingAddress和BillingAddress和Order之间都是一对多的关系。在Order和LineItem之间也是一对多的关系。实体LineItem和Product是多对一的关系。
查询订单的查询语句可以通过关联字段和状态字段Order和LineItem来遍历。查询所有带明细的订单可以写成下面这种形式:
SELECT DISTINCT o
FROM Order AS o JOIN o.lineItems AS l
WHERE l.shipped = FALSE
查询通过Order的关联字段lineItems去查找所有的订单明细,然后使用LineItem的shipped字段去过滤那些还没有完全被托运的订单。(注意:这个查询没有查询那些没有订单明细的订单)。
尽管预定了一些保留标识,如DISTINCT、FROM、AS、JOIN、WHERE和FALSE,且在这个例子中用大写,但保留标识是不区分大小写的。
这个例子中的SELECT语句设定了查询的返回值是Order类型。
由于在同一个持久化单元定义了相关实体的抽象持久化Schema,所以开发者也可以指定一个使用Product的抽象Schema类型来查询订单的查询。因此,就会使用到抽象Schema类型Order和Product的状态字段和关联字段。例如,如果抽象Schema类型Product有一个名字为productType的状态字段,那么一个查询可以用这个字段来定义查询订单的查询。这个查询可以用于查找产品类型为供应办公室产品的所有订单。这个查询可以如下:
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l JOIN l.product p
WHERE p.productType =’office_supplies’
因为Order是通过LineItem关联到Product的,所以使用lineItems和product关联字段来定义查询。这个查询使用抽象Schema的名字Order来指定,Order名字指出了查询使用的抽象Schema类型。通过抽象Schema类型Order和LineItem的关联字段lineItems和product实现了抽象Schema类型的连接。
1.4    FROM子句和连接声明
通过声明标识变量,FROM子句定义了查询的域。标识变量是声明在查询的FROM子句中的唯一标识。路径表达式可以用于限制查询域。
标识变量用于标识一个特定实体抽象Schema类型的所有实例。FROM子句可以包含多个标识变量,这些表示变量用“,”分开。
from_clause ::=
FROM identification_variable_declaration
{, {identification_variable_declaration | collection_member_declaration}}*
identification_variable_declaration ::= range_variable_declaration { join | fetch_join }*
range_variable_declaration ::= abstract_schema_name [
AS] identification_variable
join ::= join_spec join_association_path_expression [AS] identification_variable
fetch_join ::= join_specFETCHjoin_association_path_expression
join_association_path_expression ::= join_collection_valued_path_expression |
join_single_valued_association_path_expression
join_spec::= [LEFT[OUTER]|INNER]JOIN
collection_member_declaration ::=
IN (collection_valued_path_expression) [AS] identification_variable
下面的几节来讨论在FROM子句中使用的结构。
一个标识符是一个无限长的字符串。这个字符串必须以java标识符的开始字符开始,并且所有其他字符必须是java标识符其余部分允许的字符(译者注:就是符合java标识符的规范)。标识符的第一个字符可以是Character.isJavaIdentifierStart()方法返回true的任何字符。包括下划线(_)和美元($)符号。标识符的其他部分可以是Character.isJavaIdentifierPart()方法返回true的任何字符。问号(?)被java持久化语言保留了。
以下是保留的标识符:SELECT, FROM, WHERE, UPDATE, DELETE,JOIN, OUTER, INNER, LEFT, GROUP, BY, HAVING, FETCH, DISTINCT, OBJECT, NULL, TRUE,FALSE, NOT, AND, OR, BETWEEN, LIKE, IN, AS, UNKNOWN(将来使用,现在被保留), EMPTY, MEMBER, OF, IS, AVG,MAX, MIN, SUM, COUNT, ORDER, BY, ASC, DESC, MOD, UPPER, LOWER, TRIM, POSITION,CHARACTER_LENGTH, CHAR_LENGTH, BIT_LENGTH, CURRENT_TIME, CURRENT_DATE,CURRENT_TIMESTAMP, NEW, EXISTS, ALL, ANY, SOME。
保留字不区分大小写。这些保留字不能用于声明表示变量标识符。
建议:SQL 的保留字也不要使用,因为这些保留字在将来版本中也可能成为这个规范的保留字。
标识变量是一个在FROM子句中声明的有效的标识符。
所有的标识变量必须声明在FROM子句中,不能在其他子句中声明变量。
标识变量不能是保留字,或者与同一个持久化单元内的实体名称相同。
标识变量是大小写敏感的。
标识变量是声明变量的表达式的类型的值。例如,对于前面的查询:
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l JOIN l.product p
WHERE p.productType = ‘office_supplies’
在FROM子句中声明o.lineItems l,标识变量l是直接从Order得到的LineItem的值。关联字段lineItems是抽象Schema类型LineItem实例的集合,并且标识变量l指向这个集合内的一个元素。l的类型是LineItem的抽象Schema类型。
标识变量总是指向一个对单值的引用。有三种途径来声明标识变量:在范围变量声明内,在join语句内或者在一个集合成员声明内。标识变量在FROM子句内按照从左到右的顺序计算,且一个标识变量可以作为上一个标识变量的查询结果。
声明标识变量为范围变量的语法类似于SQL的语法;不同的是,AS关键字是可选的。
range_variable_declaration::=abstract_schema_name [AS] identification_variable
范围变量声明可以让开发者为多个对象指明一个根,这些对象可能无法通过遍历获得。
为了通过比较一个实体抽象Schema类型的多个实例来获得查询结果,则需要在FROM子句内为同一个实体抽象Schema类型声明多个标识变量来确定范围。
下面的查询语句返回比Joh Smith订单数多的订单。这个例子说明了如何在FROM子句内使用不同的标识变量,这两个不同的标识变量的抽象Schema类型都是Order。查询的SELECT语句决定了返回的结果是订单数比John Smith订单多的订单。
SELECT DISTINCT o1
FROM Order o1, Order o2
WHERE o1.quantity > o2.quantity AND
o2.customer.lastname = ‘Smith’  AND
o2.customer.firstname= ‘John’
标识变量后跟“.”加上状态字段或关联字段构成路径表达式。路径表达式的类型就是导航结果的类型。也就是说,状态字段或关联字段的类型就是路径表达式的类型。
依靠导航,指向关联字段的路径表达式可以被进一步组合。如果源路径表达式的结果是单值类型(不是集合),那么路径表达式可以由多个单值路径表达式组合而成。
路径表达式导航可以使用“inner join”语义来组合。也就是说,如果在路径表达式中的非终点关联字段的值不是null,那么这个路径可以被认为是没有值,并且不影响查询结果。
单值路径表达式和集合值路径表达式的语法如下所示:
single_valued_path_expression ::=
state_field_path_expression | single_valued_association_path_expression
state_field_path_expression ::=
{identification_variable | single_valued_association_path_expression}.state_field
single_valued_association_path_expression ::=
identification_variable.{single_valued_association_field.}*single_valued_association_field
collection_valued_path_expression ::=
identification_variable.{single_valued_association_field.}*collection_valued_association_field
state_field ::= {embedded_class_state_field.}*simple_state_field
Single_valued_association_field用于指明在一对一或多对一关系中关联字段的名字。Single_valued_association_field的类型和single_valued_association_path_expression都是都是关联实体的抽象Schema类型。
Collection_valued_association_field用于指明在一对多或多对多关系中关联字段的名称。Collection_valued_association_field的类型是关联实体的抽象Schema类型的值的集合。
Embedded_class_field指实体中指向被嵌入类的状态字段的名字。
导航到关联实体则会产生关联实体的抽象Schema类型的值。
对状态字段内的终端路径表达式的计算会产生一个与这个状态字段的Java类型对应的抽象Schema类型。(就是会实例化一个这个字段的类型的对象)。
在语法上,不能使用由结果是集合的路径表达式组成的路径表达式。例如,如果o指向Oreder,路径表达式o.lineItems.product就是错误的。由于导航到lineItems的结果是一个集合。为了处理这种导航,必须在FROM子句内声明一个标识变量指向lineItems集合内的元素,然后在WHERE子句内用另外一个路径表达式遍历这个元素。如下所示:
SELECT DISTINCT l.product FROM Order AS o, IN(o.lineItems) l
内连接(inner join)是可以通过在FROM子句内使用笛卡尔积(即不写就是内连接),并且在WHERE子句内增加连接条件的方式来隐式地指定。如果不使用条件限定,则是所有的笛卡尔积。
内连接通常用于关联条件不涉及到外键关联的情况(即关联条件中字段对应的字段属性间没有关联关系)。
例子:
select c from Customer c, Employee e where c.hatsize = e.shoesize
一般情况下,内连接的这种风格(也称为theta-join)很少在实体内显式定义实体关系。
显式连接定义的语法如下:
join ::= join_spec join_association_path_expression [AS] identification_variable
fetch_join ::= join_spec FETCH join_association_path_expression
join_association_path_expression ::= join_collection_valued_path_expression |
join_single_valued_association_path_expression
join_spec::= [LEFT[OUTER]|INNER]JOIN
支持下述的内连接和外连接类型。
内连接操作的语法如下:
[INNER]JOINjoin_association_path_expression [AS] identification_variable
例如,下面的查询基于客户和订单的关系进行连接。这种连接等同与数据库中的外键关系。
SELECT c FROM Customer c JOIN c.orders o WHERE c.status = 1
可以不用关键字INNER,不用就是INNER连接。
SELECT c FROM Customer c INNER JOIN c.orders o WHERE c.status = 1
上面的语句等同于早期使用IN结构的查询语句(在EJB2.0中规定的),如下所示。下例是查询所有状态为1且至少有一个订单的客户:
SELECT OBJECT(c) FROM Customer c, IN(c.orders) o WHERE c.status = 1
LEFT JOIN和LEFT OUTER JOIN是相同的。它们用于在连接条件内匹配的值缺少的情况下仍然可以查询到结果。
语法如下:
LEFT[OUTER] JOIN join_association_path_expression [AS] identification_variable
例如:
SELECT c FROM Customer c LEFT JOIN c.orders o WHERE c.status = 1
可以没有OUTER关键字。
SELECT c FROM Customer c LEFT OUTER JOIN c.orderso WHERE c.status=1
左连接一个重要的用途就是可以预先读取关联数据项作为查询的附加结果。这可以通过将LEFT JOIN指定为FETCH JOIN来实现。
FETCH JOIN用于在执行查询的时候顺便将关联数据项读取。FETCH JOIN指定在实体和它的关联实体上。
语法如下:
fetch_join ::= [LEFT[OUTER]|INNER] JOIN FETCH join_association_path_expression
FETCH JOIN语句的右边引用的关系必须属于查询结果的实体。FETCH JOIN语句右边引用的实体不能有标识变量,因此,对隐式fetched的实体的引用不能出现在查询语句的其他地方。
下面的查询返会一个部门的集合。附带的,这些部门关联的雇员也将被查询出来,尽管在查询结果中没有显式的指定它们。被同时查出的雇员的持久化字段或属性也都被初始化。是否初始化雇员的关联属性需要根据Employee实体类的元语来决定。
SELECT d
FROM Department d LEFT JOIN FETCH d.employees
WHERE d.deptno = 1
除了连接操作右端指定的关联对象不在查询结果内或者在查询中没有被引用以外,Fetch连接的语义与对应的内连接或外连接的语义相同。因此,例如,如果部门l由5个雇员,则上面的查询返回5个对部门l实体的引用。
由collection_member_declaration声明的标识变量指向通过路径表达式导航获得的集合的值。这种路径表达式代表了一个涉及实体抽象Schema类型的关系字段的导航。由于一个路径表达式可以基于另外一个路径表达式,所以这种导航用于关联实体的关联字段。
用一个特定的操作来声明集合成员声明的标识变量,这个保留字是IN。IN操作的参数是值是集合的路径表达式。这个路径表达式将导航结果放入实体抽象Schema类型的值是集合的关系字段中。
声明集合成员标识变量的语法如下:
collection_member_declaration ::=
IN (collection_valued_path_expression) [AS] identification_variable
例如,查询:
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l JOIN l.product p
WHERE p.productType = ‘office_supplies’
等同于下面用IN的查询:
SELECT DISTINCT o
FROM Order o, IN(o.lineItems) l
WHERE l.product.productType = ‘office_supplies’
在这个例子中,lineItems是关联字段的名字,这个关联字段的值是LineItem实例的集合。标识变量l指向这个集合的成员,即一个单个LineItem实例。在这个例子中,o是Order的标识变量。
1.4.7    FROM语句和SQL
Java持久化查询语言把FROM子句和SQL看作是相似的是因为声明的标识变量影响查询结果,即使它们没有在WHERE语句中使用。应用开发者应该谨慎定义标识变量,因为查询域可能会依赖声明的类型是否有值。
例如,下例的FROM语句用于查询所有有明细且产品存在的订单。如果在数据库中没有Product实例,那么查询域就是空的,同时也不会查询出订单。
SELECT o
FROM Order AS o, IN(o.lineItems) l, Product p
Java持久化查询自动是多义性的。查询的FROM子句不仅指向显式指定的特定实体的实例,而且也指向它的子类。查询的结果包含满足条件的子类的实例。(注:这在EJB2.0中是不支持的,由于EJB2.0不支持继承。)
查询的WHERE语句由条件表达式组成,这些条件表达式用于选择满足表达式的对象或值。WHERE语句用于限制选择语句的结果或者用于限制更新或删除操作的范围。
WHERE语句的语法如下:
where_clause ::=WHERE conditional_expression
GROUP BY用于根据实体的属性对值进行分组。HAVING用于在组上进一步限制查询结果。
HAVING的语法如下:
having_clause ::=HAVING conditional_expression
GROUP BY和HAVING在3.7节中作进一步的讨论。
以下章节描述可以用在WHERE或HAVING语句内的条件表达式的语法结构。
在可移植的应用中,不要在条件表达式中使用那些映射为序列化形式或作为blob 的状态字段。(注:不期望持久化实现能够在内存中执行带有这种字段的查询语句,而是要在数据库中执行)
字符串是用单引号‘’括住的——例如,‘literal’。带有单引号的字符串需要用单引号转义——例如,‘literal’’s’。在查询中的字符串类似于Java的String使用unicode字符集编码。在查询的字符串语法中不支持java的转义符。
精确数值支持java的整型和SQL的整型数值语法。
近似数值支持java的浮点数以及SQL的近似数值语法。
枚举支持java的枚举语法。但必须指定枚举类。
为了和java语言规范保持一致,可以在数值后使用用适当的后缀来表示特定的数值类型。在本规范中不要求支持十六进制和八进制。
Booolean是TRUE和FALSE。
所有预定义的保留字都是不区分大小写的。
正如在3.4.2章节中所述,所有在SELECT或DELECT语句内的WHERE或HAVING语句中使用的标识变量必须在FROM语句内声明。同样,在UPDATE语句内的WHERE语句中使用的标识变量也必须在UPDATE语句内声明。
在WHERE和HAVING语句内使用的标识变量必需是可量化的。意思是,这个标识变量代表的是实体抽象Schema类型实例或是一个集合的成员。标识变量从来都不会指向一个集合。
除了在empty_collection_comparison_expression、collection_memeber_expression或作为SIZE操作的参数外,不能在WHERE和HAVING的条件表达式中使用collection_valued_path_expression。
可以使用位置和命名参数。在同一个查询语句内不可以同时使用位置参数和命名参数。
入参只能在查询语句的WHERE或HAVING语句内使用。
注意:如果入参的值是null ,涉及到入参的比较运算或数学运算将返回一个不知道的值。参见3.11
位置参数需遵循以下规则:
l 在整数前使用?表示入参。如,?1。
l 入参的序号从1开始。
注意:同一个参数可以在查询语句内使用多次,而且参数的使用顺序可以和位置参数的顺序不一致。
命名参数以“:”为前缀。它遵循在3.4.1章节中描述的规则。命名参数是大小写敏感的。
例如:
SELECT c
FROM Customer c
WHERE c.status = :stat
在2.6.1章节内讲述了绑定当命名参数的API。
条件表达是可以由其他条件表达式、比较操作、逻辑操作、结果值是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章节。
下面列出的操作符的优先级是依次降低的:
l 导航操作符( .)
l 数学运算符
n +,- 一元运算符
n *,/
n +,- 两元的加和减
l 比较运算符:=,>,>=,<,<=,<>,[NOT] BETWEEN,[NOT] LIKE,[NOT] IN,IS [NOT] NULL,IS [NOT] EMPTY,[NOT] MEMBER [OF]
l 逻辑运算符
n NOT
n AND
n OR
下面的章节介绍在特定表达式内使用的操作符。
在条件表达式内使用的[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
1.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或未知,那么整个表达式的值就是未知的。
1.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》,它对这些规则有精确的定义)
例如:
l address.phone LIKE ‘12%3’ is true for ‘123’  ‘12993’ and false for ‘1234’
l asentence.word LIKE ‘l_se’ is true for ‘lose’ and false for ‘loose’
l aword.underscored LIKE ‘/_%’ ESCAPE ‘/’ is true for ‘_foo’ and false for ‘bar’
l 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表达式的值就是未知的。
1.6.10   NULL比较表达式
在条件表达式中的 [NOT] IS NULL表达式的语法如下:
{single_valued_path_expression | input_parameter } IS [NOT] NULL
空比较表达式用于检查单值路径表达式或入参是否是NULL值。
1.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
如果在一个空集合比较表达式中的值是集合的路径表达式的值是未知的,那么空比较表达式的值就是未知的。
在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或未知,那么这个集合成员表达式的值也是未知的。
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)
上例中查询的结果由所有职员的配偶也是职员的记录组成。
1.6.14   ALL或ANY表达式
ALL条件表达式是一个谓词。如果所有的值都在子查询的结果内或子查询的结果为空,那么ALL表达式就是true。如果比较的结果只要有一行是false,则ALL条件表达式就是false,并且如果既不是true又不是false,那就是未知。
ANY条件表达式也是谓词。如果对子查询结果内的某些值的比较操作是true ,那么ANY条件表达式就是true。如果子查询的结果是空或与子查询结果的每一个值比较都是false,那么ANY条件表达式的值就是false,并且如果既不是true又不是false,那就是未知。关键字SOME和ANY是同义词。
和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)
可以在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)
Java持久化查询语言有以下内置的函数,这些函数可以在WHERE或HAVING语句内使用。
如果函数表达式的参数值是null或未知,那么函数的值就是未知的。
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]) |
CONCAT函数将两个字符串连接成一个字符串。
SUBSTRING函数的第二个和第三个参数表示子串开始的位置和子串的长度。这两个参数都是整数。字符串的第一个位置是1. SUBSTRING返回一个子串。
TRIM函数用于从字符串内剪切指定的字符。如果没有指定要剪切的字符,那么这个字符假定是空格。Trim_character是可选的,它是一个只有一个字符的字符串或是一个字符(也就是char或Character)(注:注意,不是所有的数据库都支持任意字符剪切,有的只支持空格,指定剪切字符可能使应用不可移植)。如果没有提供剪切规范(trim_specification),则假定是BOTH。TRIM函数返回被剪切后的字符串。
LOWER和UPPER函数用于将字符串转换成大写或小写。它们返回转换后的字符串。
LOCATE函数返回给定字符串在字符串中的位置,从给定的位置开始向后搜索。它以整数形式返回搜索到的第一个给定字符串的位置。第一个参数是用于定位的被搜索的字符串;第二个参数用于搜索的字符串;第三个参数是可选的,它指定从哪个位置开始搜索(缺省情况下,从被搜索的字符串的开始位置开始搜索)。字符串的第一个位置是1. 如果没有搜索的要搜索的字符窜,则返回0。(注:注意,不是所有的数据库都支持LOCATE的第三个参数;使用这个参数可能导致应用的不可移植性)
LENGTH函数返回字符串的长度。
functions_returning_numerics::=
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的原始数值类型。
1.6.16.3     时间函数
functions_returning_datetime:=
CURRENT_DATE |
CURRENT_TIME |
CURRENT_TIMESTAMP
时间函数返回数据库服务器的当前日期、时间和时间戳。
GROUP BY用于根据一系列属性组合值。HAVING用于在GROUP BY上进一步限定查询结果。
GROUP BY和HAVING语句的语法如下:
groupby_clause ::=GROUP BYgroupby_item {, groupby_item}*
groupby_item ::= single_valued_path_expression | identification_variable
having_clause ::=HAVINGconditional_expression
如果查询同时有WHERE语句和GROUP BY语句,则查询过程就是,首先应用WHERE语句,然后组织组并根据HAVING语句过滤这些组。HAVING语句将保留那些满足HAVING语句条件的组。
对于使用GROUP BY的SELECT语句的要求就是:出现在SELECT语句内的任何项(除了合计函数的参数)必须在GROUP BY中出现。当组织组时,null值也被看作是一个组。
允许按实体进行分组。在这种情况下,实体必须不能包含已序列化的状态字段或lob字段。
HAVING语句必须基于分组的项或使用分组项的合计函数指定查询条件。
如果没有使用GROUP BY和HAVING,那么查询结果认为是一个组,并且select的结果列表只能由合计函数组成。不要求持久化实现支持没有GROUP BY但有HAVING的情况。可移植应用不应当依赖于没有GROUP BY但有HAVING的实现。
例如:
SELECT c.status, avg(c.filledOrderCount), count(c)
FROM Customer c
GROUP BY c.status
HAVING c.status IN (1, 2)
 
SELECT c.country, COUNT(c)
FROM Customer c
GROUP BY c.country
HAVING COUNT(c.country) > 3
SELECT语句用于声明查询的结果。SELECT语句可以返回多个值。
SELECT语句可以包含一到多个下面的元素:单值变量或一个指向实体抽象Schema的单值标识变量,单值路径表达式,合计选择表达式和构造器表达式。
SELECT的语法如下:
select_clause ::=SELECT [DISTINCT] select_expression {, select_expression}*
select_expression ::=
single_valued_path_expression |
aggregate_expression |
identification_variable |
OBJECT(identification_variable)|
constructor_expression
constructor_expression ::=
NEWconstructor_name( constructor_item {, constructor_item}*)
constructor_item ::= single_valued_path_expression | aggregate_expression
aggregate_expression ::=
{AVG |MAX |MIN |SUM }([DISTINCT] state_field_path_expression) |
COUNT ([DISTINCT] identification_variable | state_field_path_expression |
single_valued_association_path_expression)
例如:
SELECT c.id, c.status
FROM Customer c JOIN c.orders o
WHERE o.count > 100
注意,SELECT语句必须被指定只返回单值表达式。下面的语句就是无效的:
SELECT o.lineItems FROM Order AS o
DISTINCT关键字用于去除重复的查询结果。如果没有指定DISTINCT,则不去掉重复值。
在SELECT语句中独立的标识变量可以不使用OBJECT操作限定。SELECT语句不必使用OBJECT操作符去限定路径表达式。
1.8.1    SELECT语句的结果类型
由查询语句内的SELECT 语句指定的查询结果的类型就是实体的抽象Schema 类型,状态字段类型,合计函数的结果,构造操作的结果,或者是这些类型的组合。
SELECT 语句的结果类型由select_expressions 的结果类型定义。当在SELECT 语句内使用多个select_expressions 时,查询结果是Object[] 类型,并且在结果数组中元素的顺序和这些表达式在SELECZT 语句中指定的顺序一致,同时类型和select_expressions 的类型相对应。
Select_expressions 的结果类型如下:
l 是一个single_valued_path_expression ,它是一个state_field_path_expression 。它的结果是一个对象,这个对象的类型和实体的状态字段的类型一致。如果这个状态字段的类型是原始类型,那么返回对应的对象类型。
l 是一个single_valued_path_expression ,它是一个single_valued_associate_path_expression 。它的结果是一个实体对象,这个对象的类型和实体对象的关系字段的类型或关系字段的子类型,这个类型由O/R 映射确定。
l 是一个Identification_variable 的结果类型。这个类型是标识变量对应的实体类型或它的子类型,由O/R 映射确定。
l 是一个aggreate_expression 的结果类型,这个类型在3.8.4 章节中描述。
l 是一个consturctor_expression 的结果类型,这个类型是类的构造器的类型。构造器内的参数的类型根据上述规则确定。
1.8.2    SELECT语句内的构造器表达式
可以在SELECT列表内使用构造器,以便能一个或多个java实例。这个类可以不是实体或可以和数据库没有映射。但是,构造器名称必须是全称。
如果在SELECT NEW语句内使用实体类的名称,则查询的结果中实体实例的状态是new。
SELECT NEW com.acme.example.CustomerDetails(c.id, c.status, o.count)
FROM Customer c JOIN c.orders o
WHERE o.count > 100
如果与关联字段或状态字段相对应的查询结果值是null,那么查询方法的返回值就是null。IS NOT NULL指令用于从查询结果内去除这些null值。
但是要注意,根据java的数字类型定义的状态字段类型在查询结果内不能产生出NULL值(即原始数值类型的值不会是null)。返回这些字段的查询不必返回null值。
1.8.4    SELECT语句内的合计函数
查询的结果可以是使用路径表达式的合计函数的结果。
在SELECT语句内可以使用以下合计函数:AVG,COUNT,MAX,MIN,SUM。
除了COUNT外,作为合计函数参数的路径表达式的最后必须是状态字段。作为COUNT函数参数的路径表达式的最后可以是状态字段,也可以是关联字段,还可以是标识变量。
SUM和AVG函数的参数必须是数字。MAX和MIN函数的参数的类型和可排序的状态字段类型一致(也就是,数字类型,字符串类型,字符类型或日期类型)。
包含在使用合计函数的查询结果内的java类型有:
l COUNT返回Long
l MAX,MIN返回使用的状态字段的类型。
l AVG返回Double
l 当状态字段是整型(不是BigInteger)时,SUM返回Long;当状态字段是浮点类型时,SUM返回Double;当状态字段类型是BigInteger时,SUM返回BigInteger;当状态字段类型是BigDecimal时,SUM返回BigDecimal。
如果使用SUM,AVG,MAX或MIN,但没有参数值,那么合计函数的结果就是NULL。
如果使用COUNT,但没有参数值,那么合计的结果就是0.
可以在合计函数的参数前加关键字DISTINCT来指定在合计之前去除重复值。(注:可以在MAX或MIN中使用DISTINCT,但不影响结果)
在执行合计函数之前会将Null值去除,无论是否使用DISTINCT关键字。
下面的例子返回平均的的订单数量:
SELECT AVG(o.quantity) FROM Order o
下面的查询返回John Smith订购的所有物品的总金额:
SELECT SUM(l.price)
FROM Order o JOIN o.lineItems l JOIN o.customer c
WHERE c.lastname = ‘Smith’  AND c.firstname = ‘John’
下面的查询返回订单总数:
SELECT COUNT(o)
FROM Order o
下面的查询计算John Smith的订单中所有给定价格的物品数量:
SELECT COUNT(l.price)
FROM Order o JOIN o.lineItems l JOIN o.customer c
WHERE c.lastname = ‘Smith’  AND c.firstname = ‘John’
注意:上面的查询等价于:
SELECT COUNT(l)
FROM Order o JOIN o.lineItems l JOIN o.customer c
WHERE c.lastname = ‘Smith’  AND c.firstname = ‘John’
AND l.price IS NOT NULL
ORDER BY用于对查询结果或对象进行排序。
语法如下:
orderby_clause ::=ORDER BY orderby_item {, orderby_item}*
orderby_item ::= state_field_path_expression [ASC | DESC]
当在查询中使用ORDER BY语句时,SELECT中的元素必须是下列元素之一:
l 标识变量x,也可以表示为OBJECT(x)
l 一个single_valued_association_path_expression
l 一个state_field_path_expression
对于前两种情况,每一个orderby_item必须是由SELECT语句返回的抽象schema值的可排序状态字段。对于第三种情况,orderby_item必须和SELECT语句中的state_path_expression是同一抽象schema类型的相同字段。
例如,下面的前两个查询是正确的,但第三和第四两个是错误的:
SELECT o
FROM Customer c JOIN c.orders o JOIN c.address a
WHERE a.state = ‘CA’
ORDER BY o.quantity, o.totalcost
SELECT o.quantity, a.zipcode
FROM Customer c JOIN c.orders o JOIN c.address a
WHERE a.state = ‘CA’
ORDER BY o.quantity, a.zipcode
下面的两个查询是不正确的,因为orderby_item不是SELECT中的元素。
SELECT p.product_name
FROM Order o JOIN o.lineItems l JOIN l.product p JOIN o.customer c
WHERE c.lastname = ‘Smith’  AND c.firstname = ‘John’
ORDER BY p.price
 
SELECT p.product_name
FROM Order o, IN(o.lineItems) l JOIN o.customer c
WHERE c.lastname = ‘Smith’  AND c.firstname = ‘John’
ORDER BY o.quantity
如果指定多个orderby_item,orderby_item元素从左到右的顺序决定了排序的优先顺序,因此,最左边的orderby_item的优先级最高。
关键字ASC指明使用升序排列;关键字DESC指明使用降序排列。缺省是升序排列。
对于null值的SQL排序规则是:所有的空值出现在非空值之前或所有的空值出现在非空值之后,但没有规定使用哪一个。
如果使用ORDER BY,那么查询结果的顺序会被预先保存在查询方法的结果内。
批量更新和删除应用与单个实体类的实体(如果可能,可以包括它的子类)。在FROM 或UPDATE 语句中只能指定一个实体抽象Schema 类型。
批量更新和删除的语法如下:
update_statement ::= update_clause [where_clause]
update_clause ::=UPDATE abstract_schema_name [[AS] identification_variable]
SET update_item {, update_item}*
update_item ::= [identification_variable.]{state_field | single_valued_association_field}=new_value
new_value ::=
simple_arithmetic_expression |
string_primary |
datetime_primary |
boolean_primary |
enum_primary
simple_entity_expression |
NULL
 
delete_statement ::= delete_clause [where_clause]
delete_clause ::=
DELETEFROM abstract_schema_name [[AS] identification_variable]
WHERE 语句的语法在3.5 章节中描述。
删除操作只应用与指定类和它的子类的实体上,不会层级到相关的实体。
更新操作中指定的新值在类型上必须和它被赋予的状态字段的类型一致。
批量更新绕过乐观锁检查直接映射到数据库的更新操作上。可移植应用必须手动更新版本列的值,如果希望验证版本列的值,也需要手工验证。
持久化上下文不与批量更新和删除的结果同步。
执行批量更新或删除时应当非常小心,因为它们会引起数据库和活动持久化上下文中实体的不一致。通常情况下,批量更新和删除操作只应当在一个单独的事务中或在实体的开始处执行(在实体已经读取之前,实体的状态可能已经被这些操作改变了)。
例子:
DELETE
FROM Customer c
WHERE c.status = ‘inactive’
DELETE
FROM Customer c
WHERE c.status = ‘inactive’
 AND c.orders IS EMPTY
UPDATE customer c
SET c.status = ‘outstanding’
WHERE c.balance < 10000
 AND 1000 > (SELECT COUNT(o)
                FROM customer cust JOIN cust.order o)
当引用的目标对象在数据库中不存在时,它的值被认为是NULL,SQL92中NULL语法定义了包含NULL值的条件表达式的计算方法。
下面是这些语法的简要描述:
l 用NULL值进行的比较或算术运算的结果总是未知的值。
l 两个NULL值是不相等的,比较的结果是未知的。
l 对未知值进行比较或算术运算的结果仍然是未知的。
l IS NULL和IS NOT NULL操作将NULL状态字段或单值关系字段的值转换为TRUE或FALSE。
l Boolean操作使用三个值逻辑,分别定义在Table1,Table2和Table3.
 
Table1 AND操作符的定义
AND
T
F
U
T
T
F
U
F
F
F
F
U
U
F
U
 
Table2 OR操作的定义
OR
T
F
U
T
T
T
T
F
T
F
U
U
T
U
U
 
Table3 NOT操作的定义
NOT
 
T
F
F
T
U
U
 
注意:Java 持久化语言定义了空串‘’,它不等于NULL 值,只是字符串的长度为0. 然而,对某些数据库,NULL 值和空串没有严格区分。因此,应用开发者不应当依赖涉及空串和NULL 值的比较语法。
只允许相似类型的值进行比较。相似类型是指两个类型是同一个java类型或者一个原始类型,另一个是原始封装类型那么两个类型(例如,int和Integer)。这个规则有一个特殊情况:比较那些遵循数值转换规则的数值类型总是有效的。除了数值类型外条件表达是不允许比较非相似的类型。
注意,允许类型为原始封装类型的状态字段和入参上使用算术操作和比较操作。
当同一个抽象Schema类型的两个实体有且只有相同的主键值时,那么他们才是相等的。
只要求支持对枚举进行相等或不等的比较。
下面的例子解释Java持久化查询语言的语法和语义。这些例子基于3.3.2章节的例子。
查询所有的订单:
SELECT o
FROM Order o
查找所有需要托运到加利福尼亚的订单:
SELECT o
FROM Order o
WHERE o.shippingAddress.state = ‘CA’
Find all states for which there are orders:
SELECT DISTINCT o.shippingAddress.state
FROM Order o
查询所有有订单明细的订单:
SELECT DISTINCT o
FROM Order o, IN(o.lineItems) l
注意,这个查询的结果不包括那些没有订单明细的订单。这个查询也可以写作:
查询所有没有订单明细的订单:
SELECT o
FROM Order o
WHERE o.lineItems IS NOT EMPTY
查询所有没有明细的订单:
SELECT o
FROM Order o
WHERE o.lineItems IS EMPTY
查询所有未确定的订单:
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l
WHERE l.shipped = FALSE
查询那些托运地址和订单地址不同的订单。这个例子假定应用开发者使用两个不同的实体类型来描述托运地址和订单地址:
SELECT o
FROM Order o
WHERE
NOT (o.shippingAddress.state = o.billingAddress.state AND
 o.shippingAddress.city = o.billingAddress.city AND
 o.shippingAddress.street = o.billingAddress.street)
如果应用开发者在一个实体内使用两个不同的关系来表示托运地址和订单地址,上面的表达式就可以根据在3.12章节内定义的相等规则做简化。查询如下:
SELECT o
FROM Order o
WHERE o.shippingAddress <> o.billingAddress
这个查询检查是否同一个实体抽象Schema类型实例(用主键标识)通过两个不同的关系被关联到一个订单。
查询订购了书名为“Appling Enterprise JavaBean: Component-Base Development for the J2EE Platform”的书的所有订单:
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l
WHERE l.product.type = ‘book ‘ AND
l.product.name = ‘Applying Enterprise JavaBeans
Component-Based Development for the J2EE Platform’
下面的查询查找产品名称等于输入参数的订单:
SELECT DISTINCT o
FROM Order o, IN(o.lineItems) l
WHERE l.product.name = ?1
对于上面的查询,输入参数必须是和状态字段的类型一致,例如,一个字符串。
BNF符号总览:
l { ... } grouping
l [ ... ] optional constructs
l boldface keywords
l *zero or more
l |alternates
下面是java持久化查询语言的BNF:
QL_statement ::= select_statement | update_statement | delete_statement
select_statement ::= select_clause from_clause [where_clause] [groupby_clause]
[having_clause] [orderby_clause]
update_statement ::= update_clause [where_clause]
delete_statement ::= delete_clause [where_clause]
from_clause ::=
FROM identification_variable_declaration
{, {identification_variable_declaration | collection_member_declaration}}*
identification_variable_declaration ::= range_variable_declaration { join | fetch_join }*
range_variable_declaration ::= abstract_schema_name [AS] identification_variable
join ::= join_spec join_association_path_expression [AS] identification_variable
fetch_join ::= join_specFETCHjoin_association_path_expression
association_path_expression ::=
collection_valued_path_expression | single_valued_association_path_expression
join_spec::= [LEFT[OUTER]|INNER]JOIN
join_association_path_expression ::= join_collection_valued_path_expression |
join_single_valued_association_path_expression
join_collection_valued_path_expression::=
identification_variable.collection_valued_association_field
join_single_valued_association_path_expression::=
identification_variable.single_valued_association_field
collection_member_declaration ::=
IN (collection_valued_path_expression) [AS] identification_variable
single_valued_path_expression ::=
state_field_path_expression | single_valued_association_path_expression
state_field_path_expression ::=
{identification_variable | single_valued_association_path_expression}.state_field
single_valued_association_path_expression ::=
identification_variable.{single_valued_association_field.}* single_valued_association_field
collection_valued_path_expression ::=
identification_variable.{single_valued_association_field.}*collection_valued_association_field
state_field ::= {embedded_class_state_field.}*simple_state_field
update_clause ::=
UPDATE abstract_schema_name [[AS] identification_variable]
SET update_item {, update_item}*
update_item ::= [identification_variable.]{state_field | single_valued_association_field}=
new_value
new_value ::=
simple_arithmetic_expression |
string_primary |
datetime_primary |
boolean_primary |
enum_primary
simple_entity_expression |
NULL
delete_clause ::=DELETEFROM abstract_schema_name [[AS] identification_variable]
select_clause ::=SELECT [DISTINCT] select_expression {, select_expression}*
select_expression ::=
single_valued_path_expression |
aggregate_expression |
identification_variable |
OBJECT(identification_variable)|
constructor_expression
constructor_expression ::=
NEWconstructor_name( constructor_item {, constructor_item}*)
constructor_item ::= single_valued_path_expression | aggregate_expression
aggregate_expression ::=
{AVG |MAX |MIN |SUM }([DISTINCT] state_field_path_expression) |
COUNT ([DISTINCT] identification_variable | state_field_path_expression |
single_valued_association_path_expression)
where_clause ::=WHERE conditional_expression
groupby_clause ::=GROUP BYgroupby_item {, groupby_item}*
groupby_item ::= single_valued_path_expression | identification_variable
having_clause ::=HAVINGconditional_expression
orderby_clause ::=ORDER BYorderby_item {, orderby_item}*
orderby_item ::= state_field_path_expression [ASC |DESC ]
subquery ::= simple_select_clause subquery_from_clause [where_clause]
[groupby_clause] [having_clause]
subquery_from_clause ::=
FROMsubselect_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_clause ::=SELECT [DISTINCT] simple_select_expression
simple_select_expression::=
single_valued_path_expression |
aggregate_expression |
identification_variable
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
between_expression ::=
arithmetic_expression [NOT]BETWEEN
arithmetic_expressionAND arithmetic_expression |
string_expression [NOT]BETWEEN string_expressionAND string_expression |
datetime_expression [NOT]BETWEEN
datetime_expressionAND datetime_expression
in_expression ::=
state_field_path_expression [NOT]IN( in_item {, in_item}* | subquery)
in_item ::= literal | input_parameter
like_expression ::=
string_expression [NOT]LIKEpattern_value [ESCAPE escape_character]
null_comparison_expression ::=
IS[NOT] NULL
{single_valued_path_expression | input_parameter}
empty_collection_comparison_expression ::=
collection_valued_path_expressionIS [NOT] EMPTY
collection_member_expression ::= entity_expression
[NOT]MEMBER[OF]collection_valued_path_expression
exists_expression::= [NOT]EXISTS (subquery)
all_or_any_expression ::= {ALL |ANY |SOME}(subquery)
comparison_expression ::=
string_expressioncomparison_operator{string_expression|all_or_any_expression}|
boolean_expression {=|<>} {boolean_expression | all_or_any_expression} |
enum_expression {=|<>} {enum_expression | all_or_any_expression} |
datetime_expression comparison_operator
{datetime_expression | all_or_any_expression} |
entity_expression {= |<> } {entity_expression | all_or_any_expression} |
arithmetic_expression comparison_operator
{arithmetic_expression | all_or_any_expression}
comparison_operator ::== |> |>= |< |<= |<>
arithmetic_expression ::= simple_arithmetic_expression |(subquery)
simple_arithmetic_expression ::=
arithmetic_term | simple_arithmetic_expression {+ |- } arithmetic_term
arithmetic_term ::= arithmetic_factor | arithmetic_term {* |/ } arithmetic_factor
arithmetic_factor ::= [{+ |-}] arithmetic_primary
arithmetic_primary ::=
state_field_path_expression |
numeric_literal |
(simple_arithmetic_expression) |
input_parameter |
functions_returning_numerics |
aggregate_expression
string_expression ::= string_primary |(subquery)
string_primary ::=
state_field_path_expression |
string_literal |
input_parameter |
functions_returning_strings |
aggregate_expression
datetime_expression ::= datetime_primary |(subquery)
datetime_primary ::=
state_field_path_expression |
input_parameter |
functions_returning_datetime |
aggregate_expression
boolean_expression ::= boolean_primary |(subquery)
boolean_primary ::=
state_field_path_expression |
boolean_literal |
input_parameter |
enum_expression ::= enum_primary |(subquery)
enum_primary ::=
state_field_path_expression |
enum_literal |
input_parameter |
entity_expression ::=
single_valued_association_path_expression | simple_entity_expression
simple_entity_expression ::=
identification_variable |
input_parameter
functions_returning_numerics::=
LENGTH(string_primary)|
LOCATE(string_primary,string_primary[, simple_arithmetic_expression]) |
ABS(
simple_arithmetic_expression) |
SQRT(simple_arithmetic_expression) |
MOD(
simple_arithmetic_expression, simple_arithmetic_expression) |
SIZE(
collection_valued_path_expression)
functions_returning_datetime ::=
CURRENT_DATE|
CURRENT_TIME |
CURRENT_TIMESTAMP
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
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值