2015-01-13 4 views
0

Я пытаюсь собрать массив номеров ревизий.
Я буду использовать для удаления записей в нескольких таблицах аудита.
Так что я написал PLSQL, чтобы собрать этот массив и выполнить удаление других таблиц, основанных на условиях, используя этот массивoracle bulk delete: удалить из таблицы, где столбец в массиве

declare 
    type NumberArray is table of number index by binary_integer; 
    revisions NumberArray; 
Begin 
    select rev bulk collect into revisions from (
    select t.rev, row_number() over (partition by 
     column1, 
     column2 
     order by column3) rn 
    from table1 t) 
    where rn <> 1; 

    dbms_output.put_line(revisions.count || ' records found from table2 to be deleted'); 
    delete from table2 where rev in (revisions); 
    dbms_output.put_line('deleted from table2'); 

Я получаю

PLS-00382: expression is of wrong type 
06550. 00000 - "line %s, column %s:\n%s" 
*Cause: Usually a PL/SQL compilation error. 

Datatype из тахометра число в table1.

+0

Почему PL/SQL, когда вы могли бы сделать это просто в SQL? –

+0

данные очень огромные .. я хочу время работы – Sahu

+0

Если данные огромны, то переключение контекста будет огромным, PL/SQL будет медленнее, гораздо медленнее, чем SQL. –

ответ

6

Это является хорошим кандидатом для FORALL заявления

declare 
    type NumberArray is table of number(10) index by binary_integer; 
    revisions NumberArray; 
Begin 
    select rev bulk collect into revisions from (
    select t.rev, row_number() over (partition by 
     column1, 
     column2 
     order by column3) rn 
    from table1 t) 
    where rn <> 1; 

    dbms_output.put_line(revisions.count || ' records found from table2 to be deleted'); 
    forall i in revisions.first .. revisions.last 
     delete from table2 where rev = revisions(i); 
    dbms_output.put_line('deleted from table2'); 
End; 

Но если вы по-прежнему настаивают на использовании IN состоянии, вы должны определить свой тип на уровне схемы:

create type NumberArray as table of number; 

, а затем использовать его например

declare 
    revisions NumberArray; 
Begin 
    select rev bulk collect into revisions from (
    select t.rev, row_number() over (partition by 
     column1, 
     column2 
     order by column3) rn 
    from table1 t) 
    where rn <> 1; 

    dbms_output.put_line(revisions.count || ' records found from table2 to be deleted'); 
    delete from table2 where rev in (select column_value from table(revisions)); 
    dbms_output.put_line('deleted from table2'); 
End; 
3

Должно быть это:

delete from table2 where rev MEMBER OF revisions; 

or 

delete from table2 where rev =ANY (SELECT COLUMN_VALUE FROM TABLE(revisions)); 

or 

forall i in revisions.FIRST..revisions.LAST 
delete from table2 where rev = revisions(i); 

or 

delete from table2 where rev =ANY (
select rev 
from (
    select t.rev, row_number() over (partition by 
     column1, 
     column2 
     order by column3) rn 
    from table1 t) 
    where rn <> 1 
); 

or (not the preferred way of doing it) 

for i in revisions.FIRST..revisions.LAST LOOP 
    delete from table2 where rev = revisions(i); 
END LOOP; 

Как уже писал Marcin Wroblewski, вложенная таблица должна быть создана на уровне схемы.

1

А почему бы вам сделать это в PL/SQL, когда это может быть сделано в простом SQL? Вам необязательно ввести переключение контекста между обоими двигателями.

Все, что PL/SQL кода нет ничего, кроме простого ВЕЬЕТЕ -

DELETE FROM table2 WHERE rev IN(
    SELECT rev FROM(
     select t.rev, row_number() over (partition by 
       column1, 
       column2 
       order by column3) rn 
     from table1 t) 
    where rn <> 1 
); 
Смежные вопросы