2012-02-09 10 views
1

私は選択された項目に応じて項目のデータを返す長いストアドプロシージャを持っています。ストアドプロシージャのfromおよびwhere句を決定するためにcase文を使用するにはどうすればよいですか?

ケースを使用してストアドプロシージャを構築することはできましたが、それぞれのケースで重複した情報をたくさん含める必要がありました。選択できる11の異なるアイテムコードをできるだけきれいにしたいと思います。

FROM句とWHERE句にわずかな違いがありますが、共通のINSERTとSELECT文の後にCasesを使用する正しい方法を理解することはできません。

私は、oracleがSELECTの後の適切なTHEN文を求めていることを私は理解しています。

これは文法的な状況ですか、それとも根本的に欠陥がありますか?

私の2つのケースの作業コードは以下のとおりです。私は代わりにケースを入れたいと思っています。

お読みいただきありがとうございました、お寄せいただきありがとうございます。

PROCEDURE Fetch_Data_By_Item  
(
inItem STRING, 
RC1 IN OUT Sys_Refcursor 
)AS 

tRc1 SYS_REFCURSOR; 

BEGIN 

     CASE 
     WHEN inItem = 'ItemOne' 
     THEN 

     DELETE FROM TEMP_DATA;   ----Common to all procedures 
     INSERT INTO TEMP_DATA 
     (
      Item_Name, 
      Item_OTher, 
      Item_id, 
      _code, 
      _date 
     ) 


    --Get all the ILists 

     WITH _LIST AS     ----Common to all procedures 
    ( 
      SELECT DISTINCT 
          A.List_ as "_IList" 
      FROM   Schema.VIEW_One    A 
      INNER JOIN  SChema2.VIEW_Two  
      WHERE   A.SI_    = 'Y' 

    ) 

     --ItemOne 


    ( SELECT   
       'Item_One' as "Item_Name", 
       'ITem_One' as "Item_Other" , 
       S.Item_ID, 
       T._CODE, 
       S._DATE,      ----Common to all procedures 

         ----Case should start here  
     FROM Schema.VIEW_ONE T, 
       SChema.VIEW_Two S 
     WHERE T.Item_id   =   S.Item_id 
     AND T.SI_    =   'Y' 
     AND S.SI_    =   'Y' 
     AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 
    ) 

     ); 

     --Item 2 

    WHEN inItem = 'ItemTwo' 
     THEN 

     DELETE FROM TEMP_DATA; 
     INSERT INTO TEMP_DATA 
     (
      Item_Name, 
      Item_OTher, 
      Item_id, 
      _code, 
      _date 
     ) 


    --Get all the ILists 

     WITH _LIST AS 
    ( 

      SELECT DISTINCT 
          A.List_ as "_IList" 
      FROM   Schema.VIEW_One    A 
      INNER JOIN  SChema2.VIEW_Two  
      WHERE   A.SI_    = 'Y'      
     --Real Estate 
    ) 

    ( SELECT   
       'Item_Two' as "Item_Name", 
       'ITem_Two' as "Item_Other" , 
       S.Item_ID, 
       T._CODE, 
       S._DATE,       

     FROM Schema.VIEW_ONE T, 
       SChema.VIEW_Two S, 
      Schema.VIEW_Three U 
     WHERE T.Item_id   =   S.Item_id 
     AND T.SI_    =   'Z' 
     AND S.SI_    =   'Z' 
     And U.Id  =  '123' 
     AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 
    ) ; 

---9 other cases******** 

End Case; 

OPEn RC1 for 

SELECT 

Item_Name, 
Item_Other, 
Item_Id, 
code, 
date 

FROM TEMP_DATA; 
END FETCH_DATA_BY_ITEM 

リビジョン 述べたように、この結果を達成するために、いくつかの方法を試してきたし、これまでのところ、これは私が得ることができる最も近いです。私はここで何が欠けているのか分からないようです。これは私が現時点で持っているものですが、私が行方不明のものを見ることができますか?

PROCEDURE Fetch_Data_By_Item 
    (
    inItem STRING, 
    RC1 IN OUT Sys_Refcursor 
    )AS 

    tRc1 SYS_REFCURSOR; 

    BEGIN 

    DELETE FROM TEMP_DATA;    ----Common to all procedures 
    INSERT INTO TEMP_DATA 
    (
     .... 
    ) 
--Get all the ILists 

    WITH _LIST AS       ----Common to all procedures 
( 
     .... 
) 

( SELECT   
      S.Item_Name, 
      S.Item_Other , 
      S.Item_ID, 
      T._CODE, 
      S._DATE,       ----Common to all procedures 


    FROM Schema.VIEW_ONE T, 
      Schema.VIEW_Two S, 
      Schema.VIEW_Three U 

    WHERE 

    CASE inItem 

    --ItemOne 

    WHEN 'ItemOne' 
    THEN 

      T.Item_id  =   S.Item_id 
    AND T.SI_   =   'Y' 
    AND S.SI_   =   'Y' 
    AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 

    --Item 2 

    WHEN 'ItemTwo' 
    THEN   

      T.Item_id  =   S.Item_id 
    AND T.SI_   =   'Z' 
    AND S.SI_   =   'Z' 
    And U.Id   =   '123' 
    AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 
    END 
); 

    ---9 other cases******** 

    OPEN RC1 for 

    SELECT 

    .... 

    FROM TEMP_DATA; 
    END FETCH_DATA_BY_ITEM 
+0

編集いただきありがとうございます。 – dee

答えて

1

それが現在であるとしてあなたのWHERE句のCASEを必要としません:

WHERE 
(
    inItem = 'ItemOne' 
    AND T.Item_id  =   S.Item_id 
    AND T.SI_   =   'Y' 
    AND S.SI_   =   'Y' 
    AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 
) 
OR (
    inItem = 'ItemTwo' 
    AND T.Item_id  =   S.Item_id 
    AND T.SI_   =   'Z' 
    AND S.SI_   =   'Z' 
    And U.Id   =   '123' 
    AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 
) 

そして、あなたの他のオプションに応じて、これを簡素化することができる。

WHERE 
    T.Item_id  =   S.Item_id 
    AND T.List_    NOT IN  (SELECT _IList FROM _LIST) 
    AND (
     (
     inItem = 'ItemOne' 
     AND T.SI_   =   'Y' 
     AND S.SI_   =   'Y' 
    ) 
     OR (
     inItem = 'ItemTwo' 
     AND T.SI_   =   'Z' 
     AND S.SI_   =   'Z' 
     And U.Id   =   '123' 
    ) 
    ) 

フォームの「条件」テーブルがある場合

inItem, T_SI_, S_SI_, U_Id 
ItemOne, Y, Y, NULL 
ItemTwo, Z, Z, 123 

その後、これは(私はあなたが私が放棄をお勧めされ、暗黙の加入を使用し知っている)少し単純に取得します。

INNER JOIN conditions 
    ON conditions.inItem = inItem 
    AND (conditions.T_SI_ IS NULL OR conditions.T_SI_ = T.SI_) 
    AND (conditions.S_SI_ IS NULL OR conditions.S_SI = S.SI_) 
    AND (conditions.U_Id IS NULL OR conditions.U_Id = U.Id) 
WHERE 
    T.Item_id = S.Item_id -- This actually moves up into an INNER JOIN 
    AND T.List_ NOT IN (SELECT _IList FROM _LIST) 

ロジックテーブルは時折変更し、しばしば回ももののために良いです、より読みやすいコードのために作ることができます。システムを維持するのが難しくなる可能性があるので、メタを使いすぎることに注意する必要がありますが、賢明に使うと良い戦略になることがあります。

+0

これは単なる修正かもしれません。私は単純化のために除外したかなりのバリエーションがかなりありますが、これは有望です。 – dee

+0

@deeまた、このような複雑なリテラル条件をテーブルから外すことも可能であることに注意してください。私は答えを更新します。 –

+0

私はあなたが提案したアイデアに取り組むのに数日間を費やしました。残念ながら、第3のビュー "Schema.VIEW_Three U"に参加することはできません。これは、アイテムの約半分の結果セットを変更するためです。 inItemに基づいてFROM句を決定する方法を見つけることができますか?ありがとう。 – dee

0

動的なSQLを使用する必要があります。 execute immediateでこれを行うことができます。例:

set serveroutput on size 10000 
declare 
    vtest varchar2(1); 
begin 
    execute immediate 'select ''X'' from dual' into vtest; 
    dbms_output.put_line(vtest); 
end; 

したがって、変数を作成してSQLを格納し、その変数を完全に使用することができます。

詳細情報here

関連する問題