Équivalent du RowID D'Oracle dans SQL Server

Quel est l'équivalent du RowID D'Oracle dans SQL Server?

68
demandé sur John Saunders 2009-05-26 10:20:05

13 réponses

de L'Oracle

pseudo-colonne ROWID

pour chaque ligne de la base de données, la pseudocolumn ROWID renvoie la l'adresse de la ligne. Les valeurs rowid de la base de données Oracle contiennent des informations nécessaire pour localiser une rangée:

  • le numéro d'objet de données de l'objet
  • Le bloc de données dans la fichier de données dans laquelle la ligne réside
  • la position de la rangée dans le bloc de données (la première rangée est 0)
  • le fichier de données dans lequel la ligne réside (le premier fichier est 1). Fichier nombre est relatif à l'espace de table.

l'équivalent le plus proche de cela dans SQL Server est le rid qui a trois composants File:Page:Slot .

dans SQL Server 2008, il est possible d'utiliser la colonne virtuelle non documentée et non supportée %%physloc%% pour voir ceci. Cela renvoie une valeur binary(8) avec L'ID de Page dans les quatre premiers octets, puis 2 octets pour L'ID du fichier, suivi de 2 octets pour l'emplacement de fente sur la page.

la fonction scalaire sys.fn_PhysLocFormatter ou le sys.fn_PhysLocCracker TVF peut être utilisé pour convertir cela dans une forme plus lisible

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

Exemple De Sortie

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

Notez que c'est pas exploité par le processeur de requête. Alors qu'il est possible à utiliser dans une WHERE clause

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

SQL Server va pas chercher directement à la ligne spécifiée. Au lieu de cela, il effectuera un balayage complet de la table, évaluera %%physloc%% pour chaque ligne et retournera celle qui correspond (s'il y a lieu).

pour inverser le processus effectué par les 2 fonctions précédemment mentionnées et obtenir le binary(8) valeur correspondant à des valeurs connues de fichier,Page,Slot ci-dessous peut être utilisé.

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))
109
répondu Martin Smith 2013-05-17 07:42:39

si vous voulez identifier de façon unique une ligne dans la table plutôt que votre ensemble de résultats, alors vous devez regarder en utilisant quelque chose comme une colonne D'identité. Voir "propriété D'identité" dans L'aide de SQL Server. SQL Server ne génère pas automatiquement un ID pour chaque ligne de la table comme le fait Oracle, donc vous devez vous donner la peine de créer votre propre colonne ID et explicitement le récupérer dans votre requête.

EDIT: pour la dynamique de la numérotation des lignes de jeu de résultats voir ci-dessous, mais ce serait probablement un équivalent pour le ROWNUM D'Oracle et je suppose de tous les commentaires sur la page que vous voulez la substance ci-dessus. Pour SQL Server 2005 et les suivantes, vous pouvez utiliser la nouvelle fonction de classement pour obtenir une numérotation dynamique des lignes.

par exemple je le fais sur une requête de la mienne:

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

vous donnera:

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

il y a aussi un article sur support.microsoft.com sur les lignes à numérotation dynamique.

9
répondu Xiaofu 2009-05-26 07:59:28

Vérifiez la nouvelle fonction ROW_NUMBER . Cela fonctionne comme ceci:

SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
6
répondu Daren Thomas 2009-05-26 06:50:06

plusieurs des réponses ci-dessus seront travailler autour de l'absence d'une référence directe à une ligne spécifique, mais ne fonctionnera pas si des changements se produisent aux autres lignes d'un tableau. C'est mon critère pour lequel les réponses sont techniquement insuffisantes.

une utilisation courante de ROWID D'Oracle est de fournir une méthode (quelque peu) stable de sélectionner des lignes et de revenir plus tard à la ligne pour la traiter (par exemple, pour la mettre à jour). La méthode pour trouver un ligne (des jointures complexes, la recherche plein texte, de la navigation ou ligne par ligne et en appliquant la procédure des tests sur les données) ne peut pas être facilement et en toute sécurité ré-utilisé pour qualifier l'instruction de mise à JOUR.

le SQL Server RID semble fournir la même fonctionnalité, mais ne fournit pas la même performance. C'est la seule question que je vois, et malheureusement l'objectif de conserver un ROWID est d'éviter de répéter une opération coûteuse pour trouver la rangée dans, disons, une très grande table. Néanmoins, dans de nombreux cas, le rendement est acceptable. Si Microsoft ajuste l'optimiseur dans une version future, le problème pourrait être résolu.

il est également possible d'utiliser simplement pour mettre à jour et garder le curseur ouvert dans un programme de procédure. Toutefois, cela pourrait s'avérer coûteux dans le cas d'un traitement par lots de grande envergure ou complexe.

mise en garde: même le ROWID D'Oracle ne serait pas stable si le DBA, entre le SELECT et la mise à jour, pour exemple, étaient de reconstruire la base de données, parce qu'il s'agit de l'Identificateur de ligne physique. Le dispositif ROWID ne doit donc être utilisé que dans le cadre d'une tâche bien précise.

6
répondu Vincent 2011-09-28 16:54:13

je dois démonter une très grande table avec beaucoup de colonnes et la vitesse est importante. Ainsi j'utilise cette méthode qui fonctionne pour n'importe quelle table:

delete T from 
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1
5
répondu S Wright 2016-11-10 19:19:01

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

Oracle a un rownum pour accéder aux lignes d'une table en utilisant le numéro de ligne ou le numéro d'identification de ligne. Y a-t-il un équivalent pour cela dans SQL Server? Ou comment générer sortie avec le numéro de ligne dans le serveur SQL?

il n'y a pas d'équivalent direct au rownum ou au row id D'Oracle en SQL Serveur. À proprement parler, dans une base de données relationnelle, les lignes à l'intérieur d'un les tables ne sont pas ordonnées et un numéro d'identification de ligne n'a pas vraiment de sens. Mais si vous besoin de cette fonctionnalité, envisager les trois alternatives suivantes:

  • ajouter une colonne IDENTITY à votre tableau.

  • Utiliser la requête suivante pour générer un numéro de ligne pour chaque ligne. La requête suivante génère un numéro de ligne pour chaque ligne dans les auteurs table de base de données pubs. Pour cette requête travailler, la table doit avoir un clé unique.

    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
    
  • utilisez une approche de table temporaire, pour stocker l'ensemble des résultats dans une table temporaire, avec un ID de ligne généré par le IDENTITY() fonction. La création d'une table temporaire sera coûteuse, surtout si vous travaillez avec de grandes tables. Pour cette approche, si vous n'avez pas avoir une clé unique dans votre table.

3
répondu Curt J. Sampson 2012-07-23 20:06:22

si vous voulez numéroter en permanence les lignes dans le tableau, S'il vous plaît n'utilisez pas la solution RID pour SQL Server. Il sera pire que L'accès sur un vieux 386. Pour SQL Server, créez simplement une colonne D'identité, et utilisez cette colonne comme une clé primaire groupée. Cela placera un arbre B-entier permanent et rapide sur la table, et plus important encore, chaque index non-groupé l'utilisera pour localiser les lignes. Si vous essayez de vous développer dans SQL Server comme si C'était Oracle, vous créerez une mauvaise performance la base de données. Vous devez optimiser pour le moteur, pas prétendre que c'est un autre moteur.

aussi, s'il vous plaît n'utilisez pas le NewID() pour peupler la clé primaire avec des GUIDs, vous allez tuer la performance insert. Si vous devez utiliser GUIDs, utilisez NewSequentialID () comme colonne par défaut. Mais L'INT sera encore plus rapide.

si d'un autre côté, vous voulez simplement numéroter les lignes qui résultent d'une requête, utilisez la fonction RowNumber Over() comme l'une des colonnes de requête.

3
répondu user2793105 2013-09-18 20:28:07

si vous voulez simplement numéroter une ligne de base pour un petit ensemble de données, que diriez-vous de quelque chose comme ça?

SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
2
répondu Adrian Carneiro 2011-06-23 19:28:11

ROWID est une colonne cachée sur les tables Oracle, donc, pour SQL Server, construisez la vôtre. Ajouter une colonne appelée ROWID avec une valeur par défaut de NEWID() .

Comment faire: ajouter colonne, avec valeur par défaut, à la table existante dans le serveur SQL

1
répondu Erik 2017-05-23 11:47:18

j'ai pris cet exemple de MS SQL exemple et vous pouvez voir le @ID peut être interchangé avec integer ou varchar ou quoi que ce soit. C'est la même solution que je cherchais, donc je le partage. Profitez-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
0
répondu barry austra 2011-09-23 18:48:24

vous pouvez obtenir le ROWID en utilisant les méthodes indiquées ci-dessous:

1.Créer une nouvelle table avec le champ auto increment EN it

2.Utilisez la fonction d'analyse Row_Number pour obtenir la séquence basée sur vos besoins.Je préférerais cela parce qu'il aide dans les situations où vous êtes vous voulez le row_id sur la manière ascendante ou descendante d'un champ spécifique ou d'une combinaison de champs

exemple: Row_Number () Over (Partition by Deptno ordonnance de sal desc)

ci-dessus vous donnera le numéro de séquence basé sur le salaire le plus élevé de chaque département.Partition by est facultatif et vous pouvez le supprimer selon vos exigences

0
répondu Saurabh Gautam 2017-03-23 08:11:01