Oracle Database : Comment retrouver la date et l’heure de modification d’une donnée

Il arrive qu’à la suite d’un incident applicatif, il soit nécessaire de retrouver toutes les lignes modifiées depuis un instant T.
Depuis Oracle Database 10g, une pseudo-colonne ORA_ROWSCN a été ajoutée et peut-être utilisée pour retrouver la date et l’heure de la dernière mise à jour d’une ligne ou du dernier commit concernant le block dans lequel elle se trouve.
Par défaut, cette pseudo-colonne affiche le numéro de SCN du dernier commit enregistré concernant le block mais si la clause « ROWDEPENDENCIES » est utilisée à la création de la table, la pseudo-colonne ORA_ROWSCN affiche le numéro de SCN de la dernière mise à jour validée de la ligne.
Etudions en détail le fonctionnement avec quelques exemples :

Consulter la caractéristique « ROWDEPENDENCIES » des tables :

SQL> SELECT table_name, dependencies
  2  FROM   user_tables;
TABLE_NAME                     DEPENDEN
------------------------------ --------
DEPT                           DISABLED
EMP                            DISABLED
SALGRADE                       DISABLED
DEPT_BIS                       ENABLED

Comportement par défaut (pas de clause ROWDEPENDENCIES sur la table) :

SQL> SELECT ora_rowscn,
  2         scn_to_timestamp(ora_rowscn) date_heure_scn,
  3        DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) num_block,
  4        deptno,dname,loc
  5  FROM   dept;
ORA_ROWSCN DATE_HEURE_SCN                  NUM_BLOCK     DEPTNO DNAME          LOC
---------- ------------------------------ ---------- ---------- -------------- -------------
   3832477 01/07/11 10:05:42,000000000           135         10 ACCOUNTING     NEW YORK
   3832477 01/07/11 10:05:42,000000000           135         20 RESEARCH       PARIS
   3832477 01/07/11 10:05:42,000000000           135         30 SALES          CHICAGO
   3832477 01/07/11 10:05:42,000000000           135         40 OPERATIONS     BOSTON
SQL> UPDATE dept
  2  SET     loc = 'XXXX'
  3  WHERE   deptno = 20;
1 row updated.
SQL> SELECT ora_rowscn,
  2         scn_to_timestamp(ora_rowscn) date_heure_scn,
  3        DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) num_block,
  4        deptno,dname,loc
  5  FROM   dept;
ORA_ROWSCN DATE_HEURE_SCN                  NUM_BLOCK     DEPTNO DNAME          LOC
---------- ------------------------------ ---------- ---------- -------------- -------------
   3832477 01/07/11 10:05:42,000000000           135         10 ACCOUNTING     NEW YORK
   3832477 01/07/11 10:05:42,000000000           135         20 RESEARCH       XXXX
   3832477 01/07/11 10:05:42,000000000           135         30 SALES          CHICAGO
   3832477 01/07/11 10:05:42,000000000           135         40 OPERATIONS     BOSTON
SQL>
SQL> COMMIT;
Commit complete.
SQL> SELECT ora_rowscn,
  2         scn_to_timestamp(ora_rowscn) date_heure_scn,
  3        DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) num_block,
  4        deptno,dname,loc
  5  FROM   dept;
ORA_ROWSCN DATE_HEURE_SCN                  NUM_BLOCK     DEPTNO DNAME          LOC
---------- ------------------------------ ---------- ---------- -------------- -------------
   3832489 01/07/11 10:05:54,000000000           135         10 ACCOUNTING     NEW YORK
   3832489 01/07/11 10:05:54,000000000           135         20 RESEARCH       XXXX
   3832489 01/07/11 10:05:54,000000000           135         30 SALES          CHICAGO
   3832489 01/07/11 10:05:54,000000000           135         40 OPERATIONS     BOSTON

Si la clause « ROWDEPENDENCIES » est utilisée à la création de la table, la pseudo-colonne ORA_ROWSCN affiche le numéro de SCN de la dernière mise à jour validée de la ligne :

SQL> CREATE TABLE dept_bis ROWDEPENDENCIES AS SELECT * FROM dept;
Table created.
SQL>
SQL> SELECT ora_rowscn,
  2         scn_to_timestamp(ora_rowscn) date_heure_scn,
  3        DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) num_block,
  4        deptno,dname,loc
  5  FROM   dept_bis;
 ORA_ROWSCN DATE_HEURE_SCN                  NUM_BLOCK     DEPTNO DNAME          LOC
---------- ------------------------------ ---------- ---------- -------------- -------------
   3832818 01/07/11 10:08:19,000000000           555         10 ACCOUNTING     NEW YORK
   3832818 01/07/11 10:08:19,000000000           555         20 RESEARCH       XXXX
   3832818 01/07/11 10:08:19,000000000           555         30 SALES          CHICAGO
   3832818 01/07/11 10:08:19,000000000           555         40 OPERATIONS     BOSTON
SQL> UPDATE dept_bis
  2  SET     loc = 'PARIS'
  3  WHERE   deptno = 20;
 1 row updated.
SQL> SELECT ora_rowscn,
  2        DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) num_block,
  3        deptno,dname,loc
  4  FROM   dept_bis;
 ORA_ROWSCN  NUM_BLOCK     DEPTNO DNAME          LOC
---------- ---------- ---------- -------------- -------------
   3832818        555         10 ACCOUNTING     NEW YORK
                  555         20 RESEARCH       PARIS
   3832818        555         30 SALES          CHICAGO
   3832818        555         40 OPERATIONS     BOSTON
SQL> COMMIT;
 Commit complete.
SQL> SELECT ora_rowscn,
  2         scn_to_timestamp(ora_rowscn) date_heure_scn,
  3        DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) num_block,
  4        deptno,dname,loc
  5  FROM   dept_bis;
 ORA_ROWSCN DATE_HEURE_SCN                  NUM_BLOCK     DEPTNO DNAME          LOC
---------- ------------------------------ ---------- ---------- -------------- -------------
   3832818 01/07/11 10:08:19,000000000           555         10 ACCOUNTING     NEW YORK
   3832845 01/07/11 10:08:19,000000000           555         20 RESEARCH       PARIS
   3832818 01/07/11 10:08:19,000000000           555         30 SALES          CHICAGO
   3832818 01/07/11 10:08:19,000000000           555         40 OPERATIONS     BOSTON

Facile et utile dans bien des cas, je ne saurai que vous recommander d’utiliser cette fonctionnalité !

6 réflexions sur “Oracle Database : Comment retrouver la date et l’heure de modification d’une donnée”

  1. Bonjour,
    peux ton positionner la bonne clause ROWDEPENDENCIES après coup (via un alter table) plutot que de devoir backuper/supprimer/recreer avec la clause/restorer la table ?
    Merci !

  2. Bonjour,
    c’est le le numéro de SCN qui couvre une fenêtre de 3 secondes en 11g, j’ai dû être rapide entre le « create table » et le « commit ».
    Si vous prenez votre temps entre les deux, il y a bien une heure différente.

  3. Bonjour,
    je ne comprends pas pourquoi à la fin le ORA_ROW_SCN change bien lui pour la ligne modifiée et pas la DATE_HEURE_SCN

  4. Hervé Etché

    Désolé, j’avais juste testé la première partie…j’avais completement échappé la fin…désolé…

  5. Hervé Etché

    Bonjour,
    Bel article. Mais le problème avec ça, c’est que la requête ramène tous les enregistrements ayant le même ORA_ROWSCN. Si un seul enregistrement a été modifié comme c’est le cas dans votre exemple, comment le retrouver?
    Merci

Les commentaires sont fermés.