ORA-01775:同义词的循环链但没有同义词

时间:2008-10-31 15:15:49

标签: oracle stored-procedures

无法弄清楚为什么我在这个存储过程的第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;

2 个答案:

答案 0 :(得分:1)

我不知道你为什么会得到同义词错误。但这是一些应该是单个DELETE语句的代码。我假设您已将其更改为commit-every-n以避免回滚错误。如果你能让你的DBA增加撤销空间,那么你可以真正完成你需要做的工作。如果做不到这一点,我认为你仍然可以让它更简单:

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;

如果你愿意的话,你可以抛出你的重试逻辑。

如果我错过了一些与你正在做的不同的微妙之处,请道歉。

答案 1 :(得分:0)

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

返回0行 据我所知,没有同义词.......