1

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

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

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

我知道我可以SELECT使用一个语句编写两个单独的 's 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;
/
4

2 回答 2

2

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

改变这个:

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

对此:

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

你的代码很有意义。此限制可能是 Oracle 不完全支持布尔值的结果。


更新

如果遇到性能问题,您可能希望使用动态 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)
于 2014-12-31T19:12:38.947 回答
1

您需要在过程中使用动态 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;
/
于 2014-12-31T17:56:40.223 回答