Oracle'ın SQL Server'daki RowID'sinin karşılığı


84

Oracle'ın RowID'sinin SQL Server'daki karşılığı nedir?


Stephanie: Varsayım, verilerde verilerin normalize edildiğini varsayan benzersiz bir anahtar olduğu yönündedir, bu bazen yanlış bir varsayımdır. Bu nedenle, Oracle'ın SQL sunucusundaki RowID'sinin eşdeğeri nedir?
Christopher Mahan

Yanıtlar:


117

Oracle belgelerinden

ROWID Sözde Sütun

Veritabanındaki her satır için, ROWID sözde sütun, satırın adresini döndürür. Oracle Database satır kimliği değerleri, bir satırı bulmak için gerekli bilgileri içerir:

  • Nesnenin veri nesnesi numarası
  • Satırın bulunduğu veri dosyasındaki veri bloğu
  • Veri bloğundaki satırın konumu (ilk satır 0'dır)
  • Satırın bulunduğu veri dosyası (ilk dosya 1'dir). Dosya numarası tablo alanına bağlıdır.

SQL Server'da buna en yakın eşdeğer rid, üç bileşene sahip olanıdır File:Page:Slot.

SQL Server 2008'de bunu %%physloc%%görmek için belgelenmemiş ve desteklenmeyen sanal sütunu kullanmak mümkündür . Bu binary(8), ilk dört baytta Sayfa Kimliği, ardından Dosya Kimliği için 2 bayt ve ardından sayfadaki yuva konumu için 2 bayt olan bir değer döndürür .

Skaler işlevi sys.fn_PhysLocFormatterveya sys.fn_PhysLocCrackerTVF, bunu daha okunabilir bir forma dönüştürmek için kullanılabilir

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

Örnek Çıktı

+--------------------+----------------+
|    %%physloc%%     | File:Page:Slot |
+--------------------+----------------+
| 0x2926020001000000 | (1:140841:0)   |
| 0x2926020001000100 | (1:140841:1)   |
+--------------------+----------------+

Bunun sorgu işlemcisi tarafından kullanılmadığını unutmayın. Bunu bir cümlede kullanmak mümkün olsa daWHERE

SELECT *
FROM T
WHERE %%physloc%% = 0x2926020001000100 

SQL Server olacak değil doğrudan belirtilen satıra ararlar. Bunun yerine tam bir tablo taraması yapacak, değerlendirin%%physloc%% her satırı ve eşleşen olanı (varsa) döndürecektir.

Daha önce bahsedilen 2 fonksiyon tarafından gerçekleştirilen işlemi tersine çevirmek ve binary(8)bilinen Dosya, Sayfa, Yuva değerlerine karşılık gelen değeri elde etmek için aşağıdaki kullanılabilir.

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))

SQL Server 2005'te bunun yerine belgelenmemiş ve desteklenmeyen sanal sütunları %% LockRes %% kullanabilirsiniz
Henrik Holmgaard Høyer

mutlak doğru. %% LockRes %% "doğru yol" değil - yalnızca 2008 öncesi sql sunucularının eski sürümlerindeki verilere hızlı ve kirli düzeltmeler için kullanın
Henrik Holmgaard Høyer

11

Çok sayıda sütun içeren çok büyük bir tabloyu tekilleştirmem gerekiyor ve hız önemli. Bu nedenle, herhangi bir tablo için çalışan bu yöntemi kullanıyorum:

delete T from 
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1

9

Yeni ROW_NUMBER işlevine göz atın . Şu şekilde çalışır:

SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE

15
Sanırım bu rownum yerine Rowid değil.
tuinstoel

9

Sonuç kümeniz yerine tablodaki bir satırı benzersiz bir şekilde tanımlamak istiyorsanız, KİMLİK sütunu gibi bir şeye bakmanız gerekir. SQL Server yardımında "IDENTITY özelliği" konusuna bakın. SQL Server, Oracle'ın yaptığı gibi tablodaki her satır için otomatik olarak bir kimlik oluşturmaz, bu nedenle kendi kimlik sütununuzu oluşturma zahmetine girmeniz ve bunu sorgunuza açıkça getirmeniz gerekir.

DÜZENLEME: Sonuç kümesi satırlarının dinamik numaralandırması için aşağıya bakın, ancak bu muhtemelen Oracle'ın ROWNUM için bir eşdeğer olacaktır ve sayfadaki tüm yorumlardan yukarıdaki şeyleri istediğinizi varsayıyorum. SQL Server 2005 ve sonrası için, satırların dinamik numaralandırması için yeni Sıralama İşlevleri işlevini kullanabilirsiniz.

Örneğin bunu bir sorgumda yapıyorum:

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

Sana vereceğim:

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

Ayrıca support.microsoft.com'da satırları dinamik olarak numaralandırmakla ilgili bir makale var .


Bir kimlik sütununun bir tablodaki bir satırı benzersiz olarak tanımladığını, ancak bir veritabanında olmadığını düşünüyorum.
tuinstoel

Bu doğru, ancak Oracle belgelerinde gördüğüm ROWID tanımına uyuyor: "Harici veri türü ROWID, bir veritabanı tablosundaki belirli bir satırı tanımlar" ... ancak bunu, üst. :) Bunu belirttiğiniz için teşekkürler.
Xiaofu

Satır "numarası" ROWID değil. ROWID, satırın fiziksel konumunu benzersiz bir sayıdan farklı bir şekilde içerir. Özellikle veritabanındaki tüm tablolarda benzersizdir (özel depolama tekniklerinin kullanıldığı bazı istisnalar dışında)
a_horse_with_no_name

6

Yukarıdaki yanıtlardan birkaçı, belirli bir satıra doğrudan başvuru olmamasına geçici bir çözüm olacaktır , ancak bir tablodaki diğer satırlarda değişiklik olursa işe yaramayacaktır . Cevapların teknik olarak yetersiz kaldığı kriterlerim budur.

Oracle'ın ROWID'sinin yaygın bir kullanımı, satırları seçmek için (biraz) kararlı bir yöntem sağlamak ve daha sonra onu işlemek için satıra geri dönmektir (örneğin, GÜNCELLEME). Bir satırı bulma yöntemi (karmaşık birleştirmeler, tam metin arama veya satır satır göz atma ve verilere karşı prosedür testleri uygulama) UPDATE ifadesini nitelemek için kolayca veya güvenli bir şekilde yeniden kullanılamayabilir.

SQL Server RID aynı işlevselliği sağlıyor gibi görünüyor, ancak aynı performansı sağlamıyor. Gördüğüm tek sorun bu ve ne yazık ki bir ROWID tutmanın amacı, örneğin çok büyük bir tablodaki satırı bulmak için pahalı bir işlemi tekrar etmekten kaçınmaktır. Bununla birlikte, birçok durumda performans kabul edilebilir. Microsoft, iyileştiriciyi gelecekteki bir sürümde ayarlarsa, performans sorunu çözülebilir.

Yordamsal bir programda FOR UPDATE'ı kullanmak ve CURSOR'u açık tutmak da mümkündür. Bununla birlikte, bu, büyük veya karmaşık toplu işlemede pahalı olabilir.

Uyarı: Örneğin SELECT ve UPDATE arasındaki DBA, fiziksel satır tanımlayıcısı olduğu için veritabanını yeniden oluşturacak olsaydı Oracle'ın ROWID'si bile kararlı olmayacaktır. Bu nedenle, ROWID cihazı yalnızca iyi kapsamlı bir görevde kullanılmalıdır.


3

Küçük bir veri kümesi için sadece basit satır numaralandırması istiyorsanız, böyle bir şey yapmaya ne dersiniz?

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

Ancak bazı izleyicilerin ROWID'in ne olduğunu bilmeden arayacağı hızlı eklenen kimlik için çalışır.
Graeme

3

Gönderen http://vyaskn.tripod.com/programming_faq.htm#q17 :

Oracle, satır numarasını veya satır kimliğini kullanarak bir tablonun satırlarına erişmek için bir satıra sahiptir. Bunun SQL Server'da herhangi bir eşdeğeri var mı? Veya SQL Server'da satır numarası ile çıktı nasıl oluşturulur?

Oracle'ın SQL Server'daki satır veya satır kimliğine doğrudan bir eşdeğeri yoktur. Açıkçası, ilişkisel bir veritabanında, bir tablodaki satırlar sıralı değildir ve bir satır kimliği gerçekten bir anlam ifade etmez. Ancak bu işleve ihtiyacınız varsa, aşağıdaki üç alternatifi göz önünde bulundurun:

  • IDENTITYTablonuza bir sütun ekleyin .

  • Her satır için bir satır numarası oluşturmak üzere aşağıdaki sorguyu kullanın. Aşağıdaki sorgu, pubs veritabanının yazarlar tablosundaki her satır için bir satır numarası oluşturur. Bu sorgunun çalışması için tablonun benzersiz bir anahtarı olmalıdır.

    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
    
  • Sonuç kümesinin tamamını, IDENTITY() işlev tarafından oluşturulan bir satır kimliğiyle birlikte geçici bir tabloda depolamak için geçici bir tablo yaklaşımı kullanın . Geçici bir tablo oluşturmak, özellikle büyük tablolarla çalışırken maliyetli olacaktır. Tablonuzda benzersiz bir anahtar yoksa bu yaklaşımı kullanın.


3

Tablodaki satırları kalıcı olarak numaralandırmak istiyorsanız, lütfen SQL Server için RID çözümünü kullanmayın. Eski bir 386'daki Access'ten daha kötü performans gösterecektir. SQL Server için basitçe bir IDENTITY sütunu oluşturun ve bu sütunu kümelenmiş birincil anahtar olarak kullanın. Bu, tabloya kalıcı, hızlı bir Tamsayı B-Ağacı yerleştirecek ve daha da önemlisi, kümelenmemiş her indeks, onu satırları bulmak için kullanacaktır. Oracle gibi SQL Server'da geliştirmeye çalışırsanız, düşük performanslı bir veritabanı oluşturursunuz. Motor için optimizasyon yapmanız gerekir, farklı bir motormuş gibi davranmanız gerekmez.

Ayrıca, lütfen Birincil Anahtarı GUID'lerle doldurmak için NewID () kullanmayın, ekleme performansını öldüreceksiniz. GUID'leri kullanmanız gerekiyorsa, sütun varsayılanı olarak NewSequentialID () kullanın. Ancak INT yine de daha hızlı olacak.

Öte yandan, bir sorgudan kaynaklanan satırları numaralandırmak istiyorsanız, sorgu sütunlarından biri olarak SatırNumarası Fazla () işlevini kullanın.




1

Lütfen http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx sayfasına bakın SQL sunucusunda bir zaman damgası bir DateTime sütunu ile aynı değildir. Bu, yalnızca bir tablodaki değil, tüm veritabanındaki bir veritabanındaki bir satırı benzersiz şekilde tanımlamak için kullanılır. Bu, iyimser eşzamanlılık için kullanılabilir. örneğin GÜNCELLEME [İş] SET [Ad] = @ Ad, [XCustomData] = @ XCustomData WHERE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp AND [GUID] = @ Original_GUID

ModifiedTimeStamp, orijinal verileri güncellemenizi sağlar ve satırda başka bir güncelleme olursa başarısız olur.


0

Bu örneği MS SQL örneğinden aldım ve @ID'nin tamsayı veya varchar veya her neyse ile değiştirilebileceğini görebilirsiniz. Bu, aradığım çözümün aynısıydı, bu yüzden onu paylaşıyorum. Zevk almak!!

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

0

ROWID'yi aşağıda verilen yöntemleri kullanarak alabilirsiniz:

1. İçinde otomatik artış alanı olan yeni bir tablo oluşturun

2. İhtiyaçlarınıza göre sıralamayı elde etmek için Row_Number analitik işlevini kullanın. Bunu tercih ederim çünkü belirli bir alanın veya alanların kombinasyonunun artan veya azalan biçiminde row_id istediğiniz durumlarda yardımcı olur

Örnek: Row_Number () Over (Sal desc ile Deptno sırasına göre bölümleme)

Yukarıdaki örnek size her departmanın en yüksek maaşına göre sıra numarasını verecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.