日期:2014-05-16  浏览次数:20414 次

DB2使用小结(五):使用Case语句
http://qml007.blog.163.com/blog/static/5134854200610159394453/
应用难点技巧:使用Case让你的SQL语句有条件的执行

我们在编写SQL语句时,常常遇到希望SQL能够按条件执行的情况。这里的条件不是指Where子句中的条件,而是指让DB2根据条件执行SQL的语句块。大多数情况下我们可以使用case来实现。

例如,我们希望从员工表中查出员工的工资情况,如果小于20000,则标志为low,20000到50000间为middle,否则为high。一般大家会想到先取出工资数据然后在Java代码中做判断,但我们也可以在SQL中完成上述操作。如下例:

select empno, sex, salary,

case

when salary < 20000 then 'low'

when salary >=20000 and salary <50000 then 'middle'

else 'high'

end as salaryclass

from employee


类似的,如果想在SQL语句中把性别翻译成文字,也可以用case实现,注意这两条SQL语句使用了不同的case表达式写法:

select empno,

case sex

when 'M' then 'male'

when 'F' then 'female'

else 'invalid'

end,

salary

from employee


Case不但能够在Select子句中使用,在From子句和Where子句中同样可以使用。下面是在Where子句中使用的一个例子:

select empno, sex, age

from employee

where

case sex

when 'M' then 55

when 'F' then 50

end > age


在From子句中使用的例子极为少见,下面是一个极端的例子。在合同表ctrct_list、客户表customer和订单表quote中都有合同号字段,但订单表中的合同号可能为空。要求查询出订单表订单id和合同号,如订单表中合同号为空的话,查出客户表中相应的合同号。

select distinct

    q.quote_id,

    case rtrim(coalesce(q.ctrct_num, ''))

        when '' then rtrim(coalesce(c.ctrct_num, ''))

        else rtrim(coalesce(q.ctrct_num, ''))

    end ctrct_num

from

    (quote q

    left outer join customer c

        on q.sold_to_cust_num = c.cust_num)

    inner join ctrct_list cl

        on cl.cust_num = q.sold_to_cust_num

        and cl.ctrct_num = (

                case rtrim(coalesce(q.ctrct_num, ''))

                when '' then c.ctrct_num

                else q.ctrct_num

                end

            )


有时让SQL语句有条件的执行也可以不使用case。下面是一个例子:

select *

from EMPLOYEE

WHERE

((job='MANAGER') AND vMgrFlag=1)

or

((job='DESIGNER' or job='ANALYST') AND vTechFlag =1)

or

((job='CLERK' or job='OPERATOR') AND vOfficeFlag=1)


此SQL可以要求根据标志位的不同选择出不同类型的雇员。各个标志位在执行SQL前应提前设置好。这种方法可以在某些情况下将动态SQL改写为静态SQL,因此在编写存储过程时非常实用。但要指出的是,DB2的查询优化器不可能将这种SQL也优化得非常高效,因此在数据量比较大时可能会带来性能问题。开发人员需要在编写完成后使用实际数据测试,必要的话进行性能优化。



此篇文章没有完全解决问题,经过查询,以下代码将问题解决

动态匹配查询条件的问题,如果MY_NAME==null那么忽略查询条件
MY_NAME = CASE :name WHEN 'null' THEN MY_NAME ELSE :name END
当null 值,MY_NAME =MY_NAME 相当于忽略