簡體   English   中英

SQL Server中Oracle的RowID的等價物

[英]Equivalent of Oracle's RowID in SQL Server

什么相當於SQL Server中的Oracle RowID?

來自Oracle文檔

ROWID偽列

對於數據庫中的每一行,ROWID偽列返回行的地址。 Oracle數據庫rowid值包含查找行所需的信息:

  • 對象的數據對象編號
  • 行所在的數據文件中的數據塊
  • 數據塊中行的位置(第一行為0)
  • 行所在的數據文件(第一個文件為1)。 文件號是相對於表空間的。

在SQL Server中與此最接近的是rid ,它有三個組件File:Page:Slot

在SQL Server 2008中,可以使用未記錄和不受支持的%%physloc%%虛擬列來查看此內容。 這將返回binary(8)值,其中頁面ID在前四個字節中,然后是2個字節用於文件ID,后面是2個字節用於頁面上的插槽位置。

標量函數sys.fn_PhysLocFormattersys.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%%並返回匹配的(如果有的話)。

要反轉前面提到的2個函數執行的過程並獲得對應於已知文件,頁面,插槽值的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))

如果要唯一地標識表中的行而不是結果集,那么您需要查看使用IDENTITY列之類的內容。 請參閱SQL Server幫助中的“IDENTITY屬性”。 SQL Server不像Oracle那樣為表中的每一行自動生成ID,因此您必須不必創建自己的ID列並在查詢中顯式獲取它。

編輯:對於結果集行的動態編號,請參見下文,但這可能與Oracle的ROWNUM相當,我假設您希望上面的內容在頁面上的所有注釋中。 對於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上還有一篇文章。

我必須重復一個包含許多列的非常大的表,速度很重要。 因此,我使用適用於任何表的此方法:

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

有幾個問題的答案上面會解決缺乏直接引用特定行,但如果變化發生在一個表中的其他行會無法正常工作 這是我的答案在技術上很短的標准。

Oracle ROWID的一個常見用途是提供一種(某種程度上)穩定的方法來選擇行,然后返回到行來處理它(例如,更新它)。 查找行的方法(復雜連接,全文搜索或逐行瀏覽以及對數據應用程序測試)可能無法輕松或安全地重新使用以限定UPDATE語句。

SQL Server RID似乎提供相同的功能,但不提供相同的性能。 這是我看到的唯一問題,不幸的是,保留ROWID的目的是避免重復昂貴的操作來查找例如非常大的表中的行。 盡管如此,許多情況下的表現都是可以接受的。 如果Microsoft在將來的版本中調整優化程序,則可以解決性能問題。

也可以簡單地使用FOR UPDATE並在程序程序中保持CURSOR打開。 然而,這在大型或復雜的批處理中可能證明是昂貴的。

警告:例如,如果SELECT和UPDATE之間的DBA重建數據庫,那么即使Oracle的ROWID也不會穩定,因為它是物理行標識符。 所以ROWID設備應該只在一個范圍很廣的任務中使用。

如果要永久編號表中的行,請不要使用SQL Server的RID解決方案。 它將比舊版386上的Access表現更差。對於SQL Server,只需創建一個IDENTITY列,並將該列用作聚簇主鍵。 這將在表上放置一個永久的,快速的整數B樹,更重要的是,每個非聚集索引將使用它來定位行。 如果您嘗試在SQL Server中進行開發,就好像它是Oracle,那么您將創建性能較差的數據庫。 您需要針對引擎進行優化,而不是假裝它是不同的引擎。

另外,請不要使用NewID()用GUID填充主鍵,你將殺死插入性能。 如果必須使用GUID,請使用NewSequentialID()作為列默認值。 但INT仍然會更快。

另一方面,如果只想對查詢產生的行進行編號,請使用RowNumber Over()函數作為查詢列之一。

來自http://vyaskn.tripod.com/programming_faq.htm#q17

Oracle有一個rownum來使用行號或行ID訪問表的行。 在SQL Server中有沒有相同的東西? 或者如何在SQL Server中生成帶行號的輸出?

在SQL Server中沒有直接等同於Oracle的rownum或row id。 嚴格地說,在關系數據庫中,表中的行不是有序的,行ID也沒有意義。 但是,如果您需要該功能,請考慮以下三種選擇:

  • 在表中添加IDENTITY列。

  • 使用以下查詢為每行生成行號。 以下查詢為pubs數據庫的authors表中的每一行生成一個行號。 要使此查詢起作用,表必須具有唯一鍵。

     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()函數生成的行ID。 創建臨時表的成本很高,尤其是在使用大型表時。 如果您的表中沒有唯一鍵,請選擇此方法。

如果你只想要一個小數據集的基本行編號,那么這樣的怎么樣?

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

請參閱http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx在SQL Server中,時間戳與DateTime列不同。 這用於唯一標識數據庫中的行,而不僅僅是表,而是整個數據庫。 這可以用於樂觀並發。 例如UPDATE [Job] SET [Name] = @ Name,[XCustomData] = @ XCustomData WHERE([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp AND [GUID] = @ Original_GUID

ModifiedTimeStamp確保您正在更新原始數據,如果該行發生了另一次更新,則會失敗。

ROWID是Oracle表上的隱藏列,因此,對於SQL Server,構建自己的列。 添加名為ROWID的列,其默認值為NEWID()

該怎么做: 將具有默認值的列添加到SQL Server中的現有表

您可以使用下面給出的方法獲取ROWID:

1.在其中創建一個帶有自動增量字段的新表

2.使用Row_Number分析函數根據您的要求獲取序列。我更喜歡這個,因為它有助於您希望row_id以特定字段或字段組合的升序或降序方式

示例:Row_Number()Over(由sal desc按Deptno順序分區)

上面的示例將根據每個部門的最高工資給出序列號。分區是可選的,您可以根據您的要求將其刪除

我從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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM