我们在PL / SQL中使用动态where子句的方法

时间:2013-11-19 14:27:47

标签: sql oracle plsql where-clause

我们有很多查询,我们需要根据任意数量的给定过滤器动态地使用where子句。过滤器源自用户输入(超出此问题的范围)。

我们提出了如下所示的解决方案:


过滤器在代码中由带有零个或多个元素的列表(plsql表)和一个包含列表长度的count变量表示,如果列表应该被忽略,则为-1(不要过滤)

示例:

CREATE OR REPLACE TYPE t_number_table AS TABLE OF NUMBER;

PROCEDURE get_filter(p_filter_type IN VARCHAR2,
                     p_key_list    OUT t_number_table,
                     p_count       OUT PLS_INTEGER) IS
BEGIN
  --normally, this procedure would consult the user input to find out what needs
  --to be filtered, but for this example just always return the same filters

  CASE p_filter_type
    WHEN 'ORDER' THEN
      p_key_list := t_number_table(11, 12, 13, 14);
      p_count    := 4; --user filtered on 4 orders
    WHEN 'PRODUCT' THEN
      p_key_list := NULL;
      p_count    := -1; --user did not filter on product
    WHEN 'CUSTOMER' THEN
      p_key_list := t_number_table(1000);
      p_count    := 1; --user filtered on 1 customer
  END CASE;
END;

get_filter程序会返回用户在四个订单上过滤时的过滤器,不会过滤产品并过滤一个客户。

如果我们想获得与这些过滤器匹配的订单集,我们按如下方式使用它:

DECLARE
  v_order_list     t_number_table;
  v_order_count    PLS_INTEGER;

  v_product_list   t_number_table;
  v_product_count  PLS_INTEGER;

  v_customer_list  t_number_table;
  v_customer_count PLS_INTEGER;
BEGIN
  get_filter('ORDER', v_order_list, v_order_count);
  get_filter('PRODUCT', v_product_list, v_product_count);
  get_filter('CUSTOMER', v_customer_list, v_customer_count);

  ...
  OPEN some_ref_cursor FOR
    SELECT *
    FROM   order_header oh
    JOIN   order_line ol ON ol.orderno = oh.orderno
    WHERE  (v_order_count = -1 OR
              oh.orderno IN (SELECT * FROM TABLE(v_order_list)))
    AND    (v_product_count = -1 OR
              ol.productno IN (SELECT * FROM TABLE(v_product_list)))
    AND    (v_customer_count = -1 OR
              oh.customerno IN (SELECT * FROM TABLE(v_customer_list)));
END;

我们对我们的方法感兴趣的是它非常灵活,有点优雅。它似乎也表现不错,但我想知道别人如何处理这个问题。此外,我们错过的方法可能存在一些问题。对这种方法有什么缺点?

0 个答案:

没有答案