Эквивалент Oracle RowID в SQL Server

Что эквивалентно Oracle RowID в SQL Server?

Ответ 1

Из документов Oracle

ROWID Pseudocolumn

Для каждой строки в базе данных псевдокоманда ROWID возвращает адрес строки. Значения базы данных Oracle Database содержат информацию необходимо найти строку:

  • Номер объекта данных объекта
  • Блок данных в файле данных, в котором находится строка
  • Позиция строки в блоке данных (первая строка равна 0)
  • Файл данных, в котором находится строка (первый файл равен 1). Файл число относительно табличного пространства.

Ближайшим эквивалентом этого в SQL Server является rid, у которого три компонента File:Page:Slot.

В SQL Server 2008 для этого можно использовать недокументированный и неподдерживаемый %%physloc%% виртуальный столбец. Это возвращает значение binary(8) с идентификатором страницы в первых четырех байтах, затем 2 байта для идентификатора файла, а затем 2 байта для местоположения слота на странице.

Скалярная функция sys.fn_PhysLocFormatter или sys.fn_PhysLocCracker TVF может использоваться для преобразования этого в более читаемую форму

CREATE TABLE T(X INT);

INSERT INTO T VALUES(1),(2)

SELECT %%physloc%% AS [%%physloc%%],
       sys.fn_PhysLocFormatter(%%physloc%%) AS [File:Page:Slot]
FROM T

Пример вывода

+--------------------+----------------+
|    %%physloc%%     | File:Page:Slot |
+--------------------+----------------+
| 0x2926020001000000 | (1:140841:0)   |
| 0x2926020001000100 | (1:140841:1)   |
+--------------------+----------------+

Обратите внимание, что процессор запросов не используется. Хотя это можно использовать в предложении WHERE

SELECT *
FROM T
WHERE %%physloc%% = 0x2926020001000100 

SQL Server будет не напрямую искать указанную строку. Вместо этого он выполнит полное сканирование таблицы, оценит %%physloc%% для каждой строки и вернет ту, которая соответствует (если она есть).

Чтобы отменить процесс, выполняемый двумя ранее упомянутыми функциями, и получить значение binary(8), соответствующее известным значениям File, Page, Slot, можно использовать ниже.

DECLARE @FileId int = 1,
        @PageId int = 338,
        @Slot   int = 3

SELECT CAST(REVERSE(CAST(@PageId AS BINARY(4))) AS BINARY(4)) +
       CAST(REVERSE(CAST(@FileId AS BINARY(2))) AS BINARY(2)) +
       CAST(REVERSE(CAST(@Slot   AS BINARY(2))) AS BINARY(2))

Ответ 2

Если вы хотите однозначно идентифицировать строку внутри таблицы, а не свой набор результатов, вам нужно посмотреть на что-то вроде столбца IDENTITY. См. "Свойство IDENTITY" в справке SQL Server. SQL Server не автоматически генерирует идентификатор для каждой строки в таблице, как это делает Oracle, поэтому вам нужно решить проблему создания собственного столбца идентификатора и явно получить его в своем запросе.

EDIT: для динамической нумерации строк набора результатов см. ниже, но это, вероятно, эквивалентно для Oracle ROWNUM, и я предполагаю, что из всех комментариев на странице, которые вы хотите использовать выше. Для SQL Server 2005 и более поздних версий вы можете использовать новую функцию Ranking Functions для достижения динамической нумерации строк.

Например, я делаю это по моему запросу:

select row_number() over (order by rn_execution_date asc) as 'Row Number', rn_execution_date as 'Execution Date', count(*) as 'Count'
from td.run
where rn_execution_date >= '2009-05-19'
group by rn_execution_date
order by rn_execution_date asc

Вы получите:

Row Number  Execution Date           Count
----------  -----------------        -----
1          2009-05-19 00:00:00.000  280
2          2009-05-20 00:00:00.000  269
3          2009-05-21 00:00:00.000  279

В динамической нумерации строк также есть статья о support.microsoft.com.

Ответ 3

Откройте новую функцию ROW_NUMBER. Он работает следующим образом:

SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE

Ответ 4

Некоторые из приведенных выше ответов будут касаться отсутствия прямой ссылки на определенную строку, но не будут работать, если изменения произойдут с другими строками в таблице. Это мои критерии, для которых ответы упадут технически короткими.

Общее использование Oracle ROWID заключается в предоставлении (несколько) стабильного метода выбора строк и последующего возврата к строке для его обработки (например, для ОБНОВЛЕНИЯ). Метод поиска строки (сложные объединения, полнотекстовый поиск или просмотр строк за строкой и применение процедурных тестов к данным) может быть нелегко или безопасно повторно использоваться для определения инструкции UPDATE.

RID SQL Server, похоже, обеспечивает ту же функциональность, но не обеспечивает такую ​​же производительность. Это единственная проблема, которую я вижу, и, к сожалению, цель сохранения ROWID заключается в том, чтобы избежать повторения дорогостоящей операции, чтобы найти строку, например, в очень большой таблице. Тем не менее, производительность для многих случаев приемлема. Если Microsoft настроит оптимизатор в будущей версии, проблема с производительностью может быть решена.

Также можно просто использовать FOR UPDATE и держать CURSOR открытым в процедурной программе. Однако это может оказаться дорогостоящим при большой или сложной пакетной обработке.

Предостережение: Даже Oracle ROWID не будет стабильным, если бы DBA между SELECT и UPDATE, например, состоял в том, чтобы перестроить базу данных, потому что это физический идентификатор строки. Таким образом, устройство ROWID должно использоваться только в рамках задачи с широким охватом.

Ответ 5

От http://vyaskn.tripod.com/programming_faq.htm#q17:

Oracle имеет rownum для доступа к строкам таблицы с использованием номера строки или идентификатора строки. Есть ли эквивалент для SQL Server? Или как сгенерировать вывод с номером строки в SQL Server?

Нет прямого эквивалента Oracle rownum или идентификатора строки в SQL Сервер. Строго говоря, в реляционной базе данных строки внутри таблица не упорядочена, а идентификатор строки не имеет смысла. Но если ты нужна эта функциональность, рассмотрите следующие три альтернативы:

  • Добавьте столбец IDENTITY в таблицу.

  • Используйте следующий запрос для создания номера строки для каждой строки. Следующий запрос генерирует номер строки для каждой строки в авторе таблица базы данных pubs. Чтобы этот запрос работал, таблица должна иметь уникальный ключ.

    SELECT (SELECT COUNT(i.au_id) 
            FROM pubs..authors i 
            WHERE i.au_id >= o.au_id ) AS RowID, 
           au_fname + ' ' + au_lname AS 'Author name'
    FROM          pubs..authors o
    ORDER BY      RowID
    
  • Используйте временный подход таблицы, чтобы сохранить весь набор результатов во временную таблицу вместе с идентификатором строки, сгенерированным IDENTITY()функция. Создание временной таблицы будет дорогостоящим, особенно когда вы работаете с большими таблицами. Пойдите для этого подхода, если вы не имеют уникальный ключ в вашей таблице.

Ответ 6

Если вы хотите навсегда указать строки в таблице, пожалуйста, не используйте RID-решение для SQL Server. Он будет работать хуже, чем Access на старом 386. Для SQL Server просто создайте столбец IDENTITY и используйте этот столбец в качестве кластерного первичного ключа. Это приведет к постоянному, быстрому целочисленному B-дереву на столе, и, что более важно, каждый некластеризованный индекс будет использовать его для поиска строк. Если вы попытаетесь разработать в SQL Server, как если бы это Oracle, вы создадите плохо исполняемую базу данных. Вам нужно оптимизировать двигатель, а не притворяться другим двигателем.

также, пожалуйста, не используйте NewID() для заполнения Первичного ключа с помощью GUID, вы убьете производительность вставки. Если вы должны использовать GUID, используйте NewSequentialID() в качестве столбца по умолчанию. Но INT все равно будет быстрее.

Если, с другой стороны, вы просто хотите указать строки, которые являются результатом запроса, используйте функцию RowNumber Over() как один из столбцов запроса.

Ответ 7

если вам просто нужна нумерация основных строк для небольшого набора данных, как насчет того, как это сделать?

SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees

Ответ 8

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

delete T from 
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1

Ответ 10

См. http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx В SQL-сервере отметка времени не совпадает с столбцом DateTime. Это используется для уникальной идентификации строки в базе данных, а не только таблицы, а всей базы данных. Это можно использовать для оптимистического concurrency. например UPDATE [Job] SET [Name] = @Name, [XCustomData] = @XCustomData WHERE ([ModifiedTimeStamp] = @Original_ModifiedTimeStamp И [GUID] = @Original_GUID

ModifiedTimeStamp гарантирует, что вы обновляете исходные данные и не сработаете, если в строку произошла другая ошибка.

Ответ 11

Я взял этот пример из примера MS SQL, и вы можете видеть, что @ID может быть заменен целым или varchar или любым другим. Это было то же самое решение, которое я искал, поэтому я делюсь им. Наслаждайтесь!!

-- UPDATE statement with CTE references that are correctly matched.
DECLARE @x TABLE (ID int, Stad int, Value int, ison bit);
INSERT @x VALUES (1, 0, 10, 0), (2, 1, 20, 0), (6, 0, 40, 0), (4, 1, 50, 0), (5, 3, 60, 0), (9, 6, 20, 0), (7, 5, 10, 0), (8, 8, 220, 0);
DECLARE @Error int;
DECLARE @id int;

WITH cte AS (SELECT top 1 * FROM @x WHERE Stad=6)
UPDATE x -- cte is referenced by the alias.
SET ison=1, @id=x.ID
FROM cte AS x

SELECT *, @id as 'random' from @x
GO

Ответ 12

Вы можете получить ROWID, используя приведенные ниже методы:

1.Создайте новую таблицу с полем автоматического увеличения в ней

2.Используйте аналитическую функцию Row_Number, чтобы получить последовательность, основанную на ваших требованиях. Я бы предпочел это, потому что он помогает в ситуациях, когда вы хотите, чтобы строка_ид по восходящей или нисходящей манере определенного поля или комбинации полей

Пример: Row_Number() Over (раздел по порядку Deptno по sal desc)

Вышеуказанный образец даст вам порядковый номер, основанный на высшей зарплате каждого отдела. Перемещение по необязательно, и вы можете удалить его в соответствии с вашими требованиями.