2009-05-26 51 views
62

¿Cuál es el equivalente de RowID de Oracle en SQL Server?Equivalente al RowID de Oracle en SQL Server

+0

Stephanie: se supone que hay una clave única de los datos, lo que supone que los datos se normaliza, que es una incorrecta suposición a veces. Por lo tanto, ¿cuál es el equivalente al RowID de Oracle en el servidor SQL? –

Respuesta

3

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

Oracle tiene una rownum acceder a las filas de una tabla utilizando el número de fila o fila ID. ¿Hay algún equivalente para eso en SQL Server? ¿O cómo generar la salida con el número de fila en SQL Server?

No existe un equivalente directo al rownum o id de fila de Oracle en SQL Servidor. Estrictamente hablando, en una base de datos relacional, las filas dentro de una tabla no están ordenadas y una identificación de fila no tendrá sentido. Pero si necesita esa funcionalidad, considere las siguientes tres alternativas:

  • Añadir una columna IDENTITY a su mesa.

  • Utilice la siguiente consulta para generar un número de fila para cada fila. La siguiente consulta genera un número de fila para cada fila en la tabla de autores de de la base de datos pubs. Para que esta consulta funcione, la tabla debe tener una clave única .

    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 
    
  • utilizan un enfoque de tabla temporal, para almacenar todo el conjunto de resultados en una tabla temporal, junto con un identificador de fila generada por la función IDENTITY() . Crear una tabla temporal será costoso, especialmente cuando está trabajando con tablas grandes. Vaya por este enfoque, si no tiene , tenga una clave única en su tabla.

9

Si desea identificar de forma única una fila dentro de la tabla en lugar de su conjunto de resultados, entonces usted tiene que mirar en el uso de algo así como una columna de identidad. Consulte "Propiedad de IDENTIDAD" en la ayuda de SQL Server. SQL Server no genera automáticamente una ID para cada fila de la tabla como lo hace Oracle, por lo que debe tomarse la molestia de crear su propia columna de ID y obtenerla explícitamente en su consulta.

EDIT: para la numeración dinámica de las filas del conjunto de resultados, pero probablemente sería un equivalente para el ROWNUM de Oracle y supongo que de todos los comentarios en la página que desea lo anterior. Para SQL Server 2005 y posterior, puede usar la nueva función Ranking Functions para lograr la numeración dinámica de filas.

Por ejemplo hago esto en una consulta mío:

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 

le 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 

También hay un artículo sobre support.microsoft.com en filas dinámicamente numeración.

+0

Creo que una columna de identidad identifica de manera única una fila en una tabla pero no en una base de datos. – tuinstoel

+0

Esto es cierto, pero eso se ajusta a la definición de ROWID que veo en los documentos de Oracle: "El tipo de datos externo ROWID identifica una fila en particular en una tabla de base de datos" ... pero veo que estás diciendo esto debido a mi error tipográfico en la parte superior. :) Gracias por señalar eso. – Xiaofu

+0

Eso es solo una parte de la definición. No cambia de consulta a consulta ... –

6

Echa un vistazo a la nueva función ROW_NUMBER. Funciona así:

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

Creo que este es un reemplazo para rownum y no rowid. – tuinstoel

2

si solo desea la numeración de filas básica para un pequeño conjunto de datos, ¿qué tal algo así?

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

No es lo que es un rowid. –

+0

Pero funciona para una identificación rápida que algunos espectadores estarán buscando, sin saber qué es ROWID. – Graeme

0

Tomé este ejemplo del ejemplo MS SQL y se puede ver la @ID se puede intercambiar con número entero o varchar o lo que sea. Esta era la misma solución que estaba buscando, así que la estoy compartiendo. ¡¡Disfrutar!!

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

Para cada fila en la base de datos, la pseudocolumna ROWID devuelve la dirección de la fila. los valores de base de datos ROWID de Oracle contienen información necesario localizar una fila:

  • el número del objeto de datos del objeto
  • El bloque de datos en el archivo de datos en el que la fila reside
  • La posición de la fila de la bloque de datos (la primera fila es 0)
  • El archivo de datos en el que reside la fila (el primer archivo es 1). El número de archivo es relativo al tablespace.

El equivalente más cercano a esto en SQL Server es el rid que tiene tres componentes File:Page:Slot.

En SQL Server 2008, es posible utilizar la columna virtual %%physloc%% no documentada y no admitida para ver esto. Esto devuelve un valor binary(8) con el ID de página en los primeros cuatro bytes, luego 2 bytes para ID de archivo, seguido de 2 bytes para la ubicación de ranura en la página.

La función escalar sys.fn_PhysLocFormatter o la sys.fn_PhysLocCracker TVF se puede utilizar para convertir esto en una forma más legible

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 

Ejemplo de Salida

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

cuenta que esto no es aprovechado por el procesador de consultas. Si bien es posible usar esto en una cláusula WHERE

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

SQL Server no buscan directamente a la fila especificada. En su lugar, realizará un escaneo completo de la tabla, evalúe %%physloc%% para cada fila y devuelva la que coincida (si corresponde).

Para invertir el proceso llevado a cabo por las 2 funciones mencionadas anteriormente y obtener el valor binary(8) correspondiente a los valores conocidos de Archivo, Página, Ranura, se puede utilizar lo siguiente.

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

Varias de las respuestas anteriores voluntad trabajo en torno a la falta de una referencia directa a una fila específica, pero no va a funcionar si se producen cambios en las otras filas de una tabla. Ese es mi criterio para el cual las respuestas son técnicamente cortas.

Un uso común de ROWID de Oracle es proporcionar un método (un tanto) estable de seleccionar filas y volver más tarde a la fila para procesarlo (por ejemplo, para ACTUALIZARLO). El método para buscar una fila (combinaciones complejas, búsqueda de texto completo o navegación fila por línea y la aplicación de pruebas de procedimiento en comparación con los datos) puede no volverse a utilizar fácilmente o con seguridad para calificar la instrucción UPDATE.

El SQL Server RID parece proporcionar la misma funcionalidad, pero no proporciona el mismo rendimiento. Ese es el único problema que veo, y desafortunadamente el propósito de conservar un ROWID es evitar repetir una operación costosa para encontrar la fila en, por ejemplo, una tabla muy grande. No obstante, el rendimiento en muchos casos es aceptable. Si Microsoft ajusta el optimizador en una versión futura, se podría abordar el problema de rendimiento.

También es posible usar FOR UPDATE y mantener el CURSOR abierto en un programa de procedimiento. Sin embargo, esto podría resultar costoso en el procesamiento de lotes grandes o complejos.

Advertencia: ROWID Incluso de Oracle no sería estable si el DBA, entre el SELECT y UPDATE, por ejemplo, eran para reconstruir la base de datos, ya que es el identificador de fila física. Por lo tanto, el dispositivo ROWID solo se debe usar dentro de una tarea con un buen alcance.

1

Consulte http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx En el servidor SQL, una marca de tiempo no es lo mismo que una columna DateTime. Esto se utiliza para identificar de manera única una fila en una base de datos, no solo una tabla, sino toda la base de datos. Esto se puede usar para concurrencia optimista. por ejemplo ACTUALIZACIÓN [Trabajo] SET [Nombre] = @ Nombre, [XCustomData] = @ XCustomData DONDE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp Y [GUID] = @ Original_GUID

la ModifiedTimeStamp asegura que está actualizando los datos originales y fallará si se ha producido otra actualización en la fila.

3

Si desea numerar permanentemente las filas en la tabla, no utilice la solución RID para SQL Server. Se ejecutará peor que Access en una antigua 386 Para SQL Server, simplemente cree una columna IDENTITY y use esa columna como una clave primaria agrupada. Esto colocará un Integer B-Tree permanente y rápido en la tabla, y lo que es más importante, cada índice no agrupado lo usará para ubicar filas. Si intentas desarrollar en SQL Server como si fuera Oracle yo creará una base de datos de bajo rendimiento. Necesita optimizar para el motor, no pretender que es un motor diferente.

Además, no use NewID() para rellenar la clave principal con GUID, matará el rendimiento de la inserción. Si debe usar GUID, use NewSequentialID() como columna predeterminada. Pero INT aún será más rápido.

Si, por otro lado, simplemente desea numerar las filas que resultan de una consulta, utilice la función RowNumber Over() como una de las columnas de la consulta.

3

Tengo que dedupe una mesa muy grande con muchas columnas y la velocidad es importante.Por lo tanto utilizo este método que funciona para cualquier tabla:

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

Puede obtener el ROWID utilizando los métodos que se indican a continuación:

1.Create una nueva tabla con el campo de incremento automático en ella

2.Utilice la función analítica Row_Number para obtener la secuencia según su requisito. Preferiría esto porque ayuda en las situaciones en las que desea el row_id en forma ascendente o descendente de un campo específico o combinación de campos

Ejemplo: Row_Number() Ove r (por orden de reparto DEPTNO por desc SAL)

Por encima de la muestra le dará el número de secuencia más alto basado en el salario de cada department.Partition por es opcional y se puede eliminar de acuerdo a sus necesidades

Cuestiones relacionadas