2015-04-20 4 views
0

я написал следующую функцию:Oracle Функция Получить Последнее обновление тайминг всех таблиц в схеме

declare 
    v_count DATE; 
    strsql VARCHAR2(200); 
begin 

    for r in (select OBJECT_NAME from all_objects where OBJECT_TYPE='TABLE' 
    and OWNER='SALES' 
    and OBJECT_NAME LIKE 'T%' 
    ORDER BY OBJECT_NAME DESC) 
    loop 
     DBMS_OUTPUT.PUT_LINE(r.OBJECT_NAME); 
     strsql := 'select SCN_TO_TIMESTAMP(MAX(ORA_ROWSCN)) FROM : 1 INTO v_count'; 
     execute immediate strsql USING r.OBJECT_NAME; 
      DBMS_OUTPUT.PUT_LINE(v_count); 
    end loop; 

end; 

К сожалению, два (плохие) вещи происходят:

  1. Он выдает только первый OBJECT_NAME (первый PUT_LINE).
  2. Он НЕ выполняет вторую PUT_LINE.

Очевидно, что я НЕ разработчик Oracle, мне просто нужна быстрая и грязная функция, чтобы показать мне последнее обновленное время для всех таблиц в данной схеме.

Может ли кто-нибудь сказать мне, что я сделал не так?

+0

По обновлению, LAST_DDL_TIME во всех объектах дает вам правильную информацию? – kevinsky

+0

LAST_DDL_TIME, по документам, - это когда последняя таблица была изменена с помощью команды DDL (включая Grants/Revokes). Мне нужна последняя вставка/обновление/удаление. – Jason

ответ

0

После кучу работы, поломки, консультации с almigty Google, я пришел с этой функцией:

declare 
    v_count TIMESTAMP; 
    strsql VARCHAR2(200); 
    tblname VARCHAR2(32); 
begin 

    for r in (select OBJECT_NAME from all_objects where OBJECT_TYPE='TABLE' 
    and OWNER='SALES' 
    and OBJECT_NAME LIKE 'T%' 
    ORDER BY OBJECT_NAME) 
    loop 
     begin 
     tblname := R.OBJECT_NAME; 
     strsql := 'select SCN_TO_TIMESTAMP(MAX(ORA_ROWSCN)) FROM SALES.' || tblname; 
     execute immediate strsql into v_count; 
     DBMS_OUTPUT.PUT_LINE(tblname || ' ' || v_count); 
     EXCEPTION 
     when others then 
      null; 
     end; 
    end loop; 
end; 

ORA_ROWSCN проводится в течение ограниченного периода времени, так если он не будет, будет выбрано исключение. Если бы я написал это «правильно», он только вернул бы нуль для ORA-006550, и я бы выяснил способ сортировки результатов по SCN (но нисходящий).

1

Ваш strsql содержит неправильный SQL, который не может быть выполнен. Итак, первый execute immediate вызывает исключение (конечно, вы его видели).

Имя таблицы не может использоваться из параметра. Вы должны что-то вроде

strsql := 'select .... from ' || r.owner || '.' || r.object_name; 
+0

Да, я видел это (хотя мне потребовалось немного, чтобы посмотреть, что я искал). К сожалению, похоже, что информация сохраняется только в течение относительно короткого времени, поэтому, если я столкнулся с таблицей, которая не была изменена, возникает ошибка SQL. – Jason

+0

Кроме того, ваша точка при определении имени таблицы с владельцем берется, это просто работает для меня, потому что существуют некоторые синомы. – Jason

+0

@Jason - также ваше предложение 'in' должно находиться в' execute instant', а не в строке; и у вас больше не будет предложения 'using', так как имя объекта не может быть связано. Но, как вы обнаружили, вы не можете полагаться на ora_rowscn на то, что вы пытаетесь выяснить. –

0

Пожалуйста, измените тип даты v_count на метку времени и выберите пункт в strsql следующим образом.

SQL>  declare 
    2   v_count timestamp; 
    3   strsql VARCHAR2(200); 
    4  begin 
    5 
    6   for r in (select OBJECT_NAME from all_objects 
    7   where OBJECT_TYPE='TABLE' 
    8   and OWNER='SCOTT' 
    9   and OBJECT_NAME like'T%' 
10   ) 
11   loop 
12    DBMS_OUTPUT.PUT_LINE(r.OBJECT_NAME); 
13    strsql := 'select SCN_TO_TIMESTAMP(MAX(ORA_ROWSCN)) FROM '||r.OBJECT_NAME || ' '; 
14    execute immediate strsql into v_count; 
15     DBMS_OUTPUT.PUT_LINE(v_count); 
16   end loop; 
17 
18  end; 
19  /
TESTEMP 
21-APR-15 11.52.20.000000 AM 
TESTEMP2 
20-APR-15 09.53.12.000000 PM 
TEST_AUDIT 
21-APR-15 11.52.20.000000 AM 

PL/SQL procedure successfully completed.