Pl / SQL Разделение таблицы - PullRequest
       1

Pl / SQL Разделение таблицы

0 голосов
/ 16 декабря 2018

У меня есть таблица в Oracle.Я хочу сделать несколько таблиц, каждая из которых содержит 1/10 данных этой таблицы (на самом деле мне нужен только один столбец).Мне удалось написать следующий код, но он не кажется эффективным, так как он каждый раз пробегает всю исходную таблицу.

declare
  baseObjid  Number := 100;
  chunkSize  Number;
  totalCount Number;
begin
  select count(1) into totalCount from table_person;
  chunkSize := trunc(totalCount / 10) + 1;
  for i in 1 .. 10 loop
    execute immediate 'create table table_person_' || i ||
                      ' AS (select sel.r + ' || baseObjid ||
                      ' objid,  sel.objid oldId from 
                      (select rownum r, objid from table_person order by objid) sel 
                      where sel.r > ' || (i - 1) * chunkSize || 
                      ' and sel.r <= ' || i * chunkSize || ')';
    commit;
  end loop;
end;

Есть ли способ сделать так, чтобы он получал доступ только к исходной таблицеодин раз?Любой другой совет тоже приветствуется.

1 Ответ

0 голосов
/ 16 декабря 2018

Самым простым способом заполнения нескольких таблиц из одного запроса является оператор INSERT ALL.

Этот запрос разбивает идентификаторы PERSON на десять предварительно созданных целевых таблиц PERSON_1 .. PERSON_10, применяя модуль к rownum в действующей select.Вы можете изменить прогноз запроса, чтобы задать другой критерий.

insert all
    when rn = 1 then into person_1 (id) values (id) 
    when rn = 2 then into person_2 (id) values (id) 
    when rn = 3 then into person_3 (id) values (id) 
    when rn = 4 then into person_4 (id) values (id) 
    when rn = 5 then into person_5 (id) values (id) 
    when rn = 6 then into person_6 (id) values (id) 
    when rn = 7 then into person_7 (id) values (id) 
    when rn = 8 then into person_8 (id) values (id) 
    when rn = 9 then into person_9 (id) values (id) 
    else into person_10 values (id) 
select id, mod(rownum,10) as rn from person;

В качестве альтернативы вы можете изменить распределение, изменив критерии WHEN, например, на сегменты:

insert all
    when id < 1000 then into person_1 (id) values (id) 
    when id < 2000 then into person_2 (id) values (id) 
    when id < 3000 then into person_3 (id) values (id) 
    when id < 4000 then into person_4 (id) values (id) 
    when id < 5000 then into person_5 (id) values (id) 
    when id < 6000 then into person_6 (id) values (id) 
    when id < 7000 then into person_7 (id) values (id) 
    when id < 8000 then into person_8 (id) values (id) 
    when id < 9000 then into person_9 (id) values (id) 
    else into person_10 values (id) 
select id from person; 

Очевидно, что сегменты могут зависеть от столбца rownum, как в вашемотправленный код.


Стоит рассмотреть преимущества отделения создания таблиц от заполнения данных.

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

Сначала создайте пустые таблицыобеспечивает восстанавливаемую позицию.INSERT ALL - это отдельный оператор, который не только более производителен, чем десять вариантов выбора, но также означает, что все таблицы заполнены или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...