私の理解では、ROWID は、クエリによって返される結果の各行の一意の値です。
この ROWID が必要な理由 ORACLE にはすでに ROWNUM があります。
SQLクエリでROWIDを使用した人はいますか?
ROWIDは、行の物理的な場所です。したがって、これは行を見つけるための最速の方法であり、主キーの検索よりも高速です。where
したがって、いくつかの行を選択し、それらのROWIDを格納してから、後でそれらの同じ行に対してDMLの句でROWIDを使用する特定のタイプのトランザクションで役立ちます。
WHERE CURRENT OFを使用してロックされた行を更新する場合、Oracle SELECT ...FORUPDATE構文は暗黙的にROWIDを使用します。また、EXCEPTIONSテーブル(EXCEPTIONS INTO句で制約を適用するときに参照される)には、列ROW_IDがあります。これにより、制約を破っている行をすばやく特定できます。
後者の例は、別の一般的な使用法を示しています。一般的なコードを記述していて、データ型や複合キーなどを気にせずにUIDを格納するメカニズムが必要な場合です。
一方、ROWNUMは、特定の結果セットの行にタグを付ける疑似列です。永続的な意味はありません。
編集
特定のレコードのROWIDは、たとえばテーブルの再構築を通じて、システムの存続期間中に変更される可能性があります。また、1つのレコードが削除された場合、そのROWIDに新しいレコードを指定できます。したがって、ROWIDは長期的にUIDとして使用するのには適していません。ただし、トランザクション内で使用するには十分です。
私は今、これの例を知っています。
主キーのないテーブルがあるとします。したがって、このテーブルには重複する行が含まれる可能性があります。重複する行を削除して、その種類の行を 1 つだけ保持するにはどうすればよいでしょうか?
Oracle は、主キーの一種の代替として ROWID を提供します。相関型のネストされたクエリを作成できます [(行内のすべての列でグループ化し、内部クエリの各グループで MIN(ROWID) を取得し、グループごとに外部クエリのグループ内の他の行を削除します)]
例
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.
ROWID は、データベースの EXPORT および IMPORT サイクル全体で保持されないことに注意してください。テーブルに行 ID をキー値として格納しないでください。
ROWID は次のもので構成されます (ただし、必ずしもこの順序である必要はありませんが、覚えている限り、ROWNUM 部分は ROWID の最後の部分です)。
ROWIDTOCHAR() SQL 関数を使用するか、以下を使用して、ROWID を複合フィールド (OBJID、FILENO、BLOCKNO、ROWNUM) に簡単に分割できます。
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
フィールド ROWNUM (または上記のクエリの ROW) は、SELECT クエリで使用する SQL 疑似列 ROWNUM と同じではないことに注意してください。これは、結果セット内の行の動的に生成された行番号です。
この実装のため、行、ブロック、エクステント、およびセグメントは、インデックスを無効にする ROWID を壊さない限りトランスポートできないことに注意してください。
ROWID は、一意のファイルとそのファイル内の一意のブロック、およびそのブロック内の一意の行をエンコードするため、行が存在するブロックへの最も直接的なアクセス パスであり、行を一意に識別します。
詳しくは:
ノート:
Oracle がデータベース ファイルとブロックを構造化する方法を少し理解し、C プログラミングの知識があれば、ROWID (8k、またはブロック サイズが使用されている任意のブロック サイズ) によって指定されたブロックの内容を表示するプログラムを非常に簡単に作成できます。データベース、fileheadersize + BLOCKNO * BLOCK_SIZE で始まるブロック ブロックにはブロック ヘッダーが含まれ、その後 (テーブルがクラスタ化されていないと仮定して) 行ごとに行ごとにブロック内の相対オフセットを与える行ディレクトリが含まれます。たとえば、 rowdir 内の位置 0 は、ブロック内の 0 番目の行の相対オフセットであり、rowdir 内の位置 1 は、1 番目の行の相対位置などです。行数自体は、ブロック ヘッダーのどこかに格納されます。 (ブロック レイアウトに関するオーラル ドキュメントを参照してください)。
プログラミングの知識が少しあり、ブロックの正確なレイアウトについてOracleデータベースファイルとブロックに関するドキュメントを調べると、行がディスクにどのように格納されているかを確認し、行が各列に格納するすべての値を再構築することさえできます. 各行には、行の長さと列の数のメタデータ、および各列の列の型とバイトサイズとその後の値の指標が含まれます。バイトサイズ 0 は、列データが空 (または NULL) であることを意味します。
ROWIDは、テーブル内の行を一意に識別します。ROWNUMは、特定のクエリの結果の行番号を示します。この2つは非常に異なり、互換性はありません。
また、ROWNUMのより新しいバージョンであるROW_NUMBERがあり、動作が少し異なります。違いを説明するこの記事をチェックしてください。
ROWIDを使用すると、基本的に、まったく同じデータを持つ2つの行を作成できます。通常、主キーはRowIDよりも少し意味のあるものにする必要がありますが、これは行間の一意性を自動的に保証する簡単な方法にすぎません。