Авг 052014
 

Dblink - интересный и в то же время неприятный объект. Дело в том, что в синтаксисе Oracle нет способа просто проверить, работает он или нет, если он находится в другой схеме. Доступ через точку, в отличие от других объектов, не работает, т.к. точка может являться частью имени dblink'а.
Возникла задача: проверить работоспособность всех линков в базе. Просто SQL-запрос сделать не удалось (это, на мой взгляд, всегда немного элегантнее и удобнее, чем блок PL/SQL), но нашлось отличное решение индийского коллеги: вот. Скрипт хороший, но он пишет текстовый лог, что неудобно, если у нас действительно много линков. Я немного его модифицировал, теперь он создаёт табличку, в которую пишет имя линка, его владельца и статус проверки. Так будет удобнее работать со списком, можно будет применять к нему любые фильтры и сортировки и использовать его для генерации скриптов, например, для удаления лишних dblink'ов.
Итак, скрипт:

CREATE TABLE check_links
  (
    owner  VARCHAR(255),
    dblink VARCHAR(255),
    status VARCHAR(3)
  );
 
DECLARE
  l_result VARCHAR2(1000);
  l_status NUMBER DEFAULT NULL;
  l_cursor INTEGER;
BEGIN
  EXECUTE IMMEDIATE ('ALTER SESSION SET GLOBAL_NAMES=FALSE');
  FOR c1 IN
  (SELECT u.user_id ,
	      d.owner ,
          d.db_link
    FROM dba_db_links d, dba_users u
    WHERE d.owner = u.username
    ORDER BY d.owner
  )
  LOOP
    BEGIN
      l_cursor:=sys.dbms_sys_sql.open_cursor();
      sys.dbms_sys_sql.parse_as_user(l_cursor,'SELECT * FROM global_name@' || c1.db_link, dbms_sql.native, c1.user_id);
      sys.dbms_sys_sql.define_column(l_cursor, 1, l_result, 1000);
      l_status := sys.dbms_sys_sql.EXECUTE(l_cursor);
      IF ( dbms_sys_sql.fetch_rows(l_cursor) > 0 ) THEN
        dbms_sys_sql.column_value(l_cursor, 1, l_result );
      END IF;      
      INSERT INTO sys.check_links VALUES
        (c1.owner, c1.db_link, 'OK');
      COMMIT;
      sys.dbms_sys_sql.close_cursor(l_cursor);
      COMMIT;
    EXCEPTION
    WHEN OTHERS THEN
      INSERT INTO sys.check_links VALUES
        (c1.owner, c1.db_link, 'ERR');
      COMMIT;
    END;
  END LOOP;
END ;
/

Когда мы определились со списком ненужных линков, будем их удалять. Создадим ещё одну процедуру drop_dblink (спасибо другому коллеге):

CREATE OR REPLACE PROCEDURE drop_dblink(
    schemaname VARCHAR2,
    dbLink     VARCHAR2 )
IS
  plsql VARCHAR2(1000);
  cur   NUMBER;
  UID   NUMBER;
  rc    NUMBER;
BEGIN
  SELECT u.user_id INTO UID FROM dba_users u WHERE u.username = schemaName;
  plsql := 'DROP DATABASE LINK "'||dbLink||'"';
  cur   := SYS.DBMS_SYS_SQL.open_cursor;
  SYS.DBMS_SYS_SQL.parse_as_user( c => cur, STATEMENT => plsql, language_flag => DBMS_SQL.native, userID => UID );
  rc := SYS.DBMS_SYS_SQL.EXECUTE(cur);
  SYS.DBMS_SYS_SQL.close_cursor(cur);
END;
/

Теперь можем ей пользоваться для удаления:

EXEC drop_dblink('CUBE', 'MY_LINK');

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

(обязательно)

(обязательно)