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