Что эквивалентно Oracle RowID в SQL Server?
Что эквивалентно Oracle RowID в SQL Server?
Ответы:
Псевдоколонка ROWID
Для каждой строки в базе данных псевдостолбец ROWID возвращает адрес строки. Значения 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))
Мне нужно вывести очень большую таблицу со многими столбцами, и скорость важна. Поэтому я использую этот метод, который работает для любой таблицы:
delete T from
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1
Ознакомьтесь с новой функцией ROW_NUMBER . Это работает так:
SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
Если вы хотите однозначно идентифицировать строку в таблице, а не свой набор результатов, вам нужно использовать что-то вроде столбца IDENTITY. См. «Свойство IDENTITY» в справке SQL Server. SQL Server не создает автоматически идентификатор для каждой строки в таблице, как это делает Oracle, поэтому вам придется создать собственный столбец идентификатора и явно получить его в своем запросе.
РЕДАКТИРОВАТЬ: для динамической нумерации строк набора результатов см. Ниже, но это, вероятно, было бы эквивалентом 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 также есть статья о динамической нумерации строк.
Некоторые из приведенных выше ответов будут работать с отсутствием прямой ссылки на конкретную строку, но не будут работать, если изменения произойдут в других строках в таблице. Это мои критерии, ответы на которые технически недостаточны.
Обычно ROWID используется для предоставления (в некоторой степени) стабильного метода выбора строк и последующего возврата к строке для ее обработки (например, для ее ОБНОВЛЕНИЯ). Метод поиска строки (сложные объединения, полнотекстовый поиск или просмотр строка за строкой и применение процедурных тестов к данным) может быть нелегко или безопасно повторно использовать для квалификации оператора UPDATE.
Кажется, что RID SQL Server предоставляет те же функции, но не обеспечивает такой же производительности. Это единственная проблема, которую я вижу, и, к сожалению, цель сохранения ROWID - избежать повторения дорогостоящей операции по поиску строки, скажем, в очень большой таблице. Тем не менее, производительность во многих случаях приемлема. Если Microsoft настроит оптимизатор в будущем выпуске, проблема производительности может быть решена.
Также можно просто использовать FOR UPDATE и оставить КУРСОР открытым в процедурной программе. Однако это может оказаться дорогостоящим при большой или сложной пакетной обработке.
Предостережение: даже ROWID Oracle не был бы стабильным, если бы администратор базы данных, например, между SELECT и UPDATE, перестроил базу данных, потому что это физический идентификатор строки. Таким образом, устройство ROWID следует использовать только в рамках хорошо поставленной задачи.
если вам просто нужна базовая нумерация строк для небольшого набора данных, как насчет чего-то вроде этого?
SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
С http://vyaskn.tripod.com/programming_faq.htm#q17 :
Oracle имеет rownum для доступа к строкам таблицы, используя номер строки или идентификатор строки. Есть ли для этого эквивалент в SQL Server? Или как сгенерировать вывод с номером строки в SQL Server?
В SQL Server нет прямого эквивалента rownum или идентификатора строки Oracle. Строго говоря, в реляционной базе данных строки в таблице не упорядочены, и идентификатор строки не имеет смысла. Но если вам нужна эта функция, рассмотрите следующие три альтернативы:
Добавьте
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()
функцией. Создание временной таблицы будет дорогостоящим, особенно если вы работаете с большими таблицами. Используйте этот подход, если у вас нет уникального ключа в вашей таблице.
Если вы хотите постоянно нумеровать строки в таблице, пожалуйста, не используйте решение RID для SQL Server. Он будет работать хуже, чем Access на старом 386. Для SQL Server просто создайте столбец IDENTITY и используйте этот столбец в качестве кластеризованного первичного ключа. Это поместит в таблицу постоянное быстрое целочисленное B-дерево, и, что более важно, каждый некластеризованный индекс будет использовать его для поиска строк. Если вы попытаетесь разработать SQL Server, как если бы это был Oracle, вы создадите плохо работающую базу данных. Вам нужно оптимизировать для движка, а не делать вид, что это другой движок.
также, пожалуйста, не используйте NewID () для заполнения первичного ключа идентификаторами GUID, это снизит производительность вставки. Если вы должны использовать GUID, используйте NewSequentialID () в качестве столбца по умолчанию. Но INT все равно будет быстрее.
С другой стороны, если вы просто хотите пронумеровать строки, полученные в результате запроса, используйте функцию RowNumber Over () в качестве одного из столбцов запроса.
Пожалуйста, попробуй
select NEWID()
Источник: https://docs.microsoft.com/en-us/sql/t-sql/data-types/uniqueidentifier-transact-sql
ROWID - это скрытый столбец в таблицах Oracle, поэтому для SQL Server создайте свой собственный. Добавьте столбец с именем ROWID со значением по умолчанию NEWID()
.
Как это сделать: добавить столбец со значением по умолчанию в существующую таблицу в SQL Server
См. Http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx В SQL-сервере метка времени отличается от столбца DateTime. Это используется для уникальной идентификации строки в базе данных, а не только таблицы, но и всей базы данных. Это можно использовать для оптимистичного параллелизма. например UPDATE [Job] SET [Name] = @ Name, [XCustomData] = @ XCustomData WHERE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp И [GUID] = @ Original_GUID
ModifiedTimeStamp гарантирует, что вы обновляете исходные данные, и завершится ошибкой, если в строке произошло другое обновление.
Я взял этот пример из примера 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
Вы можете получить ROWID, используя методы, указанные ниже:
1.Создайте новую таблицу с полем автоинкремента в ней
2.Используйте аналитическую функцию Row_Number, чтобы получить последовательность, основанную на ваших требованиях. Я бы предпочел это, потому что это помогает в ситуациях, когда вы хотите, чтобы row_id был в порядке возрастания или убывания определенного поля или комбинации полей
Пример: Row_Number () Over (Разделение по порядку Deptno по sal desc)
В приведенном выше примере будет указан порядковый номер, основанный на наивысшей заработной плате каждого отдела. Разделение по необязательно, и вы можете удалить его в соответствии с вашими требованиями.