Що еквівалентно RowID Oracle у SQL Server?
Що еквівалентно RowID Oracle у SQL Server?
Відповіді:
ПУЗОВА псевдоколонка
Для кожного рядка бази даних псевдостовбець 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, тому вам доведеться зіткнутися з проблемою створення власного стовпця ідентифікатора та явно отримати його у своєму запиті.
EDIT: для динамічної нумерації рядків набору результатів дивіться нижче, але це, мабуть, було б еквівалентом для ROWNUM Oracle, і я припускаю з усіх коментарів на сторінці, що ви хочете, щоб матеріали вище. Для SQL Server 2005 та пізніших версій ви можете використовувати нову функцію ранжування для досягнення динамічної нумерації рядків.
Наприклад, я роблю це за моїм запитом:
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 Oracle є надання (дещо) стабільного методу виділення рядків і пізніше повернення до рядка для його обробки (наприклад, для оновлення). Метод пошуку рядка (складні об'єднання, повнотекстовий пошук або перегляд рядків за рядком та застосування процедурних перевірок щодо даних) може бути не легко або безпечно повторно використаний для кваліфікації оператора UPDATE.
Здається, RID SQL Server надає однакову функціональність, але не забезпечує однакову продуктивність. Це єдине питання, яке я бачу, і, на жаль, метою збереження ROWID є уникнення повторення дорогої операції пошуку рядка, скажімо, у дуже великій таблиці. Тим не менше, продуктивність у багатьох випадках є прийнятною. Якщо Microsoft налаштує оптимізатор у майбутньому випуску, може бути вирішено проблему продуктивності.
Також можна просто використовувати FOR UPDATE і тримати КУРСОР відкритим у процедурній програмі. Однак це може виявитися дорогим при великій або складній партійній обробці.
Застереження: Навіть ROWID Oracle не був би стабільним, якби DBA, наприклад, між SELECT та UPDATE, перебудовував базу даних, оскільки це фізичний ідентифікатор рядка. Отже, пристрій ROWID слід використовувати лише в рамках широкомасштабного завдання.
якщо ви просто хочете базову нумерацію рядків для невеликого набору даних, як щодо такого?
SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
З http://vyaskn.tripod.com/programming_faq.htm#q17 :
Oracle має доступ до рядків таблиці, використовуючи номер рядка або ідентифікатор рядка. Чи існує якийсь еквівалент для цього в SQL Server? Або як генерувати вихідні дані з номером рядка в SQL Server?
У SQL Server немає прямого еквівалента ідентифікатора рядка або рядка Oracle. Строго кажучи, у реляційній базі даних рядки в таблиці не впорядковані, а ідентифікатор рядка не має сенсу. Але якщо вам потрібна ця функціональність, розгляньте наступні три варіанти:
Додайте
IDENTITY
стовпець до таблиці.Використовуйте наступний запит, щоб створити номер рядка для кожного рядка. Наступний запит генерує номер рядка для кожного рядка в таблиці авторів бази даних пабів. Щоб цей запит працював, таблиця повинна мати унікальний ключ.
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 і використовуйте цей стовпець як кластерний первинний ключ. Це помістить постійне, швидке Integer B-Tree на стіл, і що більш важливо, кожен некластеризований індекс використовуватиме його для пошуку рядків. Якщо ви спробуєте розвиватися в 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 AND [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 (Розділення за Дептно замовлення за Sal desc)
Наведений вище зразок дасть вам порядковий номер на основі найвищої заробітної плати кожного відділу. Розділ за не є обов’язковим, і ви можете видалити його відповідно до ваших вимог