oracle过程参数可能为空或多个值的查询(一)

   今天在网上逛笔记本,挑眼花了,好在我的要求比较明确,i3或者i5的处理器,独立显卡,4G以上内存……
品牌:√ 不限
价格:√ 4000-5000
屏幕尺寸:√ 15英寸
等等

    我在勾选了我的需求之后,符合条件的产品就被搜索出来了。然而这些条件并不是必须的,你可以勾选其中几个,也可以不勾选,不勾选的话就是完全查询了。
    于是我在想在oracle存储过程里要怎么解决这个问题呢。
    最容易让人想到的是一个参数一个参数的判断,然后去拼接sql,我非常不喜欢拼接sql这种方式,太繁琐而且容易出错并且效率还很低。不在万不得已的情况下,不要使用拼接sql。那么我们怎么简单高效而优雅的解决这个问题呢。
    巧用COALESCE函数来解决它!
    为了测试,我们简单的创建一张产品表,为了方便就建了一张TEST表吧,四个varchar2字段(CPU_,SCREEN,PRICE,ERA)
PS:由于CPU是oracle的保留字段,所以注意我用的是CPU_。
-----------------------------------------------------
TEST|CPU_ |SCREEN|PRICE| ERA
-----------------------------------------------------
          | i3       | 13         | 3999  | 2011
-----------------------------------------------------
          | i3       | 14         | 4399  | 2012
-----------------------------------------------------
          | i5       | 15         | 5200  | 2011
-----------------------------------------------------
          | i5       | 13         | 5499  | 2012
-----------------------------------------------------
          | i7       | 15         | 6999  | 2012
-----------------------------------------------------
创建包,过程
CREATE OR REPLACE PACKAGE PKG_DEMO IS
--定义游标
  TYPE P_CURSOR IS REF CURSOR;
--过程申明
  PROCEDURE TEST_SELECT(V_VAR1 IN VARCHAR2,
                        V_VAR2 IN VARCHAR2,
                        V_VAR3 IN VARCHAR2,
                        V_VAR4 IN VARCHAR2,
                        CR OUT P_CURSOR);
END PKG_DEMO;
------------------------------
CREATE OR REPLACE PACKAGE BODY PKG_DEMO IS
--创建包体
 PROCEDURE TEST_SELECT(V_VAR1 IN VARCHAR2,
                       V_VAR2 IN VARCHAR2,
                       V_VAR3 IN VARCHAR2,
                       V_VAR4 IN VARCHAR2,
                       CR OUT P_CURSOR)
     AS
     BEGIN
--这样在参数为空的时候查询条件就成了CPU_=CPU_ AND SCREEN=SCREEN......
       OPEN CR FOR 'SELECT * FROM TEST WHERE CPU_=COALESCE(:X,CPU_)
                      AND SCREEN=COALESCE(:X,SCREEN) 
                      AND PRICE=COALESCE(:X,PRICE) 
                      AND ERA=COALESCE(:X,ERA)' 
                      USING 
                      V_VAR1,
                      V_VAR2,
                      V_VAR3,
                      V_VAR4;
     END;
END PKG_DEMO;

嗯,这么一来,是不是就把任务简化了许多?
测试一下它吧。
DECLARE
RC SYS_REFCURSOR;
REC TEST%ROWTYPE;
BEGIN
  PKG_DEMO.TEST_SELECT('i5','15',NULL,'',RC);--在oracle中''和null是一样的。
  LOOP FETCH RC INTO REC;
  EXIT WHEN RC%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('CPU='||REC.CPU_||
                         ' SCREEN='||REC.SCREEN||
                         ' PRICE='||REC.PRICE||
                         ' ERA='||REC.ERA);
  END LOOP;
END;

这样我们就把i5处理器和15寸屏幕的产品给搜索出来了

CPU=i5 SCREEN=15 PRICE=5200 ERA=2011

总结:很多网上的人也遭遇过此类问题,但是他们通过IF X IS NULL THEN 来拼接sql,不仅要一个一个的判断,而且这种写法效率很低,代码的可读性也非常差,本来一句话的代码,可能要写上好几十行。而且执行效率非常低下。而隐式的绑定变量能够让oracle在share_pool中把这句话缓存起来。下次使用就非常的快了。这是至关重要的,同样查询1000条语句,动态拼接sql所使用的时间要比绑定变量所使用的时间就有可能慢100个数量级。在一个笔记本门户网站上,很多时候,远不止1000个人并发检索自己心仪的笔记本。
好了,可能你也注意到了,有时候一个条件可能被勾选多个值,比如CPU 我即勾选了i3又勾选了i5,这种情况下我们要怎么处理呢?下一篇中我们就来实现它。



猜你喜欢

转载自nikoloss.iteye.com/blog/1607775