14.9. 表达式
在where
子句中允许使用的表达式包括 大多数你可以在SQL使用的表达式种类:
数学运算符
+, -, *, /
二进制比较运算符
=, >=, <=, <>, !=, like
逻辑运算符
and, or, not
in
,not in
,between
,is null
,is not null
,is empty
,is not empty
,member of
andnot member of
"简单的" case,
case ... when ... then ... else ... end
,和 "搜索" case,case when ... then ... else ... end
字符串连接符
...||...
orconcat(...,...)
current_date()
,current_time()
,current_timestamp()
second(...)
,minute(...)
,hour(...)
,day(...)
,month(...)
,year(...)
,EJB-QL 3.0定义的任何函数或操作:
substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()
coalesce()
和nullif()
str()
把数字或者时间值转换为可读的字符串cast(... as ...)
, 其第二个参数是某Hibernate类型的名字,以及extract(... from ...)
,只要ANSIcast()
和extract()
被底层数据库支持HQL
index()
函数,作用于join的有序集合的别名。HQL函数,把集合作为参数:
size(), minelement(), maxelement(), minindex(), maxindex()
,还有特别的elements()
和indices
函数,可以与数量词加以限定:some, all, exists, any, in
。任何数据库支持的SQL标量函数,比如
sign()
,trunc()
,rtrim()
,sin()
JDBC风格的参数传入
?
命名参数
:name
,:start_date
,:x1
SQL 直接常量
'foo'
,69
,6.66E+2
,'1970-01-01 10:00:01.0'
Java
public static final
类型的常量eg.Color.TABBY
关键字in
与between
可按如下方法使用:
from DomesticCat cat where cat.name between 'A' and 'B'
from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )
而且否定的格式也可以如下书写:
from DomesticCat cat where cat.name not between 'A' and 'B'
from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )
同样, 子句is null
与is not null
可以被用来测试空值(null).
在Hibernate配置文件中声明HQL“查询替代(query substitutions)”之后, 布尔表达式(Booleans)可以在其他表达式中轻松的使用:
<property name="hibernate.query.substitutions">true 1, false 0</property>
系统将该HQL转换为SQL语句时,该设置表明将用字符 1
和 0
来 取代关键字true
和 false
:
from Cat cat where cat.alive = true
你可以用特殊属性size
, 或是特殊函数size()
测试一个集合的大小。
from Cat cat where cat.kittens.size > 0
from Cat cat where size(cat.kittens) > 0
对于索引了(有序)的集合,你可以使用minindex
与 maxindex
函数来引用到最小与最大的索引序数。 同理,你可以使用minelement
与 maxelement
函数来 引用到一个基本数据类型的集合中最小与最大的元素。
from Calendar cal where maxelement(cal.holidays) > current_date
from Order order where maxindex(order.items) > 100
from Order order where minelement(order.items) > 10000
在传递一个集合的索引集或者是元素集(elements
与indices
函数) 或者传递一个子查询的结果的时候,可以使用SQL函数any, some, all, exists, in
select mother from Cat as mother, Cat as kit
where kit in elements(foo.kittens)
select p from NameList list, Person p
where p.name = some elements(list.names)
from Cat cat where exists elements(cat.kittens)
from Player p where 3 > all elements(p.scores)
from Show show where 'fizard' in indices(show.acts)
注意,在Hibernate3种,这些结构变量- size
, elements
, indices
, minindex
, maxindex
, minelement
, maxelement
- 只能在where子句中使用。
一个被索引过的(有序的)集合的元素(arrays, lists, maps)可以在其他索引中被引用(只能在where子句中):
from Order order where order.items[0].id = 1234
select person from Person person, Calendar calendar
where calendar.holidays['national day'] = person.birthDay
and person.nationality.calendar = calendar
select item from Item item, Order order
where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11
select item from Item item, Order order
where order.items[ maxindex(order.items) ] = item and order.id = 11
在[]
中的表达式甚至可以是一个算数表达式。
select item from Item item, Order order
where order.items[ size(order.items) - 1 ] = item
对于一个一对多的关联(one-to-many association)或是值的集合中的元素, HQL也提供内建的index()
函数,
select item, index(item) from Order order
join order.items item
where index(item) < 5
如果底层数据库支持标量的SQL函数,它们也可以被使用
from DomesticCat cat where upper(cat.name) like 'FRI%'
如果你还不能对所有的这些深信不疑,想想下面的查询。如果使用SQL,语句长度会增长多少,可读性会下降多少:
select cust
from Product prod,
Store store
inner join store.customers cust
where prod.name = 'widget'
and store.location.name in ( 'Melbourne', 'Sydney' )
and prod = all elements(cust.currentOrder.lineItems)
提示: 会像如下的语句
SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order
FROM customers cust,
stores store,
locations loc,
store_customers sc,
product prod
WHERE prod.name = 'widget'
AND store.loc_id = loc.id
AND loc.name IN ( 'Melbourne', 'Sydney' )
AND sc.store_id = store.id
AND sc.cust_id = cust.id
AND prod.id = ALL(
SELECT item.prod_id
FROM line_items item, orders o
WHERE item.order_id = o.id
AND cust.current_order = o.id
)