Процедура PL / SQL и кристальный отчет - PullRequest
0 голосов
/ 26 ноября 2009

Я пытаюсь использовать следующую процедуру в качестве источника данных для моего отчета Crystal. Запрос работает, как я и ожидал, но проблема в том, что я не могу понять, как извлечь данные из этих фиктивных таблиц - IFS_PR_DUMMY_TAB и IFS_PR_DUMMY2_TAB

CREATE OR REPLACE procedure dummy9_IFS_FR2_Sales (cdate IN date)

as

acontract customer_order.contract%type;
ashowroom customer_order.district_code%type;
aorderno customer_order.order_no%type;
amount number(10);

bcontract customer_order.contract%type;
bshowroom customer_order.district_code%type;
borderno customer_order.order_no%type;
bamount number(10);

CURSOR c2 IS
select  contract, district_code ,count(order_no),
SUM(CUSTOMER_ORDER_API.Get_Total_Sale_Price__(order_no))
from CUSTOMER_ORDER
where order_no IN (select distinct order_no from customer_order_line where state IN ('Released') )  AND state IN ('Released') and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
and contract IN
('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
group by contract,district_code, date_entered ; 

CURSOR c2 IS
select  contract, district_code ,count(order_no),
SUM(CUSTOMER_ORDER_API.Get_Total_Sale_Price__(order_no))
from CUSTOMER_ORDER
where order_no IN (select distinct order_no from customer_order_line where state IN ('Reserved') )  AND state IN ('Reserved') and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
and contract IN
('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
group by contract,district_code, date_entered ; 

begin

--For Released Orders

  OPEN c1;

  DELETE FROM IFS_PR_DUMMY_TAB;

  loop
      fetch c1 into acontract, ashowroom, aorderno, amount;
      exit when c1%notfound;

Insert into IFS_PR_DUMMY_TAB
(DCONTRACT ,DSHOWROOM ,DORDERNO,DAMOUNT) values (acontract,ashowroom,aorderno,amount);

end loop;
close c1;

--For Reserved Orders

 OPEN c2;

 DELETE FROM IFS_PR_DUMMY2_TAB;

loop

      fetch c2 into bcontract, bshowroom, borderno, bamount;
      exit when c2%notfound;

Insert into IFS_PR_DUMMY2_TAB
(ECONTRACT ,ESHOWROOM ,EORDERNO,EAMOUNT) values (bcontract,bshowroom,borderno,bamount);

end loop;
close c2; 

end;

Ответы [ 2 ]

1 голос
/ 26 ноября 2009

Лучший способ решить вашу проблему - это чтобы ваша процедура возвращала наборы результатов. В Oracle мы используем REF CURSORS для достижения этой цели. Вам больше не нужно заполнять временные таблицы, но мы можем использовать одну из них для определения сигнатуры REF CURSOR.

create or replace package report_records as
    type order_recs is ref cursor 
        return IFS_PR_DUMMY_TAB%rowtype;
end;
/

Эта процедура возвращает два курсора ссылки.

create or replace procedure dummy9_ifs_fr2_sales 
    (cdate in date
     , c_released_orders in out report_records.order_recs
     , c_reserved_orders in out report_records.order_recs
     )

begin
    open c_released_orders for
        select  contract
               , district_code 
               ,count(order_no)
               ,sum(customer_order_api.get_total_sale_price__(order_no))
        from customer_order
        where order_no 
        in (select distinct order_no 
               from customer_order_line 
               where state in ('Released') )  
        AND state in ('Released') 
        and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
        and contract in ('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
        group by contract,district_code, date_entered ; 
    open c_released_orders for
        select  contract
                 , district_code 
                 ,count(order_no)
                 ,sum(customer_order_api.get_total_sale_price__(order_no))
        from customer_order
        where order_no in (select distinct order_no 
                              from customer_order_line 
                              where state in ('Reserved') )
        AND state in ('Reserved') 
        and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
        and contract in ('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
        group by contract,district_code, date_entered ; 
end;
/

Интересно, что если ваш столбец date_entered имеет тип данных DATE, вам не следует использовать преобразование TO_CHAR (). Если вы хотите обрабатывать строки, содержащие элемент времени, есть более эффективные способы обработки этого.

Ссылочные курсоры подробно объясняются в Руководстве пользователя Oracle PL / SQL. Узнайте больше.

редактировать

Я не человек Crystal Reports. Похоже, Google выбрасывает довольно старую документацию (например, this ). Но все согласны с тем, что CR довольно ограничен во взаимодействии с хранимыми процедурами Oracle.

Очевидно, что для Crystal Reports необходимы параметры, объявленные как IN OUT. Также кажется, что он может обрабатывать только один такой параметр ref курсора. Кроме того, указатель ссылки должен быть аргументом first в сигнатуре процедуры. Наконец, на мой взгляд, совершенно невероятно, что «хранимая процедура не может вызвать другую хранимую процедуру». Мы привыкли разрабатывать шаблоны, которые утверждают, что вызывающим программам не нужно ничего знать о внутренностях вызываемой программы, но здесь мы, похоже, определяем, как внутренняя работа вызываемой программы определяется видом программы, которая ее вызывает. Это довольно отстойно.

Так что, в любом случае, вышеупомянутое решение не будет работать для Crystal Reports. Единственное решение - разбить его на две процедуры с такими подписями:

create or replace procedure dummy9_ifs_fr2_sales_released 
    (c_released_orders in out report_records.order_recs
     , cdate in date
     )
 as ... 

create or replace procedure dummy9_ifs_fr2_sales_reserved 
    (c_reserved_orders in out report_records.order_recs
     , cdate in date
     )
as ...

Эти процедуры могут быть объединены в пакет (при условии, что CR может справиться с этой конструкцией).

Если решение с двумя процедурами неприемлемо, то я думаю, что вы остаетесь с подходом Дэвида: полностью отказаться от хранимых процедур и просто использовать необработанный SQL в отчете.

0 голосов
/ 26 ноября 2009

Ваш код отстой.

Во-первых, почему вы используете явные курсоры? Почему бы вам просто не вставить строки в таблицы?

Во-вторых, зачем удалять, когда вы могли бы обрезать намного быстрее?

В-третьих, to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY') применяет функцию к столбцу (поэтому индекс не может быть использован и оптимизатор не может получить точную оценку мощности), и преобразует даты в глупый символ формат с месяцем в лидирующей позиции, чтобы он даже не сделал правильное сравнение! Сортировка 02 ноября 2009 года больше, чем 01 марта 2010 года в вашей логике.

В-четвертых, с какой стати вы используете хранимую процедуру для этого? Просто запустите эти чертовы запросы и объедините их все, если вам нужно.

Это напоминает мне обо всем дерьме, которое я видел от разработчиков оффшорных отчетов в течение двух лет на моей предыдущей работе. Полная некомпетентность.

...