Facciamo un esempio: due utenti di una webapp caricano una form di attributi di una stessa persona (identificata solamente da una chiave primaria) e li modificano nello stesso intervallo di tempo. Trascurando l'opportunità della cosa, l'ultima che avrà cliccato su "aggiorna" scriverà i dati della form nel database, sovrascrivendo eventuali modifiche fatte dal primo utente.
Ci sono un paio di metodi per accorgersi questa situazione: fare la "SELECT FOR UPDATE" appena prima di modificare il record inserendo una condizione WHERE che contiene tutti i dati originali, oppure usare una colonna timestamp per sapere la data di ultima modifica.
Non ci interessa invece che cosa fa l'applicazione una volta accortasi della cosa: ciò dipende dalla business logic, ovvero dal tipo di applicazione.
In Oracle 10g è presente una nuova pseudo-colonna: ORA_ROWSCN. Essa contiene l'SCN relativo all'ultima operazione DML effettuata sul blocco che contiene la riga selezionata. In questo modo è possibile sapere se il blocco è stato modificato dall'ultima lettura effettuata; ma come si fa ad utilizzare a livello di riga? La dipendenza a livello di riga viene abilitata all'atto di creazione di una tabella con la clausola ROWDEPENDENCIES.
Facciamo un esempio:
SQL> select CLAIM_NUM, CLAIM_AMT, CLAIM_BAL, ROWID, ORA_ROWSCN
from claim;
CLAIM_NUM CLAIM_AMT CLAIM_BAL ROWID ORA_ROWSCN
---------- ---------- ---------- ------------------ ----------
1 100 0 AAAdsYAAEAAAAD0AAA 1070257362
2 200 99 AAAdsYAAEAAAAD0AAB 1070257362
3 300 0 AAAdsYAAEAAAAD0AAC 1070257362
4 400 350 AAAdsYAAEAAAAD0AAD 1070257362
5 500 0 AAAdsYAAEAAAAD0AAE 1070257362
6 600 295 AAAdsYAAEAAAAD0AAF 1070257362
7 700 700 AAAdsYAAEAAAAD0AAG 1070257362
8 800 800 AAAdsYAAEAAAAD0AAH 1070257362
8 rows selected.
SQL> update claim set CLAIM_BAL = 1 where claim_num = 1;
1 row updated.
SQL> select CLAIM_NUM, CLAIM_AMT, CLAIM_BAL, ROWID, ORA_ROWSCN
from claim;
CLAIM_NUM CLAIM_AMT CLAIM_BAL ROWID ORA_ROWSCN
---------- ---------- ---------- ------------------ ----------
1 100 1 AAAdsYAAEAAAAD0AAA 1070257362
2 200 99 AAAdsYAAEAAAAD0AAB 1070257362
3 300 0 AAAdsYAAEAAAAD0AAC 1070257362
4 400 350 AAAdsYAAEAAAAD0AAD 1070257362
5 500 0 AAAdsYAAEAAAAD0AAE 1070257362
6 600 295 AAAdsYAAEAAAAD0AAF 1070257362
7 700 700 AAAdsYAAEAAAAD0AAG 1070257362
8 800 800 AAAdsYAAEAAAAD0AAH 1070257362
8 rows selected.
SQL> commit;
Commit complete.
SQL> select CLAIM_NUM, CLAIM_AMT, CLAIM_BAL, ROWID, ORA_ROWSCN
from claim;
CLAIM_NUM CLAIM_AMT CLAIM_BAL ROWID ORA_ROWSCN
---------- ---------- ---------- ------------------ ----------
1 100 1 AAAdsYAAEAAAAD0AAA 1201770241
2 200 99 AAAdsYAAEAAAAD0AAB 1201770241
3 300 0 AAAdsYAAEAAAAD0AAC 1201770241
4 400 350 AAAdsYAAEAAAAD0AAD 1201770241
5 500 0 AAAdsYAAEAAAAD0AAE 1201770241
6 600 295 AAAdsYAAEAAAAD0AAF 1201770241
7 700 700 AAAdsYAAEAAAAD0AAG 1201770241
8 800 800 AAAdsYAAEAAAAD0AAH 1201770241
8 rows selected.
SQL> create table claim_rowdep ROWDEPENDENCIES
as select * from claim;
Table created.
SQL> select CLAIM_NUM, CLAIM_AMT, CLAIM_BAL, ROWID, ORA_ROWSCN
from claim_rowdep;
CLAIM_NUM CLAIM_AMT CLAIM_BAL ROWID ORA_ROWSCN
---------- ---------- ---------- ------------------ ----------
1 100 1 AAAlQ9AAEAAAAIEAAA 1201772166
2 200 99 AAAlQ9AAEAAAAIEAAB 1201772166
3 300 0 AAAlQ9AAEAAAAIEAAC 1201772166
4 400 350 AAAlQ9AAEAAAAIEAAD 1201772166
5 500 0 AAAlQ9AAEAAAAIEAAE 1201772166
6 600 295 AAAlQ9AAEAAAAIEAAF 1201772166
7 700 700 AAAlQ9AAEAAAAIEAAG 1201772166
8 800 800 AAAlQ9AAEAAAAIEAAH 1201772166
8 rows selected.
SQL> update claim_rowdep set claim_bal = 0 where claim_num = 1;
1 row updated.
SQL> select CLAIM_NUM, CLAIM_AMT, CLAIM_BAL, ROWID, ORA_ROWSCN
from claim_rowdep;
CLAIM_NUM CLAIM_AMT CLAIM_BAL ROWID ORA_ROWSCN
---------- ---------- ---------- ------------------ ----------
1 100 0 AAAlQ9AAEAAAAIEAAA
2 200 99 AAAlQ9AAEAAAAIEAAB 1201772166
3 300 0 AAAlQ9AAEAAAAIEAAC 1201772166
4 400 350 AAAlQ9AAEAAAAIEAAD 1201772166
5 500 0 AAAlQ9AAEAAAAIEAAE 1201772166
6 600 295 AAAlQ9AAEAAAAIEAAF 1201772166
7 700 700 AAAlQ9AAEAAAAIEAAG 1201772166
8 800 800 AAAlQ9AAEAAAAIEAAH 1201772166
8 rows selected.
SQL> commit;
Commit complete.
SQL> select CLAIM_NUM, CLAIM_AMT, CLAIM_BAL, ROWID, ORA_ROWSCN
from claim_rowdep;
CLAIM_NUM CLAIM_AMT CLAIM_BAL ROWID ORA_ROWSCN
---------- ---------- ---------- ------------------ ----------
1 100 0 AAAlQ9AAEAAAAIEAAA 1201772868
2 200 99 AAAlQ9AAEAAAAIEAAB 1201772166
3 300 0 AAAlQ9AAEAAAAIEAAC 1201772166
4 400 350 AAAlQ9AAEAAAAIEAAD 1201772166
5 500 0 AAAlQ9AAEAAAAIEAAE 1201772166
6 600 295 AAAlQ9AAEAAAAIEAAF 1201772166
7 700 700 AAAlQ9AAEAAAAIEAAG 1201772166
8 800 800 AAAlQ9AAEAAAAIEAAH 1201772166
8 rows selected.
Come si vede dal ROWID i dati stanno tutti nello stesso blocco, mentre il ROWSCN cambia per tutto il blocco nella tabella claim e solo per la riga interessata dall'update nella tabella claim_rowdep.
Non è possibile aggiungere ROWDEPENDENCIES alla tabella già creata, bisogna farlo alla creazione: la clausola infatti comporta che ogni riga aumenti le proprie dimensioni di 6 bytes.













