Oracle - 根据输入更改WHERE子句中的列

时间:2014-12-31 17:53:52

标签: oracle case where-clause multiple-columns tablecolumn

我希望根据存储过程中收到的INPUT在WHERE子句中使用单独的列。

  • 如果TYPE_DEFINITION ='SUP',则使用SUPPLIER列

  • 如果TYPE_DEFINITION ='CAT',则使用CATEGORY列

我知道我可以使用SELECT语句写两个单独的CASE,但这将是非常愚蠢和多余的。任何更干净的方式吗?

CREATE OR REPLACE PROCEDURE SG.STORED_PROCEDURE (
   TYPE_DEFINITION     IN VARCHAR2,
   VALUE               IN VARCHAR2,
   STORELIST           IN VARCHAR2)
AS
BEGIN
      SELECT O.ORGNUMBER,
             S.SKU,
        FROM SKU S JOIN ORG O ON S.ORGID = O.ORGID
       WHERE                   
             AND O.ORGNUMBER IN (STORELIST)
             AND (CASE TYPE_DEFINITION
                     WHEN 'SUP' THEN S.SUPPLIER = VALUE
                     ELSE S.CATEGORY = VALUE
                  END);
END;
/

2 个答案:

答案 0 :(得分:1)

您需要在程序中使用dynamic sql

这样的事情:

CREATE OR REPLACE PROCEDURE SG.STORE_PROC (
   TYPE_DEFINITION     IN VARCHAR2,
   VALUE               IN VARCHAR2,
   STORELIST           IN VARCHAR2)
AS
  TYPE EmpCurTyp  IS REF CURSOR;
  v_emp_cursor    EmpCurTyp;
  v_stmt_str      VARCHAR2(200);
  v_orgnumber     VARCHAR2(200);
  v_sku           VARCHAR2(200);
BEGIN
  v_stmt_str := 'SELECT O.ORGNUMBER, S.SKU,FROM SKU S JOIN ORG O ON S.ORGID = O.ORGID ';
  if type_definition = 'SUP' then
     v_stmt_str := v_stmt_str || 'WHERE s.supplier = :v';
  else
     v_stmt_str := v_stmt_str || 'WHERE s.category = :v';
  end if;


  -- Open cursor & specify bind variable in USING clause:
  OPEN v_emp_cursor FOR v_stmt_str USING value;

  -- Fetch rows from result set one at a time:
  LOOP
    FETCH v_emp_cursor INTO v_orgnumber, v_sku;
    -- you can do something here with your values
    EXIT WHEN v_emp_cursor%NOTFOUND;
  END LOOP;

  -- Close cursor:
  CLOSE v_emp_cursor;
END;
/

答案 1 :(得分:1)

您的代码非常接近。 CASE THEN必须返回表达式,而不是条件。但是CASE可以用作条件的一部分,只需移动= VALUE  到外面。

改变这个:

         AND (CASE TYPE_DEFINITION
                 WHEN 'SUP' THEN S.SUPPLIER = VALUE
                 ELSE S.CATEGORY = VALUE
              END);

To This:

         AND VALUE = (CASE TYPE_DEFINITION
                         WHEN 'SUP' THEN S.SUPPLIER
                         ELSE S.CATEGORY
                      END);

您的代码很有意义。这种限制可能是甲骨文未完全支持布尔人的结果。


<强>更新

如果遇到性能问题,可能需要使用动态SQL或确保静态SQL正确使用FILTER操作。当Oracle构建执行计划时,它可以使用绑定变量(如常量),并根据输入选择不同的计划。正如Ben指出的那样,这些FILTER操作并不总是完美有效,如果您使用这样的简化条件,有时可能会有所帮助:

(TYPE_DEFINITION = 'SUP' AND S.SUPPLIER = VALUE)
OR
((TYPE_DEFINITION <> 'SUP' OR TYPE_DEFINITION IS NULL) AND S.CATEGORY = VALUE)