2008-10-31 4 views
0

Не могу понять, почему я получаю «SQL Statement ignored» и «ORA-01775: цикл цепочки синонимов» в строке 52 этой хранимой процедуры. Есть идеи?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; 
+0

Если вы не отправили удаленный отформатированный код, я не могу помочь. – gustavodidomenico 2014-04-23 17:46:22

ответ

0
SELECT table_owner, table_name, db_link 
    FROM dba_synonyms 
WHERE owner  = 'PUBLIC' and db_l 

чернила не является нулевым

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

+0

Ну, вы только проверяете там ОБЩЕСТВЕННЫЕ синонимы. Вы также должны проверить схему, которая владеет пакетом, и, возможно, тот, кто ее вызывает, если они разные. – 2008-10-31 17:21:36

1

Я понятия не имею, почему вы получаете ошибку синонима. Но это много кода для чего-то, что должно быть единственным оператором 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; 

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

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

Смежные вопросы