prog:sql_aenderungs_datum_tabellen_eintraege
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
prog:sql_aenderungs_datum_tabellen_eintraege [2013/09/08 16:51] – angelegt gpipperr | prog:sql_aenderungs_datum_tabellen_eintraege [2013/09/08 21:47] (aktuell) – gpipperr | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | {{: | ||
+ | |||
+ | |||
+ | Mit Hilfe der Oracle Spalte ora_rowscn ist es möglich, den Zeitraum der letzten Bearbeitung von Daten in einer Tabelle ein zu grenzen. | ||
+ | |||
+ | |||
+ | Die ora_rowscn gibt die SCN (System Change Number) der Datenbank wieder, an der zum letzten Mal der Block, in dem sich die Daten befinden, bearbeitet wurde. | ||
+ | |||
+ | Beispiel: | ||
+ | <code sql> | ||
+ | select ora_rowscn, | ||
+ | |||
+ | ORA_ROWSCN DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) | ||
+ | ---------- ------------------------------------ ---------- | ||
+ | | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | | ||
+ | | ||
+ | # einen Datensatz aus Block 1046 ändern | ||
+ | update emp set ename=' | ||
+ | | ||
+ | 26540504 | ||
+ | 26540504 | ||
+ | ... | ||
+ | # alle Daten sehen nun aus als ob sich etwas geändert hat! | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Row-level dependency tracking === | ||
+ | |||
+ | Soll der Zeitpunkt genauer erkannt werden, muss auf der Tabelle zusätzlich die Tabellen Eigenschaft [[http:// | ||
+ | |||
+ | Das kostet aber pro Datensatz zusätzliche 6 Byte! | ||
+ | Auch lässt sich das nicht nachträglich per "Alter Table" Befehlt aktivieren, die Tabelle muss neu angelegt werden. | ||
+ | |||
+ | Beispiel: | ||
+ | <code sql> | ||
+ | |||
+ | create table emp_r ROWDEPENDENCIES as select * from emp; | ||
+ | |||
+ | select ora_rowscn, | ||
+ | |||
+ | ORA_ROWSCN DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) | ||
+ | |||
+ | ---------- ------------------------------------ ---------- | ||
+ | ... | ||
+ | 26543115 | ||
+ | 26543115 | ||
+ | 26543115 | ||
+ | ... | ||
+ | |||
+ | # update | ||
+ | update emp_r set ename=' | ||
+ | commit; | ||
+ | |||
+ | # test again: | ||
+ | |||
+ | select ora_rowscn, | ||
+ | |||
+ | |||
+ | ORA_ROWSCN DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) | ||
+ | |||
+ | ---------- ------------------------------------ ---------- | ||
+ | ... | ||
+ | 26543115 | ||
+ | 26544169 | ||
+ | 26543115 | ||
+ | ... | ||
+ | |||
+ | </ | ||
+ | Nun kann auf Datensatz eben erkannt werden, ob sich ein Datensatz verändert hat. | ||
+ | Dies lässt sich zum Beispiel gut bei Web Applikationen dazu verwenden, um zu erkennen, ob nach dem letzten Lesen ein andere User die Daten inzwischen verändert hat um mehr Transaktionssicherheit bei zustandlosen Applikationen zu implementieren. | ||
+ | |||
+ | |||
+ | ==== Aus der SCN den Zeitraum der Daten Änderung erkennen bzw. eingrenzen ==== | ||
+ | |||
+ | Mit der Methode SCN_TO_TIMESTAMP lässt sich bei noch relativ " | ||
+ | |||
+ | Bei älteren Daten ist dies aber oft nicht mehr möglich, hier hilft es dann nur noch über die View V$LOG_HISTORY den ungefähren Zeitraum zu ermitteln. | ||
+ | |||
+ | === Beispiel Script === | ||
+ | |||
+ | <code sql tab_last.sql > | ||
+ | SET linesize 130 pagesize 300 recsep OFF | ||
+ | SET verify off | ||
+ | |||
+ | define OWNER = '& | ||
+ | define TAB_NAME = '& | ||
+ | define FILTER | ||
+ | |||
+ | prompt | ||
+ | prompt Parameter 1 = Owner Name => && | ||
+ | prompt Parameter 2 = Tab Name => && | ||
+ | prompt Parameter 3 = Tab Name => && | ||
+ | prompt | ||
+ | |||
+ | set serveroutput on; | ||
+ | |||
+ | declare | ||
+ | |||
+ | v_tab_owner varchar2(32): | ||
+ | v_tab_name | ||
+ | v_filter | ||
+ | v_sql | ||
+ | v_max_scn | ||
+ | v_min_scn | ||
+ | v_count | ||
+ | |||
+ | function getSCNTime(p_scn number) | ||
+ | return varchar2 | ||
+ | is | ||
+ | v_return varchar2(20); | ||
+ | begin | ||
+ | |||
+ | select to_char(FIRST_TIME,' | ||
+ | from V$LOG_HISTORY | ||
+ | where p_scn between FIRST_CHANGE# | ||
+ | |||
+ | exception | ||
+ | when others then | ||
+ | |||
+ | select to_char(min(FIRST_TIME),' | ||
+ | from V$LOG_HISTORY | ||
+ | where FIRST_CHANGE# | ||
+ | |||
+ | return 'no exact value found but older then :: ' | ||
+ | |||
+ | end; | ||
+ | begin | ||
+ | |||
+ | v_sql: | ||
+ | |||
+ | if length(v_filter) > 1 then | ||
+ | v_sql: | ||
+ | end if; | ||
+ | |||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | |||
+ | execute immediate v_sql into v_max_scn, | ||
+ | |||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | |||
+ | if v_count > 0 then | ||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | |||
+ | begin | ||
+ | dbms_output.put_line(' | ||
+ | exception | ||
+ | when others then | ||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | end; | ||
+ | dbms_output.put_line(' | ||
+ | begin | ||
+ | dbms_output.put_line(' | ||
+ | exception | ||
+ | when others then | ||
+ | dbms_output.put_line(' | ||
+ | dbms_output.put_line(' | ||
+ | end; | ||
+ | else | ||
+ | dbms_output.put_line(' | ||
+ | end if; | ||
+ | |||
+ | end; | ||
+ | / | ||
+ | |||
+ | </ | ||
+ | |||
+ | Aktuellste Version des Scripts | ||
+ | |||
+ | |||
+ | ==== Quellen ==== | ||
+ | |||
+ | * http:// | ||
+ | * http:// | ||
+ | |||
prog/sql_aenderungs_datum_tabellen_eintraege.txt · Zuletzt geändert: 2013/09/08 21:47 von gpipperr