ROWID (oracle) - любое использование для него?

Я понимаю, что ROWID является уникальным значением для каждой строки в результате, возвращаемом запросом.

зачем нам этот ROWID? В ORACLE уже есть ROWNUM.

кто-нибудь использовал ROWID в SQL-запросе?

6 ответов


ROWID-это физическое расположение строки. Следовательно, это самый быстрый способ поиска строки, даже быстрее, чем поиск первичного ключа. Поэтому он может быть полезен в определенных типах транзакций, где мы выбираем некоторые строки, храним их ROWIDs, а затем используем ROWIDs в where предложения для DML против тех же строк.

выбор Oracle ... Для синтаксиса обновления неявно используется ROWID, когда мы обновляем заблокированную строку, используя where CURRENT OF. Также Таблица исключений (ссылка при применении ограничений с исключениями в предложение) имеет столбец ROW_ID. Это позволяет нам быстро идентифицировать строки, которые нарушают наше ограничение.

этот последний пример указывает на другое общее использование: когда мы пишем некоторый общий кусок кода и нуждаемся в механизме для хранения uid без проблем относительно типа данных, составных ключей и т. д.

ROWNUM, с другой стороны, является псевдо-столбцом, который помечает строку в заданном результирующем наборе. Оно имеет никакого постоянного значения.

редактировать

ROWID для данной записи может изменяться в течение всего времени существования системы, например, через перестроение таблицы. Кроме того, если одна запись удалена, новой записи может быть присвоен этот ROWID. Следовательно, ROWIDs не подходят для использования в качестве UIDs в долгосрочной перспективе. Но они достаточно хороши для использования в рамках транзакции.


теперь я знаю пример для этого.

предположим, что у вас есть таблица без первичных ключей. таким образом, эта таблица может иметь повторяющиеся строки. Как бы вы удалили повторяющиеся строки, но сохранили точно одну из них?

Oracle предоставляет ROWID в качестве замены первичного ключа. Вы можете написать вложенный запрос, который имеет коррелированный тип [(group by all columns in The row и take MIN (ROWID) в каждой группе во внутреннем запросе, для каждой группы удалите другие строки в группе в outerquery)]

пример

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 не сохраняется в цикле экспорта и импорта базы данных. вы никогда не должны хранить rowid в своих таблицах в качестве ключевого значения.


ROWID однозначно идентифицирует строку в таблице. ROWNUM дает номер строки результата для определенного запроса. Они очень различны и не взаимозаменяемы.

также есть ROW_NUMBER, который является более современной версией ROWNUM, и ведет себя немного иначе. Проверьте в этой статье что объясняет разницу.


ROWID состоит из (Но не обязательно в этом порядке, хотя часть ROWNUM является последней частью ROWID, насколько я помню):

  • OBJID Уникальный идентификатор объекта.
  • FILENO Относительное число файла данных в табличном пространстве.
  • в BLOCKNO Относительный номер блока в файле данных после fileheader.
  • этот параметр rownum Относительный rownum внутри блока.

вы можете легко сломать ROWID в составные поля (OBJID, FILENO, BLOCKNO, ROWNUM) с помощью SQL-функции ROWIDTOCHAR () или используйте:

    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 (или строка в приведенном выше запросе) -не тот же ROWNUM, что и псевдо-столбец SQL ROWNUM, который вы используете в запросе SELECT, который является динамически генерируемым номером строки в результирующем наборе.

обратите внимание, что из-за этой реализации строки, блоки, экстенты и сегменты не переносятся не нарушая ROWID, который делает индексы недействительными.

ROWID-это самый прямой путь доступа к блоку, в котором находится строка, и уникально индентифицирует строку, потому что он кодирует уникальный файл и уникальный блок в этом файле и уникальную строку в этом блоке.

дополнительная информация:

посмотреть: Примечания СУБД по формату ROWID

Примечание:

Если у вас есть немного понимания того, как оракул структур файлы и блоки базы данных, а также знать некоторые программирования C, вы можете довольно легко сделать программу, которая отображает содержимое блока, заданного ROWID (8k, или любой размер блока используется в базе данных, блок, который начинается с fileheadersize + BLOCKNO * BLOCK_SIZE. Блок содержит заголовок блока, а затем (если таблица не кластеризована) rowdir, который для каждой строки дает относительное смещение внутри блока для каждой строки. Так, например, в позиции 0 в rowdir является относительное смещение 0-й строки внутри блока, в позиции 1 в rowdir относительной позиции 1-й строки и т. д. Само количество строк хранится где-то в заголовке блока (см. документацию orale по компоновке блока).

имея немного знаний программирования и просматривая документацию по файлам баз данных oracle и блокам для точного расположения блоков, вы можете увидеть, как строки хранятся на диске, и даже восстановить все значения, которые хранит строка для каждый столбец. Каждая строка содержит метаданные для длины строки и количества столбцов, а для каждого столбца-указание типа столбца, байт-размера и последующего значения. Bytesize 0 означает, что данные столбца пусты (или: NULL).


ROWID в основном позволяет иметь две строки с точно такими же данными. Хотя вы обычно хотите, чтобы ваш первичный ключ был немного более значимым, чем RowID, это просто простой способ автоматического обеспечения уникальности между строками.