LAST_DDL_TIME vs TIMESTAMP nas views DBA/ALL/USER_OBJECTS. Tem diferença?

Por Eduardo Legatti
Postado en julho 2013

Não é raro muita gente confundir essas duas colunas existentes nas views de dicionário de dados DBA/ALL/USER_OBJECTS. Afinal, qual é a diferença entre elas? Quando é que a informação de data e horário de uma é atualizada e da outra não? Pois bem, vamos então a alguns exemplos práticos de forma a demonstrar essa diferença.

C:\>sqlplus scott/tiger

SQL*Plus: Release 10.2.0.1.0 - Production on Seg Mai 2 11:49:38 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Conectado a:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> desc user_objects
 Nome                          Nulo?    Tipo
 ----------------------------- -------- ----------------------------
 OBJECT_NAME                            VARCHAR2(128)
 SUBOBJECT_NAME                         VARCHAR2(30)
 OBJECT_ID                              NUMBER
 DATA_OBJECT_ID                         NUMBER
 OBJECT_TYPE                            VARCHAR2(19)
 CREATED                                DATE
 LAST_DDL_TIME                          DATE
 TIMESTAMP                              VARCHAR2(19)
 STATUS                                 VARCHAR2(7)
 TEMPORARY                              VARCHAR2(1)
 GENERATED                              VARCHAR2(1)
 SECONDARY                              VARCHAR2(1)

Primeiramente, podemos perceber que LAST_DDL_TIME é uma coluna do tipo DATE e TIMESTAMP, por incrível que pareça, é um VARCHAR2(19). Irei criar abaixo uma tabela de exemplo e realizar algumas operações nela.

SQL> create table t1 (id number);

Tabela criada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='T1';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
T1              02/05/2011 11:59:00 02/05/2011 11:59:00 2011-05-02:11:59:00

Acima, podemos perceber que tanto a coluna CREATED, como LAST_DDL_TIME e TIMESTAMP possuem a mesma informação de data e horário. O que acontece se modificarmos a estrutura da tabela?

SQL> alter table t1 modify id number(10,2);

Tabela alterada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='T1';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
T1              02/05/2011 11:59:00 02/05/2011 12:00:00 2011-05-02:12:00:00

Ambas as colunas LAST_DDL_TIME e TIMESTAMP tiveram suas informações atualizadas. Mas, o que acontece agora se eu simplesmente conceder alguns privilégios (SELECT, por exemplo) para algum outro usuário?

SQL> grant select on t1 to adam;

Concessão bem-sucedida.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='T1';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
T1              02/05/2011 11:59:00 02/05/2011 12:02:00 2011-05-02:12:00:00

Podemos perceber que somente a coluna LAST_DDL_TIME teve sua informação atualizada, apesar do comando GRANT ser um comando DCL (Data Control Language). No mais, podemos perceber abaixo que o comando REVOKE terá o mesmo efeito apenas na coluna LAST_DDL_TIME.

SQL> revoke select on t1 from adam;

Revogação bem-sucedida.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='T1';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
T1              02/05/2011 11:59:00 02/05/2011 12:04:00 2011-05-02:12:00:00

Existem mais comandos que afetam apenas a coluna LAST_DDL_TIME e não a coluna TIMESTAMP? Sim.

SQL> alter table t1 move;

Tabela alterada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='T1';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
T1              02/05/2011 11:59:00 02/05/2011 12:06:00 2011-05-02:12:00:00

SQL> insert into t1 values (1);

1 linha criada.

SQL> commit;

Commit concluído.

SQL> truncate table t1;

Tabela truncada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='T1';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
T1              02/05/2011 11:59:00 02/05/2011 12:08:00 2011-05-02:12:00:00

Perceberam que o comando ALTER TABLE MOVE... e TRUNCATE TABLE... atualizaram apenas a coluna LAST_DDL_TIME? Irei agora realizar o mesmo teste só que agora com uma FUNCTION. (obs: Poderia também ser uma STORED PROCEDURE ou uma TRIGGER).

SQL> create or replace function data_atual return date is
  2   data date;
  3  begin
  4     select sysdate into data from dual;
  5     return data;
  6  end;
  7  /

Função criada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='DATA_ATUAL';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
DATA_ATUAL      02/05/2011 12:59:00 02/05/2011 12:59:00 2011-05-02:12:59:00

Acima, podemos perceber que tanto a coluna CREATED, como LAST_DDL_TIME e TIMESTAMP possuem a mesma informação de data e horário. O que acontece se modificarmos o código PL/SQL da função?

SQL> create or replace function data_atual return date is
  2   data date;
  3  begin
  4     select sysdate+1 into data from dual;
  5     return data;
  6  end;
  7  /

Função criada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='DATA_ATUAL';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
DATA_ATUAL      02/05/2011 12:59:00 02/05/2011 13:00:00 2011-05-02:13:00:00

Ambas as colunas LAST_DDL_TIME e TIMESTAMP tiveram suas informações atualizadas. Mas, o que acontece se eu simplesmente conceder alguns privilégios (EXECUTE, por exemplo) para algum outro usuário?

SQL> grant execute on data_atual to adam;

Concessão bem-sucedida.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='DATA_ATUAL';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
DATA_ATUAL      02/05/2011 12:59:00 02/05/2011 13:02:00 2011-05-02:13:00:00

Podemos perceber que somente a coluna LAST_DDL_TIME teve sua informação atualizada. Vale a penas salientar que o comando REVOKE terá o mesmo efeito. O que acontece agora se apenas compilarmos a função sem qualquer alteração em seu código fonte?

SQL> alter function data_atual compile;

Função alterada.

SQL> select object_name,created,last_ddl_time,timestamp
  2    from user_objects
  3   where object_name='DATA_ATUAL';

OBJECT_NAME     CREATED             LAST_DDL_TIME       TIMESTAMP
--------------- ------------------- ------------------- -------------------
DATA_ATUAL      02/05/2011 12:59:00 02/05/2011 13:04:00 2011-05-02:13:00:00

Novamente podemos perceber que somente a coluna LAST_DDL_TIME teve sua informação atualizada.

A coluna LAST_DDL_TIME armazena a informação de data e horário sobre a última vez quando o objeto foi modificado por uma instrução DDL, incluindo alguns comandos que envolvam modificações no nível de extensões (extents) do segmento. Vale a pena salientar que essa modificação também vale para comandos DCL como (GRANT e REVOKE) que foram lançados sobre o objeto. Isso também vale para os objetos PL/SQL como functions, stored procedures, triggers, entre outros, incluindo-se o comando COMPILE executado sobre o mesmo.

Por fim, a coluna TIMESTAMP armazena a informação de data e horário sobre a última vez quando o objeto foi modificado, excluindo-se qualquer operação DCL (GRANT, REVOKE) e excluindo-se também alguns comandos DDL que afetem o objeto no nível de extensões (extents) do segmento. No caso de objetos PL/SQL, exclui-se também o comando COMPILE.

Portanto, se quiser saber realmente quando houve alguma modificação estrutural na tabela ou alguma modificação no código de um de objeto PL/SQL, confie na coluna TIMESTAMP.


Eduardo Legatti é Analista de Sistemas e DBA Oracle. É pós graduado em Gerência da Tecnologia da Informação, possui as certificações OCA 9i - OCP 9i/10g/11g – OCE, e vem trabalhando como DBA Oracle desde a versão 8.0.5. Freqüentemente posta artigos em http://eduardolegatti.blogspot.com