Я столкнулся со следующей ошибкой при попытке выполнить скрипт на основе скрипта, предоставленного мистером Рейнольдом:
ORA-04013: число в CACHE должно быть меньше одного цикла.
Причина: число, указанное в CACHE, больше, чем значения в цикле.
Действие: увеличить цикл или кэшировать меньшее количество значений.
Эта ошибка возникает, если текущее nextval слишком велико, чтобы разрешить кэширование указанного числа значений в текущем цикле. Соответственно, я включил обновленную версию его сценария, в которой целевая последовательность сначала изменяется с помощью опции «NOCACHE», а затем кэш восстанавливается до своего первоначального значения после обновления цели nextval . В моем примере db-link и псевдоним «PD» относятся к исходной базе данных, а «QA» относится к целевой базе данных.
Надеюсь, это так же полезно для кого-то, как и предыдущее решение для меня.
SET serveroutput ON
DECLARE
CURSOR GetCursorsToSync IS
SELECT pd.sequence_name, pd.last_number last_number_pd,
qa.last_number last_number_qa, qa.cache_size
FROM user_sequences@PD pd
JOIN user_sequences qa
on qa.sequence_name = pd.sequence_name
WHERE qa.last_number != pd.last_number;
TYPE CursorsTableType IS
TABLE OF GetCursorsToSync%ROWTYPE INDEX BY pls_integer;
CursorsTable CursorsTableType;
i pls_integer;
PROCEDURE Reset_Sequence(
sequence_name IN VARCHAR2,
source_value IN NUMBER,
target_value IN NUMBER,
cache_size IN NUMBER)
IS
l_sql VARCHAR2(4000);
l_temp NUMBER(30);
BEGIN
IF source_value <= target_value THEN
RETURN;
END IF;
dbms_output.put_line(sequence_name || ' ' || source_value || ' ' || target_value);
IF cache_size > 0 THEN
l_sql := 'alter sequence '|| sequence_name || ' nocache';
dbms_output.put_line(l_sql);
EXECUTE IMMEDIATE l_sql;
END IF;
l_sql := 'alter sequence '|| sequence_name || ' increment by ' || TO_CHAR(source_value-target_value);
dbms_output.put_line(l_sql);
EXECUTE IMMEDIATE l_sql;
l_sql := 'SELECT ' || sequence_name || '.nextval FROM dual';
dbms_output.put_line(l_sql);
EXECUTE IMMEDIATE l_sql INTO l_temp;
dbms_output.put_line(l_temp);
l_sql := 'alter sequence ' || sequence_name || ' increment by 1';
dbms_output.put_line(l_sql);
EXECUTE IMMEDIATE l_sql;
IF cache_size > 0 THEN
l_sql := 'alter sequence '|| sequence_name || ' cache ' || TO_CHAR(cache_size);
dbms_output.put_line(l_sql);
EXECUTE IMMEDIATE l_sql;
END IF;
COMMIT;
END Reset_Sequence;
BEGIN
OPEN GetCursorsToSync;
FETCH GetCursorsToSync BULK COLLECT INTO CursorsTable;
CLOSE GetCursorsToSync;
COMMIT;
i := CursorsTable.FIRST;
WHILE i IS NOT NULL LOOP
Reset_Sequence(CursorsTable(i).sequence_name, CursorsTable(i).last_number_pd,
CursorsTable(i).last_number_qa, CursorsTable(i).cache_size);
i := CursorsTable.NEXT(i);
END LOOP;
END;
/