Как использовать оператор case для определения предложений from и where в хранимой процедуре? - PullRequest
1 голос
/ 09 февраля 2012

У меня есть длинная хранимая процедура, которая возвращает данные об элементе в зависимости от выбранного элемента.

Мне удалось создать хранимую процедуру в течение длительного времени, используя случаи, но в каждом случае мне приходилось включать много дублирующейся информации. Из 11 различных предметов на выбор я бы хотел сделать код максимально чистым.

В выражениях FROM и WHERE есть только небольшие различия, но я не могу найти правильный способ использования Cases после общих операторов INSERT и SELECT.

Я искал вокруг, я понимаю, что оракул запрашивает у меня соответствующее ТОГДА утверждение после SELECT.

Это просто синтаксическая ситуация или она в корне ошибочна ??1009*

Мой рабочий код для двух случаев приведен ниже. Я включил комментарии, на которые я хотел бы поставить дело.

Спасибо за чтение и заранее спасибо за любые предложения.

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

Ответы [ 2 ]

1 голос
/ 10 февраля 2012

Вы не нуждаетесь в CASE для вашего предложения WHERE, так как оно в настоящее время:

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)
)

И, в зависимости от ваших других вариантов, это может быть упрощено:у вас есть таблица «условий» вида

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 голосов
/ 09 февраля 2012

Для использования разных типов и мест вам необходимо использовать динамический 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 и использовать регистр для заполнения вашей переменной.

Дополнительная информация здесь

...