ROWID, ROWNUM, ORA_ROWSCN

In una tabella ogni record è, in un certo senso, identificabile dai dati che contiene, ma esistono altri modi per riferirsi ad un record…

ROWID

Il valore ROWID è una pseudocolonna (cioè non esiste effettivamente) ed è specifico per ogni record.

Il ROWID è una informazione strutturata, infatti un certo record si trova in un certo datafile, in un certo blocco e all’interno del blocco avrà una sua posizione.

Creiamo una nuova tabella:

CREATE TABLE QPRODOTTI (QEAN VARCHAR2(20), QDESCRI VARCHAR2(30), QPREZZO NUMBER, QSTATO VARCHAR2(10))  ;

ed aggiungiamo dei record:

INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('12345','DENTIFRICIO',2.25,'ATTIVO');
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('22345','SPAZZOLINO',3.55,'ATTIVO');
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('32345','LAMETTE RASOIO',5.05,'ATTIVO');
COMMIT;

Ora verifichiamo i rowid:

select rowid , 
SUBSTR(rowid,1,6)||'=>'||
TO_NUMBER(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(
LPAD(SUBSTR(rowid,1, 6), 8, 'A'))), 'XXXXXXXXXXXX') as NUMOBJ,
SUBSTR(rowid,7,3)||'=>'||
TO_NUMBER(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(
LPAD(SUBSTR(rowid, 7, 3), 4, 'A'))), 'XXXXXX') as NUMFILE,
SUBSTR(rowid,10,6)||'=>'||
TO_NUMBER(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(
LPAD(SUBSTR(rowid, 10, 6), 8, 'A'))), 'XXXXXXXXXXXX') as NUMBLK,
SUBSTR(rowid,16,6)||'=>'||
TO_NUMBER(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(
lpad(substr(rowid, 16, 3), 4, 'A'))), 'XXXXXX') as ROWPOS
from qprodotti;

darà un risultato simile:

AAA2PEAAMAAAEn5AAA AAA2PE=>222148 AAM=>12 AAAEn5=>18937 AAA=>0
AAA2PEAAMAAAEn5AAB AAA2PE=>222148 AAM=>12 AAAEn5=>18937 AAB=>1
AAA2PEAAMAAAEn5AAC AAA2PE=>222148 AAM=>12 AAAEn5=>18937 AAC=>2

dove 222148 corrisponde al numero dell’oggetto nel catalogo, il 12 è il datafile coinvolto, il 18937 è il numero del blocco e l’ultima cifra indica l’ordine di visualizzazione.

ORA_ROWSCN

Anche ORA_ROWSCN è una pseudocolonna ed è collegato al cambio di stato del database.
Infatti, ogni modifica alla base dati ha un numero, una sequence: SCN. In altre parole anche una semplice transazione che aggiorna un solo record ha il suo numero, un valore SCN.
Esiste inoltre una relazione tra SCN e orario, quindi con ORA_ROWSCN si è in grado di conoscere quando è avvenuta la modifica. Questa informazione è utile quando, con una flashback query, si vuole “tornare indietro ad un certo orario”.
Quindi ORA_ROWSCN, a differenza di ROWID, non ha riferimento alla posizione fisica, ma solo al tempo/orario.
É importante notare che ORA_ROWSCN ha due modi operativi: il primo a livello di blocco, e il secondo a livello di riga.

Vediamo le due modalità e riutilizzando la tabella precedente:

DROP TABLE QPRODOTTI;
CREATE TABLE QPRODOTTI (QEAN VARCHAR2(20), QDESCRI VARCHAR2(30), QPREZZO NUMBER, QSTATO VARCHAR2(10)) 
ROWDEPENDENCIES ;

La tabella è stata cancellata e quindi ricreata con l’opzione ROWDEPENDENCIES . Di seguito aggiungiamo tre record con ognuno la sua commit:

INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('12345','DENTIFRICIO',2.25,'ATTIVO');
COMMIT;
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('22345','SPAZZOLINO',3.55,'ATTIVO');
COMMIT;
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('32345','LAMETTE RASOIO',5.05,'ATTIVO');
COMMIT;

Ora verifichiamo con:

SELECT SCN_TO_TIMESTAMP(ORA_ROWSCN), QDESCRI, QPREZZO
FROM QPRODOTTI;

e avremo:

25-JUN-18 05.39.43.000000000 PM DENTIFRICIO 2.25
25-JUN-18 05.39.54.000000000 PM SPAZZOLINO 3.55
25-JUN-18 05.40.06.000000000 PM LAMETTE RASOIO 5.05

Adesso rieseguiamo le operazioni precedenti, ma con l’opzione NOROWDEPENDENCIES:

DROP TABLE QPRODOTTI;
CREATE TABLE QPRODOTTI (QEAN VARCHAR2(20), QDESCRI VARCHAR2(30), QPREZZO NUMBER, QSTATO VARCHAR2(10)) NOROWDEPENDENCIES ;
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('12345','DENTIFRICIO',2.25,'ATTIVO');
COMMIT;
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('22345','SPAZZOLINO',3.55,'ATTIVO');
COMMIT;
INSERT INTO QPRODOTTI (QEAN , QDESCRI, QPREZZO, QSTATO) VALUES ('32345','LAMETTE RASOIO',5.05,'ATTIVO');
COMMIT;

e infine la query:

SELECT SCN_TO_TIMESTAMP(ORA_ROWSCN), QDESCRI, QPREZZO
FROM QPRODOTTI;

e il risultato sarà:

25-JUN-18 07.58.58.000000000 PM DENTIFRICIO 2.25
25-JUN-18 07.58.58.000000000 PM SPAZZOLINO 3.55
25-JUN-18 07.58.58.000000000 PM LAMETTE RASOIO 5.05

Noterete che l’orario dell’SCN è lo stesso per tutti e tre i record, mentre in precedenza era differente. Infatti questo orario corrisponde a quello in cui il blocco è stato utilizzato.

In altre parole, ORA_ROWSCN assieme alla ROWDEPENDENCIES , determina l’SCN  “block level” oppure  “row level”.

 

ROWNUM

Questa pseudocolonna evidenzia solo l’ordine di visualizzazione dei record.

Sempre con la stessa tabella:

DROP TABLE QPRODOTTI;
CREATE TABLE QPRODOTTI (QEAN VARCHAR2(20), QDESCRI VARCHAR2(30), QPREZZO NUMBER, QSTATO VARCHAR2(10));

eseguiamo la query:

SELECT ROWNUM,QEAN,QDESCRI FROM QPRODOTTI ORDER BY QDESCRI;

avremo:

1 12345 DENTIFRICIO
3 32345 LAMETTE RASOIO
2 22345 SPAZZOLINO

e cambiando l’ordine (ORDER BY):

SELECT ROWNUM,QEAN,QDESCRI FROM QPRODOTTI ORDER BY QEAN;

avremo:

1 12345 DENTIFRICIO
2 22345 SPAZZOLINO
3 32345 LAMETTE RASOIO

Come si nota, il ROWNUM è generato solo durante la visualizzazione.

 

Leave a Reply