2009-05-26 21 views
62

Qual è l'equivalente di RowID di Oracle in SQL Server?Equivalente di RowID di Oracle in SQL Server

+0

Stephanie: l'ipotesi è che v'è una chiave univoca nei dati, che assume i dati vengono normalizzati, che è un errato ipotesi a volte. Quindi, qual è l'equivalente di RowID di Oracle nel server SQL. –

risposta

3

Da http://vyaskn.tripod.com/programming_faq.htm#q17:

Oracle ha una rownum per accedere alle righe di una tabella utilizzando numero di riga o riga id. C'è qualche equivalente per quello in SQL Server? O come generare l'emissione con il numero di riga in SQL Server?

Non esiste un equivalente diretto al rownum o ID riga di Oracle nel server SQL . A rigor di termini, in un database relazionale, le righe all'interno di una tabella non sono ordinate e un ID di riga non ha realmente senso. Ma se si bisogno di tale funzionalità, considerare i seguenti tre alternative:

  • aggiungere una colonna IDENTITY al tavolo.

  • Utilizzare la seguente query per generare un numero di riga per ogni riga. La seguente query genera un numero di riga per ogni riga nella tabella di pubs del database pubs. Perché questa query funzioni, la tabella deve avere una chiave univoca .

    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 
    
  • utilizzare un approccio tabella temporanea, per memorizzare l'intero gruppo di risultati in una tabella temporanea, oltre ad id fila generato dalla funzione IDENTITY() . La creazione di una tabella temporanea sarà costosa, specialmente quando si sta lavorando con tabelle di grandi dimensioni. Vai per questo approccio, se non hai avere una chiave univoca nella tua tabella.

9

Se si vuole identificare in modo univoco una riga all'interno della tabella piuttosto che il vostro set di risultati, allora avete bisogno di guardare con qualcosa di simile a una colonna IDENTITY. Vedere "Proprietà IDENTITY" nella guida di SQL Server. SQL Server non genera automaticamente un ID per ogni riga della tabella come fa Oracle, quindi è necessario risolvere il problema della creazione della propria colonna ID e recuperarla esplicitamente nella query.

MODIFICA: per la numerazione dinamica delle righe dei set di risultati, vedere di seguito, ma probabilmente sarebbe un equivalente per ROWNUM di Oracle e presuppongo da tutti i commenti sulla pagina che si desidera il materiale sopra riportato. Per SQL Server 2005 e versioni successive è possibile utilizzare la nuova funzione Ranking Functions per ottenere la numerazione dinamica delle righe.

Per esempio io faccio su una query di mine:

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 

vi darà:

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'è anche un articolo su support.microsoft.com sulle righe di numerazione in modo dinamico.

+0

Penso che una colonna Identity identifica in modo univoco una riga in una tabella ma non in un database. – tuinstoel

+0

Questo è vero, ma corrisponde alla definizione di ROWID che vedo nei documenti Oracle: "Il tipo di dati esterno ROWID identifica una particolare riga in una tabella di database" ... ma vedo che stai dicendo questo a causa del mio errore di battitura a la cima. :) Grazie per la segnalazione. – Xiaofu

+0

Questa è solo una parte della definizione. Non cambia da query a query ... –

6

Controlla la nuova funzione ROW_NUMBER. Funziona così:

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

Penso che questo sia un sostituto per rownum e non per il rowid. – tuinstoel

2

se si desidera solo la numerazione di riga di base per un set di dati di piccole dimensioni, che ne dite di qualcosa del genere?

+7

Non è un rowid. –

+0

Ma funziona per l'ID aggiunto rapido che alcuni utenti cercheranno, non sapendo cosa sia ROWID. – Graeme

0

ho preso questo esempio da esempio MS SQL e si può vedere la @ID è intercambiabile con numero intero o varchar o qualsiasi altra cosa. Questa era la stessa soluzione che stavo cercando, quindi la sto condividendo. Godere!!

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

From the Oracle docs

ROWID pseudocolonna

Per ogni riga nel database, il pseudocolonna ROWID restituisce l'indirizzo della riga. Oracle valori ROWID Database contengono informazioni necessarie per individuare una riga:

  • Il numero oggetto dati dell'oggetto
  • Il blocco di dati nel file di dati in cui la riga risiede
  • La posizione della riga in blocco dati (la prima riga è 0)
  • Il file di dati in cui risiede la riga (il primo file è 1). Il numero del file è relativo al tablespace.

L'equivalente più vicino a questo in SQL Server è il rid che ha tre componenti File:Page:Slot.

In SQL Server 2008 è possibile utilizzare la colonna virtuale %%physloc%% non documentata e non supportata per visualizzarla. Ciò restituisce un valore binary(8) con l'ID pagina nei primi quattro byte, quindi 2 byte per ID file, seguito da 2 byte per la posizione dello slot nella pagina.

La funzione scalare sys.fn_PhysLocFormatter o sys.fn_PhysLocCracker TVF può essere utilizzato per convertirlo in una forma più leggibile

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 

Esempio di output

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

noti che questo non viene sfruttato dal processore di query. Mentre è possibile da utilizzare in una clausola WHERE

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

SQL Server non direttamente cercano di riga specificata. Effettua invece una scansione completa della tabella, valuta %%physloc%% per ogni riga e restituisce quella che corrisponde (se ce ne sono).

Per invertire il processo eseguito dalle 2 funzioni precedentemente citate e ottenere il valore binary(8) corrispondente ai valori noti di File, Pagina, Slot, è possibile utilizzare quanto riportato di seguito.

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

Molte delle risposte sopra volontà aggirare la mancanza di un riferimento diretto ad una riga specifica, ma non funzionerà se si verificano cambiamenti alle altre righe di una tabella. Questo è il mio criterio per cui le risposte sono tecnicamente brevi.

Un uso comune di ROWID di Oracle consiste nel fornire un metodo (un po ') stabile per selezionare le righe e successivamente tornare alla riga per elaborarlo (ad es. UPDATE). Il metodo per trovare una riga (join complessi, ricerca full-text o ricerca riga per riga e test procedurali contro i dati) non può essere riutilizzato facilmente o in sicurezza per qualificare l'istruzione UPDATE.

Il RID SQL Server sembra fornire la stessa funzionalità, ma non offre le stesse prestazioni. Questo è l'unico problema che vedo, e sfortunatamente lo scopo di mantenere un ROWID è di evitare di ripetere un'operazione costosa per trovare la riga, ad esempio, in una tabella molto grande. Ciononostante, le prestazioni per molti casi sono accettabili. Se Microsoft aggiusta l'ottimizzatore in una versione futura, il problema delle prestazioni potrebbe essere risolto.

È anche possibile utilizzare semplicemente FOR UPDATE e mantenere il CURSOR aperto in un programma procedurale. Tuttavia, questo potrebbe rivelarsi costoso nell'elaborazione batch di grandi o complessi.

Caveat: ROWID Anche Oracle non sarebbe stabile se il DBA, tra il SELECT e UPDATE, per esempio, dovesse ricostruire il database, perché è l'identificatore di riga fisica. Pertanto, il dispositivo ROWID deve essere utilizzato solo nell'ambito di un'attività ben definita.

1

Si prega di vedere http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx Nel server SQL un timestamp non è la stessa di una colonna DateTime. Questo è usato per identificare in modo univoco una riga in un database, non solo una tabella ma l'intero database. Questo può essere usato per una concorrenza ottimistica. per esempio UPDATE [lavoro] SET [Nome] = @ Nome, [XCustomData] = @ XCustomData WHERE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp E [GUID] = @ Original_GUID

la ModifiedTimeStamp assicura che si sta aggiornando i dati originali e non riuscirà se si verifica un altro aggiornamento alla riga

3

Se si desidera numerare in modo permanente le righe nella tabella, non utilizzare la soluzione RID per SQL Server. Funzionerà in modo peggiore di Access su un 386 vecchio Per SQL Server è sufficiente creare una colonna IDENTITY e utilizzare tale colonna come chiave primaria in cluster, in modo da posizionare un B-Tree intero intero rapido e permanente sulla tabella e, cosa più importante, ogni indice non cluster lo utilizzerà per individuare le righe. Se si tenta di sviluppare in SQL Server come se fosse Oracle yo creerai un database mal funzionante. È necessario ottimizzare il motore, non fingere che si tratti di un motore diverso.

inoltre, si prega di non utilizzare il NewID() per popolare la chiave primaria con GUID, si ucciderà le prestazioni dell'inserto. Se è necessario utilizzare GUID, utilizzare NewSequentialID() come valore predefinito della colonna. Ma INT sarà ancora più veloce.

Se invece si desidera semplicemente numerare le righe risultanti da una query, utilizzare la funzione RowNumber Over() come una delle colonne della query.

3

Devo deduplicare una tabella molto grande con molte colonne e la velocità è importante.Così Io uso questo metodo che funziona per qualsiasi tabella:

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

È possibile ottenere il ROWID utilizzando i metodi indicati di seguito:

1.Creare una nuova tabella con il campo di incremento automatico in esso

2.Utilizzare la funzione analitica Row_Number per ottenere la sequenza in base al requisito. Preferirei questo perché aiuta nelle situazioni in cui si desidera il row_id in modo crescente o decrescente di un campo specifico o combinazione di campi

Esempio: Row_Number() Ove r (partizione per ordine DEPTNO da SAL decrescente)

Sopra campione vi darà il numero di sequenza sulla base di stipendio più alto di ogni department.Partition da è opzionale e si può rimuovere in base alle proprie esigenze