Курсор разработчика SQL, возвращающий одну 1 строку, когда он должен возвращать несколько строк - PullRequest
0 голосов
/ 21 мая 2018
procedure new_cust (p_practiceid varchar2)is


  custid varchar2(255);
  l_error_stack varchar2(4000);
  l_error_code integer;

cursor c1 is select id
from customers
where joining_date = to_char(sysdate,'YYYY-MM');


begin

OPEN c1;
loop
FETCH c1  INTO custid;
EXIT WHEN c1%NOTFOUND;

begin 

execute immediate 'drop table new_clients';
execute immediate 'create table new_clients as  select * from client_names where custid= '''||custid||'''';

exception when others then
  l_error_stack := substr(dbms_utility.format_error_backtrace,1,2500)||chr(10)||substr(dbms_utility.format_error_stack,1,500) ;
  l_error_code := sqlcode;
  daily_check_log.logger(systimestamp, inPracticeId, 'error', 'new_cust', l_error_code, l_error_stack);
end;


END LOOP;
CLOSE c1;

end;

Я использую курсор для определения новых клиентов, которые присоединились в этом месяце.Должно быть не менее 10 новых записей, но курсор возвращает только 1 строку.Куда я иду не так?

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

На мой взгляд, вся концепция неверна.В Oracle вы не создаете таблицы динамически, действительно, действительно редкие ситуации, которые оправдывают это.Ваш код полностью статический , нет ничего, что требует динамического SQL.

Рассмотрите возможность создания таблицы один раз - и используйте ее по мере необходимости.Это может включать удаление строк из него.

CTAS с условием false создаст пустую таблицу:

create table new_clients as select * from client_names where 1 = 2;

Вставляйте в нее данные ежемесячно (какэто то, что предлагает ваш код):

insert into new_clients 
  select * 
  from client_names 
  where custid in (select id 
                   from customers 
                   where joining_date between trunc(sysdate, 'mm')
                                          and trunc(last_day(sysdate))
                  );

Я полагаю, что JOINING_DATE на самом деле не YYYY-MM, а дата true .Если на нем есть индекс, он все равно будет работать из-за предложения BETWEEN, которое извлекает весь текущий месяц (хотя, возможно, потребуется дополнительная настройка, в зависимости от имеющихся у вас данных).

Кроме того, это будетлучше, если вы указали имена столбцов, участвующих в операторе INSERT (не имеет значения, их много - назовите их по одному).select * работает нормально, пока что-то не изменится, а затем не будет работать.

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

0 голосов
/ 21 мая 2018

Вам не нужно создавать курсор для этой простой задачи, этот код должен соответствовать вашим требованиям

procedure new_cust (p_practiceid varchar2) is

begin

  execute immediate 'drop table new_clients';
  execute immediate 'create table new_clients as  
                       select cn.* 
                         from client_names cn 
                         join customers c 
                           on c.id = cn.custid
                        where c.joining_date = to_char(sysdate,''YYYY-MM'')';
end;

И не забудьте добавить в него обработку исключений:)

...