1

ストアド プロシージャで受け取った INPUT に基づいて、WHERE 句で個別の列を使用したい。

  • TYPE_DEFINITION = 'SUP' の場合、SUPPLIER 列を使用します

  • TYPE_DEFINITION = 'CAT' の場合、CATEGORY 列を使用します

SELECTステートメントを使用して2 つの別々の を記述できることはわかっています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 に答える