RowID của Oracle trong SQL Server có gì tương đương?
RowID của Oracle trong SQL Server có gì tương đương?
Câu trả lời:
Cột giả ROWID
Đối với mỗi hàng trong cơ sở dữ liệu, cột giả ROWID trả về địa chỉ của hàng. Các giá trị rowid của Cơ sở dữ liệu Oracle chứa thông tin cần thiết để định vị một hàng:
- Số đối tượng dữ liệu của đối tượng
- Khối dữ liệu trong tệp dữ liệu chứa hàng
- Vị trí của hàng trong khối dữ liệu (hàng đầu tiên là 0)
- Tệp dữ liệu chứa hàng (tệp đầu tiên là 1). Số tệp có liên quan đến không gian bảng.
Tương đương gần nhất với điều này trong SQL Server là rid
có ba thành phần File:Page:Slot
.
Trong SQL Server 2008, có thể sử dụng %%physloc%%
cột ảo không có tài liệu và không được hỗ trợ để xem điều này. Điều này trả về một binary(8)
giá trị với ID trang trong bốn byte đầu tiên, sau đó là 2 byte cho ID tệp, tiếp theo là 2 byte cho vị trí vị trí trên trang.
Hàm vô hướng sys.fn_PhysLocFormatter
hoặc sys.fn_PhysLocCracker
TVF có thể được sử dụng để chuyển đổi nó thành một dạng dễ đọc hơn
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
Đầu ra mẫu
+--------------------+----------------+
| %%physloc%% | File:Page:Slot |
+--------------------+----------------+
| 0x2926020001000000 | (1:140841:0) |
| 0x2926020001000100 | (1:140841:1) |
+--------------------+----------------+
Lưu ý rằng điều này không được bộ xử lý truy vấn tận dụng. Trong khi có thể sử dụng điều này trong một WHERE
mệnh đề
SELECT *
FROM T
WHERE %%physloc%% = 0x2926020001000100
SQL Server sẽ không trực tiếp tìm kiếm hàng được chỉ định. Thay vào đó, nó sẽ quét toàn bộ bảng, đánh giá %%physloc%%
từng hàng và trả về hàng phù hợp (nếu có).
Để đảo ngược quá trình được thực hiện bởi 2 hàm đã đề cập trước đó và nhận binary(8)
giá trị tương ứng với các giá trị Tệp, Trang, Khe đã biết, bạn có thể sử dụng giá trị bên dưới.
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))
Tôi phải suy luận một bảng rất lớn với nhiều cột và tốc độ là quan trọng. Vì vậy, tôi sử dụng phương pháp này hoạt động cho bất kỳ bảng nào:
delete T from
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1
Kiểm tra chức năng ROW_NUMBER mới . Nó hoạt động như thế này:
SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
Nếu bạn muốn xác định duy nhất một hàng trong bảng chứ không phải tập kết quả của mình, thì bạn cần xem xét bằng cách sử dụng cột nào đó như cột IDENTITY. Xem "thuộc tính IDENTITY" trong phần trợ giúp của SQL Server. SQL Server không tự động tạo ID cho mỗi hàng trong bảng như Oracle làm, vì vậy bạn phải gặp khó khăn khi tạo cột ID của riêng mình và tìm nạp rõ ràng nó trong truy vấn của bạn.
CHỈNH SỬA: để đánh số động các hàng tập kết quả, hãy xem bên dưới, nhưng điều đó có thể sẽ tương đương với ROWNUM của Oracle và tôi giả sử từ tất cả các nhận xét trên trang mà bạn muốn những thứ ở trên. Đối với SQL Server 2005 trở lên, bạn có thể sử dụng chức năng Chức năng Xếp hạng mới để đánh số động các hàng.
Ví dụ: tôi làm điều này trên một truy vấn của tôi:
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
Sẽ cung cấp cho bạn:
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
Cũng có một bài viết trên support.microsoft.com về cách đánh số hàng động.
Một số các câu trả lời ở trên sẽ làm việc xung quanh việc thiếu một tham chiếu trực tiếp đến một hàng cụ thể, nhưng sẽ không làm việc nếu thay đổi xảy ra đối với các hàng khác trong một bảng. Đó là tiêu chí của tôi cho những câu trả lời ngắn gọn về mặt kỹ thuật.
Cách sử dụng phổ biến của ROWID của Oracle là cung cấp một phương pháp (phần nào) ổn định để chọn hàng và sau đó quay trở lại hàng để xử lý nó (ví dụ: CẬP NHẬT nó). Phương pháp tìm một hàng (các phép nối phức tạp, tìm kiếm toàn văn bản hoặc duyệt từng hàng một và áp dụng các kiểm tra thủ tục đối với dữ liệu) có thể không được sử dụng lại một cách dễ dàng hoặc an toàn để đủ điều kiện cho câu lệnh UPDATE.
SQL Server RID dường như cung cấp cùng một chức năng, nhưng không cung cấp cùng một hiệu suất. Đó là vấn đề duy nhất mà tôi thấy, và thật không may, mục đích của việc giữ lại ROWID là để tránh lặp lại một thao tác tốn kém để tìm hàng trong một bảng rất lớn. Tuy nhiên, hiệu suất trong nhiều trường hợp có thể chấp nhận được. Nếu Microsoft điều chỉnh trình tối ưu hóa trong bản phát hành trong tương lai, vấn đề hiệu suất có thể được giải quyết.
Cũng có thể chỉ cần sử dụng FOR UPDATE và giữ CURSOR mở trong một chương trình thủ tục. Tuy nhiên, điều này có thể gây tốn kém trong quá trình xử lý hàng loạt lớn hoặc phức tạp.
Lưu ý: Ngay cả ROWID của Oracle cũng sẽ không ổn định nếu ví dụ như DBA, giữa SELECT và UPDATE, xây dựng lại cơ sở dữ liệu, vì nó là định danh hàng vật lý. Vì vậy, thiết bị ROWID chỉ nên được sử dụng trong một nhiệm vụ có phạm vi tốt.
nếu bạn chỉ muốn đánh số hàng cơ bản cho một tập dữ liệu nhỏ, vậy còn cách đánh số như thế này thì sao?
SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
Từ http://vyaskn.tripod.com/programming_faq.htm#q17 :
Oracle có một rownum để truy cập các hàng của bảng bằng cách sử dụng số hàng hoặc id hàng. Có bất kỳ tương đương nào cho điều đó trong SQL Server không? Hoặc làm thế nào để tạo đầu ra với số hàng trong SQL Server?
Không có tương đương trực tiếp với id hàng hoặc rownum của Oracle trong SQL Server. Nói một cách chính xác, trong cơ sở dữ liệu quan hệ, các hàng trong bảng không được sắp xếp theo thứ tự và id hàng sẽ không thực sự có ý nghĩa. Nhưng nếu bạn cần chức năng đó, hãy xem xét ba lựa chọn thay thế sau:
Thêm một
IDENTITY
cột vào bảng của bạn.Sử dụng truy vấn sau để tạo số hàng cho mỗi hàng. Truy vấn sau tạo một số hàng cho mỗi hàng trong bảng tác giả của cơ sở dữ liệu quán rượu. Để truy vấn này hoạt động, bảng phải có một khóa duy nhất.
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
Sử dụng cách tiếp cận bảng tạm thời, để lưu trữ toàn bộ tập kết quả vào một bảng tạm thời, cùng với một id hàng được tạo bởi
IDENTITY()
hàm. Tạo một bảng tạm thời sẽ rất tốn kém, đặc biệt là khi bạn đang làm việc với các bảng lớn. Hãy thực hiện cách tiếp cận này, nếu bạn không có khóa duy nhất trong bảng của mình.
Nếu bạn muốn đánh số vĩnh viễn các hàng trong bảng, Vui lòng không sử dụng giải pháp RID cho SQL Server. Nó sẽ hoạt động kém hơn Access trên 386. Đối với SQL Server, chỉ cần tạo một cột IDENTITY và sử dụng cột đó làm khóa chính nhóm. Điều này sẽ đặt một Cây số nguyên nhanh, vĩnh viễn trên bảng và quan trọng hơn là mọi chỉ mục không phân cụm sẽ sử dụng nó để định vị các hàng. Nếu bạn cố gắng phát triển trong SQL Server như thể đó là Oracle, bạn sẽ tạo ra một cơ sở dữ liệu hoạt động kém. Bạn cần phải tối ưu hóa cho động cơ, không phải giả vờ đó là một động cơ khác.
Ngoài ra, vui lòng không sử dụng NewID () để điền vào Khóa chính với các GUID, bạn sẽ giết hiệu suất chèn. Nếu bạn phải sử dụng GUID, hãy sử dụng NewSequentialID () làm cột mặc định. Nhưng INT vẫn sẽ nhanh hơn.
Mặt khác, nếu bạn chỉ muốn đánh số các hàng là kết quả của một truy vấn, hãy sử dụng hàm RowNumber Over () làm một trong các cột truy vấn.
Vui lòng thử
select NEWID()
Nguồn: https://docs.microsoft.com/en-us/sql/t-sql/data-types/uniqueidentifier-transact-sql
ROWID là một cột ẩn trên bảng Oracle, vì vậy, đối với SQL Server, hãy xây dựng cột của riêng bạn. Thêm một cột có tên ROWID với giá trị mặc định làNEWID()
.
Cách làm điều đó: Thêm cột, với giá trị mặc định, vào bảng hiện có trong SQL Server
Vui lòng xem http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx Trong máy chủ SQL, dấu thời gian không giống với cột DateTime. Điều này được sử dụng để xác định duy nhất một hàng trong cơ sở dữ liệu, không chỉ một bảng mà toàn bộ cơ sở dữ liệu. Điều này có thể được sử dụng cho đồng thời lạc quan. ví dụ: UPDATE [Job] SET [Name] = @ Name, [XCustomData] = @ XCustomData WHERE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp VÀ [GUID] = @ Original_GUID
Mod ModifiedTimeStamp đảm bảo rằng bạn đang cập nhật dữ liệu gốc và sẽ không thành công nếu một bản cập nhật khác đã xảy ra với hàng.
Tôi lấy ví dụ này từ ví dụ MS SQL và bạn có thể thấy @ID có thể được thay thế bằng số nguyên hoặc varchar hoặc bất cứ thứ gì. Đây cũng là giải pháp mà tôi đang tìm kiếm, vì vậy tôi đang chia sẻ nó. Thưởng thức!!
-- 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
Bạn có thể lấy ROWID bằng cách sử dụng các phương pháp được cung cấp bên dưới:
1.Tạo một bảng mới với trường tăng tự động trong đó
2.Sử dụng hàm phân tích Row_Number để lấy chuỗi dựa trên yêu cầu của bạn. Tôi thích điều này hơn vì nó hữu ích trong những trường hợp bạn muốn row_id theo cách tăng dần hoặc giảm dần của một trường cụ thể hoặc kết hợp các trường
Mẫu: Row_Number () Over (Partition by Deptno order by sal desc)
Mẫu trên sẽ cung cấp cho bạn số thứ tự dựa trên mức lương cao nhất của từng bộ phận. Phân vùng theo tùy chọn và bạn có thể xóa tùy theo yêu cầu của mình