ROWID (oracle) - toute utilisation pour cela?
Ma compréhension est que le ROWID est une valeur unique pour chaque ligne dans le résultat retourné par une requête.
Pourquoi avons-nous besoin de ce ROWID? Il y a déjà le ROWNUM dans ORACLE.
Quelqu'un a-t-il utilisé ROWID dans une requête SQL?
6 réponses
ROWID est l'emplacement physique d'une ligne. Par conséquent, c'est le moyen le plus rapide de localiser une ligne, même plus rapide qu'une recherche de clé primaire. Cela peut donc être utile dans certains types de transactions où nous sélectionnons des lignes, stockons leurs ROWIDs et utilisons ensuite les ROWIDs dans les clauses where
pour DML contre ces mêmes lignes.
La sélection Oracle ... Pour la syntaxe de mise à jour utilise implicitement ROWID, lorsque nous mettons à jour la ligne verrouillée en utilisant WHERE CURRENT OF. Aussi la table des EXCEPTIONS (référencée quand appliquer des contraintes avec les EXCEPTIONS dans la clause) a une colonne ROW_ID. Cela nous permet d'identifier rapidement les lignes qui cassent notre contrainte.
Ce dernier exemple pointe vers un autre usage général: lorsque nous écrivons un morceau de code générique et avons besoin d'un mécanisme pour stocker des uid sans soucis concernant le type de données, les clés composites, etc.
ROWNUM d'autre part est une pseudo-colonne qui balise une ligne dans un jeu de résultats donné. Il n'a pas de permanente de l'importance.
Modifier
Le ROWID d'un enregistrement donné peut changer pendant la durée de vie d'un système, par exemple via une reconstruction de table. De plus, si un enregistrement est supprimé, un nouvel enregistrement peut recevoir ce ROWID. Par conséquent, les ROWIDs ne conviennent pas pour une utilisation comme UIDs à long terme. Mais ils sont assez bons pour une utilisation dans une transaction.
Je connais maintenant un exemple pour cela.
Supposons que vous ayez une table sans clés primaires. donc, cette table peut avoir des lignes en double. Comment supprimeriez-vous les lignes en double mais gardez-en exactement une de ce genre?
Oracle fournit ROWID comme une sorte de substitut à la clé primaire. Vous pouvez écrire une requête imbriquée de type corrélé [(group by all columns in the row et take MIN (ROWID) dans chaque groupe dans la requête interne, pour chaque groupe supprimer les autres lignes du groupe dans outerquery)]
Exemple
SQL> select * from employees;
SSN NAME
---------- ----------
1 helen
1 helen
2 helen
2 peter
10 sally
11 null
11 null
12 null
8 rows selected.
SQL> delete from employees where ROWID NOT IN (select min(ROWID) from employees
group by ssn,name);
2 rows deleted.
SQL> select * from employees;
SSN NAME
---------- ----------
1 helen
2 helen
2 peter
10 sally
11 null
12 null
6 rows selected.
Notez que ROWID ne persiste pas dans un cycle D'exportation et D'importation de base de données. vous ne devez jamais stocker un rowid dans vos tables en tant que valeur clé.
ROWID identifie de manière unique une ligne dans une table. ROWNUM vous donne le numéro de ligne d'un résultat pour une requête spécifique. Les deux sont très différents et ne sont pas interchangeables.
Il y a aussi ROW_NUMBER qui est une version plus moderne de ROWNUM, et se comporte légèrement différemment. Consultez Cet article {[4] } qui explique la différence.
Un ROWID se compose de (mais pas nécessairement dans cet ordre, bien que la partie ROWNUM soit la dernière partie de ROWID pour autant que je me souvienne):
- OBJID L'identifiant unique de l'objet.
- FILENO Le nombre relatif du fichier de données dans l'espace de table.
- le BLOCKNO Le numéro de bloc relatif dans le fichier de données après le fileheader.
- le ROWNUM Le rownum relatif dans le bloc.
Vous pouvez facilement décomposer le ROWID en ses champs composites (OBJID, FILENO, BLOCKNO, ROWNUM) en utilisant la fonction SQL ROWIDTOCHAR (), ou utilisez:
SQL> select DBMS_ROWID.ROWID_OBJECT(rowid) "OBJECT",
2 DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) "FILE",
3 DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) "BLOCK",
4 DBMS_ROWID.ROWID_ROW_NUMBER(rowid) "ROW"
5 from dual
6 /
OBJECT FILE BLOCK ROW
---------- ---------- ---------- ----------
258 1 2082 0
Notez que le champ ROWNUM (ou ROW dans la requête ci-dessus) est Pas le même ROWNUM que le ROWNUM de pseudo colonne SQL que vous utilisez dans SELECT query, qui est juste le rownumber généré dynamiquement de la ligne dans le jeu de résultats.
Notez qu'en raison de cette implémentation, les lignes, les blocs, les extensions et les segments ne sont pas transportables sans casser le ROWID, ce qui invalide index.
Le ROWID est le chemin d'accès le plus direct au bloc dans lequel la ligne réside et indentifie de manière unique la ligne, car il Code le fichier unique et le bloc unique dans ce fichier et la ligne unique dans ce bloc.
Plus d'informations:
Voir: notes SGBD sur le format ROWID
Remarque:
Si vous avez un peu de compréhension de la façon dont oracle structure les fichiers et les blocs de base de données, et connaissez la programmation C, vous pourriez facilement faire un programme qui affiche le contenu du bloc donné par ROWID (un 8k, ou n'importe quelle taille de bloc est utilisée dans la base de données, bloc qui commence à fileheadersize + BLOCKNO * BLOCK_SIZE. Le bloc contient l'en-tête de bloc et ensuite (en supposant que la table n'est pas en cluster) le rowdir, qui pour chaque ligne donne le décalage relatif dans le bloc pour chaque ligne. Ainsi, par exemple à la position 0 dans le rowdir est le décalage relatif de la 0-ème ligne dans le bloc, à la position 1 dans le rowdir le position relative de la 1ère rangée, etc. Le nombre de lignes lui-même est stocké quelque part dans l'en-tête du bloc (voir la documentation orale sur la disposition du bloc).
Avec un peu de connaissances en programmation et en recherchant la documentation sur les fichiers de base de données oracle et les blocs pour la disposition exacte des blocs, vous pouvez voir comment les lignes sont stockées sur le disque, et même reconstruire toutes les valeurs que la ligne stocke pour chaque colonne. Chaque ligne contient des métadonnées pour la longueur de la ligne et le nombre de colonnes, et pour chaque colonne, une indication pour le type de la colonne et le bytesize et therafter la valeur. Bytesize 0 signifie que les données de la colonne sont vides (ou: NULL).
ROWID vous permet essentiellement d'avoir deux lignes avec exactement les mêmes données. Alors que vous voulez généralement que votre clé primaire soit un peu plus significative qu'un RowID, c'est juste un moyen simple d'assurer automatiquement l'unicité entre les lignes.