Was entspricht der RowID von Oracle in SQL Server?
Was entspricht der RowID von Oracle in SQL Server?
Antworten:
ROWID Pseudospalte
Für jede Zeile in der Datenbank gibt die ROWID-Pseudospalte die Adresse der Zeile zurück. Die Zeilen-ID-Werte der Oracle-Datenbank enthalten Informationen, die zum Auffinden einer Zeile erforderlich sind:
- Die Datenobjektnummer des Objekts
- Der Datenblock in der Datendatei, in der sich die Zeile befindet
- Die Position der Zeile im Datenblock (erste Zeile ist 0)
- Die Datendatei, in der sich die Zeile befindet (erste Datei ist 1). Die Dateinummer ist relativ zum Tabellenbereich.
Das nächste Äquivalent dazu in SQL Server ist rid
das mit drei Komponenten File:Page:Slot
.
In SQL Server 2008 ist es möglich, die undokumentierte und nicht unterstützte %%physloc%%
virtuelle Spalte zu verwenden, um dies anzuzeigen . Dies gibt einen binary(8)
Wert mit der Seiten-ID in den ersten vier Bytes zurück, dann 2 Bytes für die Datei-ID, gefolgt von 2 Bytes für die Position des Steckplatzes auf der Seite.
Die Skalarfunktion sys.fn_PhysLocFormatter
oder die sys.fn_PhysLocCracker
TVF können verwendet werden, um dies in eine besser lesbare Form umzuwandeln
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
Beispielausgabe
+--------------------+----------------+
| %%physloc%% | File:Page:Slot |
+--------------------+----------------+
| 0x2926020001000000 | (1:140841:0) |
| 0x2926020001000100 | (1:140841:1) |
+--------------------+----------------+
Beachten Sie, dass dies vom Abfrageprozessor nicht genutzt wird. Es ist zwar möglich , dies in einer WHERE
Klausel zu verwenden
SELECT *
FROM T
WHERE %%physloc%% = 0x2926020001000100
SQL Server sucht nicht direkt nach der angegebenen Zeile. Stattdessen wird ein vollständiger Tabellenscan durchgeführt, %%physloc%%
für jede Zeile ausgewertet und die übereinstimmende zurückgegeben (falls vorhanden).
Um den von den beiden zuvor genannten Funktionen ausgeführten Vorgang umzukehren und den binary(8)
Wert zu erhalten, der den bekannten Werten für Datei, Seite und Steckplatz entspricht, können die folgenden Werte verwendet werden.
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))
Ich muss einen sehr großen Tisch mit vielen Spalten deduplizieren und Geschwindigkeit ist wichtig. Daher verwende ich diese Methode, die für jede Tabelle funktioniert:
delete T from
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1
Überprüfen Sie die neue Funktion ROW_NUMBER . Es funktioniert so:
SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
Wenn Sie eine Zeile in der Tabelle und nicht Ihre Ergebnismenge eindeutig identifizieren möchten, müssen Sie die Verwendung einer IDENTITY-Spalte in Betracht ziehen. Siehe "IDENTITY-Eigenschaft" in der SQL Server-Hilfe. SQL Server generiert nicht wie Oracle automatisch eine ID für jede Zeile in der Tabelle. Sie müssen sich also die Mühe machen, eine eigene ID-Spalte zu erstellen und diese explizit in Ihrer Abfrage abzurufen.
BEARBEITEN: Für die dynamische Nummerierung von Ergebnismengenzeilen siehe unten, aber das wäre wahrscheinlich ein Äquivalent für Oracle ROWNUM, und ich gehe von allen Kommentaren auf der Seite davon aus, dass Sie das obige Material möchten. Für SQL Server 2005 und höher können Sie die neue Funktion "Ranking-Funktionen" verwenden, um eine dynamische Nummerierung von Zeilen zu erreichen.
Zum Beispiel mache ich das bei einer Abfrage von mir:
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
Werde dir geben:
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
Es gibt auch einen Artikel auf support.microsoft.com über die dynamische Nummerierung von Zeilen.
Einige der oben genannten Antworten arbeiten um das Fehlen einer direkten Bezug zu einer bestimmten Zeile, aber wird nicht funktionieren , wenn Änderungen auftreten , zu den anderen Zeilen in einer Tabelle. Das sind meine Kriterien, für die die Antworten technisch unzureichend sind.
Eine häufige Verwendung der ROWID von Oracle besteht darin, eine (etwas) stabile Methode zum Auswählen von Zeilen und zum späteren Zurückkehren in die Zeile bereitzustellen, um sie zu verarbeiten (z. B. um sie zu aktualisieren). Die Methode zum Suchen einer Zeile (komplexe Verknüpfungen, Volltextsuche oder zeilenweises Durchsuchen und Anwenden von Prozedurtests auf die Daten) kann möglicherweise nicht einfach oder sicher wiederverwendet werden, um die UPDATE-Anweisung zu qualifizieren.
Die SQL Server-RID scheint dieselbe Funktionalität zu bieten, bietet jedoch nicht dieselbe Leistung. Dies ist das einzige Problem, das ich sehe, und leider besteht der Zweck der Beibehaltung einer ROWID darin, zu vermeiden, dass eine teure Operation wiederholt wird, um die Zeile beispielsweise in einer sehr großen Tabelle zu finden. Trotzdem ist die Leistung in vielen Fällen akzeptabel. Wenn Microsoft das Optimierungsprogramm in einer zukünftigen Version anpasst, kann das Leistungsproblem behoben werden.
Es ist auch möglich, FOR UPDATE einfach zu verwenden und den CURSOR in einem prozeduralen Programm offen zu halten. Dies könnte sich jedoch bei der Verarbeitung großer oder komplexer Chargen als teuer erweisen.
Vorsichtsmaßnahme: Selbst die ROWID von Oracle wäre nicht stabil, wenn der DBA zwischen SELECT und UPDATE beispielsweise die Datenbank neu erstellen würde, da es sich um die physische Zeilen-ID handelt. Das ROWID-Gerät sollte daher nur innerhalb einer gut definierten Aufgabe verwendet werden.
Wenn Sie nur eine einfache Zeilennummerierung für einen kleinen Datensatz wünschen, wie wäre es dann mit so etwas?
SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
Von http://vyaskn.tripod.com/programming_faq.htm#q17 :
Oracle verfügt über ein Rownum für den Zugriff auf Zeilen einer Tabelle mithilfe der Zeilennummer oder der Zeilen-ID. Gibt es dafür ein Äquivalent in SQL Server? Oder wie generiert man eine Ausgabe mit Zeilennummer in SQL Server?
Es gibt keine direkte Entsprechung zu Oracle Rownum oder Zeilen-ID in SQL Server. Genau genommen sind in einer relationalen Datenbank die Zeilen in einer Tabelle nicht geordnet, und eine Zeilen-ID ist nicht wirklich sinnvoll. Wenn Sie diese Funktionalität benötigen, sollten Sie die folgenden drei Alternativen in Betracht ziehen:
Fügen Sie
IDENTITY
Ihrer Tabelle eine Spalte hinzu.Verwenden Sie die folgende Abfrage, um eine Zeilennummer für jede Zeile zu generieren. Die folgende Abfrage generiert eine Zeilennummer für jede Zeile in der Autorentabelle der Pubs-Datenbank. Damit diese Abfrage funktioniert, muss die Tabelle einen eindeutigen Schlüssel haben.
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
Verwenden Sie einen temporären Tabellenansatz, um die gesamte Ergebnismenge zusammen mit einer von der
IDENTITY()
Funktion generierten Zeilen-ID in einer temporären Tabelle zu speichern . Das Erstellen einer temporären Tabelle ist kostspielig, insbesondere wenn Sie mit großen Tabellen arbeiten. Entscheiden Sie sich für diesen Ansatz, wenn Sie keinen eindeutigen Schlüssel in Ihrer Tabelle haben.
Wenn Sie die Zeilen in der Tabelle dauerhaft nummerieren möchten, verwenden Sie bitte nicht die RID-Lösung für SQL Server. Es ist schlechter als Access auf einem alten 386. Erstellen Sie für SQL Server einfach eine IDENTITY-Spalte und verwenden Sie diese Spalte als Cluster-Primärschlüssel. Dadurch wird ein permanenter, schneller Integer-B-Baum in die Tabelle eingefügt, und was noch wichtiger ist, jeder nicht gruppierte Index verwendet ihn zum Auffinden von Zeilen. Wenn Sie versuchen, in SQL Server so zu entwickeln, als wäre es Oracle, erstellen Sie eine Datenbank mit schlechter Leistung. Sie müssen für den Motor optimieren und nicht so tun, als wäre es ein anderer Motor.
Verwenden Sie außerdem nicht die NewID (), um den Primärschlüssel mit GUIDs zu füllen. Andernfalls wird die Leistung beim Einfügen beeinträchtigt. Wenn Sie GUIDs verwenden müssen, verwenden Sie NewSequentialID () als Spaltenstandard. Aber INT wird immer noch schneller sein.
Wenn Sie andererseits einfach die Zeilen nummerieren möchten, die sich aus einer Abfrage ergeben, verwenden Sie die Funktion RowNumber Over () als eine der Abfragespalten.
Bitte versuche
select NEWID()
Quelle: https://docs.microsoft.com/en-us/sql/t-sql/data-types/uniqueidentifier-transact-sql
ROWID ist eine versteckte Spalte in Oracle-Tabellen. Erstellen Sie daher für SQL Server eine eigene Spalte. Fügen Sie eine Spalte mit dem Namen ROWID mit dem Standardwert von hinzu NEWID()
.
Vorgehensweise: Fügen Sie der vorhandenen Tabelle in SQL Server eine Spalte mit dem Standardwert hinzu
Weitere Informationen finden Sie unter http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx. In SQL Server entspricht ein Zeitstempel nicht einer DateTime-Spalte. Dies wird verwendet, um eine Zeile in einer Datenbank eindeutig zu identifizieren, nicht nur eine Tabelle, sondern die gesamte Datenbank. Dies kann für eine optimistische Parallelität verwendet werden. Beispiel: UPDATE [Job] SET [Name] = @ Name, [XCustomData] = @ XCustomData WHERE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp AND [GUID] = @ Original_GUID
Der ModifiedTimeStamp stellt sicher, dass Sie die Originaldaten aktualisieren, und schlägt fehl, wenn die Zeile erneut aktualisiert wurde.
Ich habe dieses Beispiel aus dem MS SQL-Beispiel genommen und Sie können sehen, dass die @ID mit einer Ganzzahl oder einem Varchar oder was auch immer ausgetauscht werden kann. Dies war die gleiche Lösung, nach der ich gesucht habe, also teile ich sie. Genießen!!
-- 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
Sie können die ROWID mithilfe der folgenden Methoden abrufen:
1.Erstellen Sie eine neue Tabelle mit einem Feld für die automatische Inkrementierung
2.Verwenden Sie die Analysefunktion Row_Number, um die Sequenz basierend auf Ihren Anforderungen zu erhalten. Ich würde dies bevorzugen, da dies in Situationen hilfreich ist, in denen Sie möchten, dass die row_id in aufsteigender oder absteigender Weise eines bestimmten Felds oder einer Kombination von Feldern angezeigt wird
Beispiel: Row_Number () Over (Partition nach Deptno Reihenfolge nach sal desc)
Das obige Beispiel gibt Ihnen die Sequenznummer basierend auf dem höchsten Gehalt jeder Abteilung. Die Aufteilung nach ist optional und Sie können sie gemäß Ihren Anforderungen entfernen