2009-05-26 3 views
62

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

+0

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

ответ

3

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

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

Нет прямого эквивалента идентификатора rownum или строки Oracle в 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 
    
  • Используйте временный подход таблицы, чтобы хранить всю ResultSet во временную таблицу, вместе с идентификатором строки, порожденной функцией IDENTITY() . Создание временной таблицы будет дорогостоящим, особенно когда вы работаете с большими таблицами. Пойдите для этого подхода, если у вас нет , у вас есть уникальный ключ в вашей таблице.

9

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

EDIT: для динамической нумерации строк набора результатов см. Ниже, но это, вероятно, эквивалентно для ROWNUM Oracle, и я предполагаю, что из всех комментариев на странице, которые вы хотите использовать выше. Для 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 динамически нумерации строк.

+0

Я думаю, что столбец идентичности однозначно идентифицирует строку в таблице, но не в базе данных. – tuinstoel

+0

Это верно, но это соответствует определению ROWID, которое я вижу в документах Oracle: «Внешний тип данных ROWID идентифицирует определенную строку в таблице базы данных» ... но я вижу, что вы говорите об этом из-за моей опечатки на вершина. :) Спасибо что подметил это. – Xiaofu

+0

Это только часть определения. Он не изменяется от запроса к запросу ... –

6

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

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

Я думаю, что это замена для rownum, а не rowid. – tuinstoel

2

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

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

Не то, что такое рядовой. –

+0

Но он работает для быстрого добавления идентификатора, который некоторые зрители будут искать, не зная, что такое ROWID. – Graeme

1

ROWID - это скрытый столбец на таблицах Oracle, поэтому для SQL Server создайте свой собственный. Добавьте столбец с именем ROWID со значением по умолчанию NEWID().

Как сделать: Add column, with default value, to existing table in SQL Server

+1

Разве это не комментарий? –

0

Я взял этот пример из примера 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 
102

From the Oracle docs

ROWID псевдостолбец

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

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

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

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

Функция скалярная sys.fn_PhysLocFormatter или sys.fn_PhysLocCracker ТВФ может быть использован для преобразования этого в более читаемом виде

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

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)) 
6

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

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

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

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

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

1

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

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

3

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

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

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

3

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

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

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

1.Create новая таблица с полем автоматического приращения в нем

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

Образец: Row_Number() Ove г (Partition по Deptno порядке сал по алфавиту)

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

Смежные вопросы