在SQL Server中,与Oracle的RowID相当的是什么?
在SQL Server中,与Oracle的RowID相当的是什么?
ROWID伪列
对于数据库中的每一行,ROWID伪列将返回该行的地址。Oracle数据库的rowid值包含了定位行所必需的信息:
- 对象的数据对象号
- 行所在的数据文件中的数据块
- 行在数据块中的位置(第一行为0)
- 行所在的数据文件(第一个文件为1)。文件号相对于表空间而言。
SQL Server中最接近此功能的是rid
,它有三个组成部分File:Page:Slot
。
在SQL Server 2008中,可以使用未记录和不支持的%%physloc%%
虚拟列来查看这一信息。它返回一个binary(8)
值,其中包含前四个字节的页面ID、两个字节的文件ID,以及页面上槽的位置的两个字节。
标量函数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%%
并返回匹配的行(如果有的话)。
要反转之前两个函数执行的过程,并获取与已知File、Page、Slot值相对应的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))
我需要对一个非常大的表进行去重,该表有许多列,速度非常重要。因此我使用了这种适用于任何表格的方法:
delete T from
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1
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。
请查看新的ROW_NUMBER函数。它的使用方法如下:
SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
来自http://vyaskn.tripod.com/programming_faq.htm#q17:
Oracle has a rownum to access rows of a table using row number or row id. Is there any equivalent for that in SQL Server? Or how to generate output with row number in SQL Server?
There is no direct equivalent to Oracle's rownum or row id in SQL Server. Strictly speaking, in a relational database, rows within a table are not ordered and a row id won't really make sense. But if you need that functionality, consider the following three alternatives:
Add an
IDENTITY
column to your table.Use the following query to generate a row number for each row. The following query generates a row number for each row in the authors table of pubs database. For this query to work, the table must have a unique key.
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
Use a temporary table approach, to store the entire resultset into a temporary table, along with a row id generated by the
IDENTITY()
function. Creating a temporary table will be costly, especially when you are working with large tables. Go for this approach, if you don't have a unique key in your table.
ROWID是Oracle表上的隐藏列,因此对于SQL Server,需要自行构建。添加一个名为ROWID的列,并将默认值设置为NEWID()
。