ORA-01775: зацикленная цепочка синонимов, но синонимов нет

Не могу понять, почему в строке 52 этой хранимой процедуры я получаю сообщение «Проигнорировано выражение SQL» и «ORA-01775: зацикленная цепочка синонимов». Есть идеи?

CREATE OR REPLACE PACKAGE PURGE_LOG_BY_EVENT_DAYS AS

  TYPE dual_cursorType IS REF CURSOR RETURN dual%ROWTYPE;

  PROCEDURE log_master_by_event_days (event_id NUMBER, purge_recs_older_than NUMBER, result_cursor OUT dual_cursorType);


END PURGE_LOG_BY_EVENT_DAYS;

/


CREATE OR REPLACE PACKAGE BODY PURGE_LOG_BY_EVENT_DAYS
AS

  err_msg     VARCHAR2(4000);

  PROCEDURE log_master_by_event_days (event_id NUMBER, purge_recs_older_than NUMBER, result_cursor OUT dual_cursorType)
  IS

  TYPE  type_rowid IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
  TYPE  type_ref_cur IS REF CURSOR;

  l_rid                   type_rowid;
  c1                      type_ref_cur;

  l_sql_stmt              VARCHAR2(4000);
  proc_start_time         DATE := sysdate;
  purge_date              DATE;

  l_bulk_collect_limit    NUMBER := 1000;
  retry                   NUMBER := 5;
  retry_count             NUMBER := 0; 
  loop_count              NUMBER := 0;

  err_code                VARCHAR2(10);


BEGIN

  purge_date := to_date(sysdate - purge_recs_older_than);

  l_sql_stmt := '';
  l_sql_stmt := l_sql_stmt ||' SELECT rowid FROM LOG_MASTER ';
  l_sql_stmt := l_sql_stmt ||'  WHERE last_changed_date < :purge_date';
  l_sql_stmt := l_sql_stmt ||'    AND event_id = :event_id';


  -- The following while loop
  -- executes the purge code
  -- 'retry' number of times in case of ORA-01555

  WHILE retry > 0 LOOP

    BEGIN

      -- START of purge code
      OPEN c1 FOR l_sql_stmt USING purge_date, event_id;
      LOOP

        FETCH c1 BULK COLLECT into l_rid LIMIT l_bulk_collect_limit;

        FORALL i IN 1..l_rid.COUNT
          DELETE from log_master
           WHERE rowid = l_rid(i);
        COMMIT;

        loop_count := loop_count + 1;
        EXIT WHEN c1%NOTFOUND;

      END LOOP;
      CLOSE c1;

      -- End of purge code
      -- if processing reached this point
      -- Process completed successfuly, set retry = 0 to exit loop
      retry := 0;

    EXCEPTION
    WHEN OTHERS THEN
      -- ====================================
      -- Get error msg
      -- ====================================

      ROLLBACK;
      err_code := sqlcode;

      dbms_output.put_line(err_code);

      -- ====================================
      -- Check if it is 01555
      -- if so retry, else exit loop
      -- ====================================

      retry := retry - 1;
      if err_code = '-1555' and retry > 0 THEN
        CLOSE c1;
        retry_count :=  retry_count + 1;
      else
        err_msg := sqlerrm;
        exit;
      end if;
    END;
  END LOOP;


  IF err_msg IS NULL THEN


    open result_cursor for select '1 - PURGE_LOG_BY_EVENT_DAYS ran successfully (event_id : '||event_id||', loop_count : '||loop_count||', bulk_limit : '||l_bulk_collect_limit||', retries : '||retry_count||') ' from dual;


  ELSE


    open result_cursor for select '2 - PURGE_LOG_BY_EVENT_DAYS After (event_id : '||event_id||', loop_count : '||loop_count||', bulk_limit : '||l_bulk_collect_limit||', retries : '||retry_count||') with Error: ' || err_msg from dual;


  END IF;

 END log_master_by_event_days;


END PURGE_LOG_BY_EVENT_DAYS;

person Community    schedule 31.10.2008    source источник
comment
Если вы не пришлете хорошо отформатированный фрагмент кода, я не смогу помочь.   -  person gustavodidomenico    schedule 23.04.2014


Ответы (2)


Я понятия не имею, почему вы получаете ошибку синонима. Но это слишком много кода для чего-то, что должно быть одним оператором DELETE. Я предполагаю, что вы изменили его на commit-every-n, чтобы избежать ошибок отката. Было бы неплохо, если бы вы могли заставить своего администратора баз данных увеличить пространство для отмены, чтобы вы действительно могли выполнять необходимую работу. В противном случае, я думаю, вы все равно можете сделать это намного проще:

LOOP
  DELETE FROM log_master
    WHERE last_changed_date < :purge_date
      AND event_id = :event_id
      AND rownum <= :batch_delete_limit
    USING purge_date, event_id, l_bulk_collect_limit;
  EXIT WHEN SQL%NOTFOUND;
END LOOP;

И вы можете использовать свою логику повторных попыток, если хотите.

Извините, если я упустил какую-то тонкость, которая отличает это от того, что вы делаете.

person Dave Costa    schedule 31.10.2008

SELECT table_owner, table_name, db_link
  FROM dba_synonyms 
 WHERE owner        = 'PUBLIC' and db_link is not null

насколько я знаю, возвращает 0 строк, синонимов нет.......

person Community    schedule 31.10.2008
comment
Ну, вы проверяете там только ПУБЛИЧНЫЕ синонимы. Вы также должны проверить схему, которой принадлежит пакет, и, возможно, ту, которая вызывает его, если они разные. - person Dave Costa; 31.10.2008