L oop для курсора - PL / SQL - PullRequest
       5

L oop для курсора - PL / SQL

0 голосов
/ 02 марта 2020

Я работаю над анализом огромного количества данных в течение года. Подход состоит в том, чтобы выбирать данные один день за раз с помощью курсора и продолжать заполнять другую таблицу данными за весь год: -


declare
  i_start_date  date := date '2019-04-01';
  i_end_date    date := date '2019-04-02';
begin  
  for cur_r in (select a.id, b.status
                from table1 a join table2 b on a.msg_id = b.msg_id
                where b.t_date between i_start_date and i_end_date
               )
  loop
    insert into test_table (id, status)
      values (cur_r.id, cur_r.status);
  end loop;
end;
/

Не могли бы вы помочь мне запустить этот курсор в PL / SQL блок на весь год с обработкой ошибок (например: - если данные уже есть на 01 апреля, их не следует снова вставлять в таблицу, не создавая дубликатов)

что-то вроде ниже: -

declare
  i_start_date  date := date '2019-01-01'; --start date set
  i_end_date    date := date '2019-12-31'; --end date set
begin

for i_start_date<=i_end_date --condition to fetch data & insert
  (for cur_r in (select a.id, b.status
                from table1 a join table2 b on a.msg_id = b.msg_id
                where b.t_date = i_start_date
               )
  loop
    insert into test_table (id, status)
      values (cur_r.id, cur_r.status);
  end loop;)

  i_start_date+1 -- increment start date


end;
/

Спасибо,

Ответы [ 3 ]

2 голосов
/ 02 марта 2020

Зачем вам даже нужно pl / sql?

insert into test_table (id, 
                        status
                        )
      values (select a.id, 
                     b.status
              from table1 a 
              join table2 b on a.msg_id = b.msg_id
              where b.t_date between date '2019-04-01
                                 and date '2019-04-02'
                and b.t_date not in (select t_date
                                     from status)
;

Но будьте осторожны при сравнении DATE (которые я просто воспроизвел), что oracle DATE всегда включает в себя компонент времени, и Приведенное выше сравнение урезает предоставленные вами даты до полуночи. Таким образом, строка с b.t_date = to_date ('2019-04-02 09:10:11', 'yyyy-mm-dd') не будет выбрана.

0 голосов
/ 02 марта 2020

Вы можете напрямую использовать оператор insert into <table> select ... как

SQL> insert into test_table
     select a.id, b.status
       from table1 a
       join table2 b
         on a.msg_id = b.msg_id
      where b.t_date >= trunc(sysdate) - interval '1' year
        and not exists ( select 0 from test_table t where t.id = a.id );

SQL> commit;

, используя b.t_date >= trunc(sysdate) - interval '1' year, начиная с предыдущего года до текущего дня.

Если вам нужно начать с определенную дату, такую ​​как date'2019-04-01' и сканирование на предстоящий годовой период,

, затем используйте b.t_date between date'2019-04-01' and date'2019-04-01' + interval '1' year - 1

и исключите уже существующие данные в пределах от test_table до

not exists ( select 0 from test_table t where t.id = a.id ) с учетом того, что столбцы идентификаторов являются уникальными или первичными ключами в соответствующих таблицах.

0 голосов
/ 02 марта 2020

Если у вас есть первичный ключ со значением даты, вы можете обработать исключение с помощью dup_val_on_index и затем использовать возврат.

BEGIN
  ...
EXCEPTION
  WHEN DUP_VAL_ON_INDEX THEN
     ...
     RETURN;
END;

Или вы можете использовать MERGE , чтобы указать, когда вставлять или нет.

MERGE INTO TEST_TABLE T
  USING CUR_R C
  ON (C.DATE = T.DATE)
WHEN NOT MATCHED THEN
  INSERT (id, status)
  values (cur_r.id, cur_r.status);
...