Partager via


TOP (Transact-SQL)

S’applique à :SQL ServerBase de données Azure SQLAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Point de terminaison d'analyse SQL dans Microsoft FabricEntrepôt dans Microsoft FabricBase de données SQL dans Microsoft Fabric

Limite les lignes retournées dans un jeu de résultats de la requête à un nombre spécifié de lignes ou à un pourcentage de lignes dans SQL Server. Lorsque vous utilisez TOP avec la clause ORDER BY, le jeu de résultats est limité au premier n nombre de lignes ordonnées. Sinon, TOP retourne le premier n nombre de lignes dans un ordre non défini. Utilisez cette clause pour spécifier le nombre de lignes retournées à partir d’une instruction SELECT. Vous pouvez également utiliser TOP pour spécifier les lignes affectées par une instruction INSERT, UPDATE, MERGEou DELETE.

Conventions de la syntaxe Transact-SQL

Syntaxe

Syntaxe pour SQL Server et Azure SQL Database :

[
    TOP (expression) [ PERCENT ]
    [ WITH TIES ]
]

Syntaxe pour azure Synapse Analytics and Analytics Platform System (PDW) :

[
    TOP ( expression )
    [ WITH TIES ]
]

Arguments

expression

Expression numérique qui définit le nombre de lignes à renvoyer. expression est implicitement convertie en valeur de float si vous spécifiez . Sinon, expression est converti en une valeur de type bigint.

PERCENT

Indique que la requête retourne seulement les premiers expression % des lignes du jeu de résultats. Les valeurs fractionnaires sont arrondies à la valeur entière suivante.

WITH TIES

Retourne au moins deux lignes liées au dernier emplacement dans le jeu de résultats limité. Vous devez utiliser cet argument avec la clause ORDER BY. WITH TIES peut renvoyer plus de lignes que la valeur spécifiée dans expression. Par exemple, si expression est définie sur 5 mais que deux lignes supplémentaires correspondent aux valeurs des colonnes ORDER BY dans la ligne 5, le jeu de résultats contient sept lignes.

Vous pouvez spécifier la clause TOP avec l’argument WITH TIES uniquement dans les instructions SELECT, et uniquement si vous spécifiez également la clause ORDER BY. L'ordre retourné pour la liaison des enregistrements est arbitraire. ORDER BY n’affecte pas cette règle.

Meilleures pratiques

Dans une instruction SELECT, utilisez toujours une clause ORDER BY avec la clause TOP. Il s’agit de la seule façon d’indiquer de manière prévisible les lignes affectées par TOP.

Utilisez OFFSET et FETCH dans la clause ORDER BY au lieu de la clause TOP pour implémenter une solution de pagination de requête. Une solution de pagination (autrement dit, l’envoi de blocs ou de pages de données au client) est plus facile à implémenter à l’aide de OFFSET et de clauses FETCH. Pour plus d’informations, consultez clause SELECT - ORDER BY.

Utilisez TOP (ou OFFSET et FETCH) au lieu de SET ROWCOUNT pour limiter le nombre de lignes retournées. Ces méthodes sont préférées à l’utilisation de SET ROWCOUNT pour les raisons suivantes :

  • Dans le cadre d’une instruction SELECT, l’optimiseur de requête peut prendre en compte la valeur de expression dans les clauses TOP ou FETCH lors de l’optimisation des requêtes. Étant donné que vous utilisez SET ROWCOUNT en dehors d’une instruction qui exécute une requête, sa valeur ne peut pas être considérée dans un plan de requête.

Prise en charge de la compatibilité

Pour la compatibilité descendante, les parenthèses sont facultatives dans les instructions SELECT si l’expression est une constante entière. Nous vous recommandons d’utiliser toujours des parenthèses pour TOP dans les instructions SELECT. Cela fournit une cohérence avec son utilisation requise dans les instructions INSERT, UPDATE, MERGEet DELETE.

Interopérabilité

L’expression TOP n’affecte pas les instructions qui peuvent s’exécuter en raison d’un déclencheur. Les tables inserted et deleted dans les déclencheurs retournent uniquement les lignes réellement affectées par les instructions INSERT, UPDATE, MERGEou DELETE. Par exemple, si une INSERT TRIGGER se déclenche à la suite d’une instruction INSERT qui a utilisé une clause TOP.

SQL Server tient compte de la mise à jour de lignes via des vues. Étant donné que vous pouvez inclure la clause TOP dans la définition d’affichage, certaines lignes peuvent disparaître de la vue si les lignes ne répondent plus aux exigences de l’expression TOP en raison d’une mise à jour.

Lorsqu’elle est spécifiée dans l’instruction MERGE, la clause TOP s’applique après la table source entière et la table cible entière est jointe. Les lignes jointes non éligibles à une action INSERT, UPDATE ou DELETE sont supprimées. La clause TOP réduit davantage le nombre de lignes jointes à la valeur spécifiée et les actions d’insertion, de mise à jour ou de suppression s’appliquent aux lignes jointes restantes de manière non ordonnée. Autrement dit, il n’existe aucun ordre dans lequel les lignes sont distribuées entre les actions définies dans les clauses WHEN. Par exemple, si la spécification de TOP (10) affecte 10 lignes, sept de ces lignes peuvent être mises à jour et trois insérées. Ou bien, un peut être supprimé, cinq mis à jour et quatre insérés, et ainsi de suite. Étant donné que l’instruction MERGE effectue une analyse complète de table des tables sources et cibles, les performances d’E/S peuvent être affectées lorsque vous utilisez la clause TOP pour modifier une table volumineuse en créant plusieurs lots. Dans ce scénario, il est important de s’assurer que tous les lots consécutifs ciblent les nouvelles lignes.

Soyez prudent lorsque vous spécifiez la clause TOP dans une requête qui contient un UNION, UNION ALL, EXCEPTou un opérateur INTERSECT. Il est possible d’écrire une requête qui retourne des résultats inattendus, car l’ordre dans lequel les clauses TOP et ORDER BY sont traitées logiquement n’est pas toujours intuitive lorsque ces opérateurs sont utilisés dans une opération de sélection. Par exemple, d'après le tableau et les données qui suivent, supposez que vous souhaitez renvoyer la voiture rouge la moins chère et la voiture bleue la moins chère. Autrement dit, la berline rouge et le fourgon bleu.

CREATE TABLE dbo.Cars
(
    Model VARCHAR (15),
    Price MONEY,
    Color VARCHAR (10)
);

INSERT dbo.Cars
VALUES ('sedan', 10000, 'red'),
    ('convertible', 15000, 'blue'),
    ('coupe', 20000, 'red'),
    ('van', 8000, 'blue');

Pour obtenir ces résultats, vous pouvez écrire la requête suivante.

SELECT TOP (1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'red'
UNION ALL
SELECT TOP (1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'blue'
ORDER BY Price ASC;
GO

Voici le jeu de résultats.

 Model         Color      Price
 ------------- ---------- -------
 sedan         red        10000.00
 convertible   blue       15000.00

Les résultats inattendus sont retournés, car la clause TOP s’exécute logiquement avant la clause ORDER BY, qui trie les résultats de l’opérateur (UNION ALL dans ce cas). Par conséquent, la requête précédente retourne toute voiture rouge et toute voiture bleue, puis classe le résultat de cette union en fonction du prix. L'exemple suivant affiche la méthode correcte de l'écriture de cette requête pour obtenir le résultat désiré.

SELECT Model, Color, Price
FROM (SELECT TOP (1) Model, Color, Price
      FROM dbo.Cars
      WHERE Color = 'red'
      ORDER BY Price ASC) AS a
UNION ALL
SELECT Model, Color, Price
FROM (SELECT TOP (1) Model, Color, Price
      FROM dbo.Cars
      WHERE Color = 'blue'
      ORDER BY Price ASC) AS b;
GO

En utilisant TOP et ORDER BY dans une opération de sous-sélection, vous vérifiez que les résultats de la clause ORDER BY sont appliqués à la clause TOP et non au tri du résultat de l’opération de UNION.

Voici le jeu de résultats.

 Model         Color      Price
 ------------- ---------- -------
 sedan         red        10000.00
 van           blue        8000.00

Limitations

Lorsque vous utilisez TOP avec INSERT, UPDATE, MERGEou DELETE, les lignes référencées ne sont pas organisées dans un ordre quelconque. Vous ne pouvez pas spécifier directement la clause ORDER BY dans ces instructions. Si vous devez utiliser TOP pour insérer, supprimer ou modifier des lignes dans un ordre chronologique significatif, utilisez TOP avec une clause ORDER BY spécifiée dans une instruction de sous-sélection. Consultez la section Exemples dans cet article.

Vous ne pouvez pas utiliser TOP dans UPDATE ou DELETE instructions sur les vues partitionnée.

Vous ne pouvez pas combiner TOP avec OFFSET et FETCH dans la même expression de requête (dans la même étendue de requête). Pour plus d’informations, consultez clause SELECT - ORDER BY.

Exemples

Les exemples de code Transact-SQL de cet article utilisent l’exemple de base de données AdventureWorks2022 ou AdventureWorksDW2022, que vous pouvez télécharger à partir de la page d’accueil Microsoft SQL Server Samples and Community Projects.

Category Éléments syntaxiques proposés
Syntaxe de base TOP * PERCENT
Y compris les valeurs de lien WITH TIES
Limitation des lignes affectées par DELETE, INSERT ou UPDATE DELETE, INSERT, UPDATE

Syntaxe de base

Les exemples de cette section illustrent les fonctionnalités de base de la clause ORDER BY à l’aide de la syntaxe minimale requise.

R. Utiliser TOP avec une valeur constante

Les exemples suivants utilisent une valeur constante pour spécifier le nombre d'employés retournés dans le jeu de résultats de la requête. Dans le premier exemple, les 10 premières lignes non définies sont retournées, car une clause ORDER BY n’est pas utilisée. Dans le deuxième exemple, une clause ORDER BY est utilisée pour renvoyer les 10 premiers employés récemment embauchés.

USE AdventureWorks2022;
GO

-- Select the first 10 random employees.
SELECT TOP (10) JobTitle, HireDate
FROM HumanResources.Employee;
GO

-- Select the first 10 employees hired most recently.
SELECT TOP (10) JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY HireDate DESC;
GO

B. Utiliser TOP avec une variable

L'exemple suivant utilise une variable pour spécifier le nombre d'employés retournés dans le jeu de résultats de la requête.

USE AdventureWorks2022;
GO

DECLARE @p AS INT = 10;

SELECT TOP (@p) JobTitle, HireDate, VacationHours
FROM HumanResources.Employee
ORDER BY VacationHours DESC;
GO

C. Spécifier un pourcentage

L’exemple suivant utilise PERCENT pour spécifier le nombre d’employés retournés dans le jeu de résultats de la requête. Il y a 290 employés dans la table HumanResources.Employee. Comme 5 pour cent de 290 est une valeur fractionnelle, la valeur est arrondie au nombre entier supérieur.

USE AdventureWorks2022;
GO

SELECT TOP (5) PERCENT JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY HireDate DESC;
GO

Inclure des valeurs de liaison

R. Utiliser WITH TIES pour inclure des lignes qui correspondent aux valeurs de la dernière ligne

L’exemple suivant fournit les 10 % des employés ayant le salaire le plus élevé et les retourne dans l’ordre décroissant de leur salaire. En spécifiant WITH TIES, vous incluez également dans le jeu de résultats les employés dont le salaire est égal au salaire le plus faible retourné (dernière ligne), même s’il dépasse 10 % des employés.

USE AdventureWorks2022;
GO

SELECT TOP (10) PERCENT WITH TIES pp.FirstName,
                                  pp.LastName,
                                  e.JobTitle,
                                  e.Gender,
                                  r.Rate
FROM Person.Person AS pp
     INNER JOIN HumanResources.Employee AS e
         ON pp.BusinessEntityID = e.BusinessEntityID
     INNER JOIN HumanResources.EmployeePayHistory AS r
         ON r.BusinessEntityID = e.BusinessEntityID
ORDER BY Rate DESC;
GO

Limiter les lignes affectées par DELETE, INSERT ou UPDATE

R. Utiliser TOP pour limiter le nombre de lignes supprimées

Lorsque vous utilisez une clause TOP (<n>) avec DELETE, l’opération de suppression est effectuée sur une sélection non définie de n nombre de lignes. Autrement dit, l’instruction DELETE choisit n’importe quel nombre de lignes (n) qui répondent aux critères définis dans la clause WHERE. L’exemple suivant supprime 20 lignes de la table PurchaseOrderDetail, dont la date d’échéance est antérieure au 1er juillet 2002.

USE AdventureWorks2022;
GO

DELETE TOP (20)
FROM Purchasing.PurchaseOrderDetail
WHERE DueDate < '20020701';
GO

Si vous souhaitez utiliser TOP pour supprimer des lignes dans un ordre chronologique significatif, utilisez TOP avec ORDER BY dans une instruction de sous-sélection. La requête suivante supprime les 10 lignes de la table PurchaseOrderDetail dont la date d'expiration est la plus proche. Pour garantir que seules 10 lignes sont supprimées, la colonne spécifiée dans l'instruction de sous-sélection (PurchaseOrderID) constitue la clé primaire de la table. L’utilisation d’une colonne non clé dans l’instruction de sous-sélection peut entraîner la suppression de plus de 10 lignes si la colonne spécifiée contient des valeurs en double.

USE AdventureWorks2022;
GO

DELETE Purchasing.PurchaseOrderDetail
WHERE PurchaseOrderDetailID IN (
    SELECT TOP 10 PurchaseOrderDetailID
    FROM Purchasing.PurchaseOrderDetail
    ORDER BY DueDate ASC
);
GO

B. Utiliser TOP pour limiter le nombre de lignes insérées

L’exemple suivant crée la table EmployeeSales et insère le nom et les ventes de l’année des 5 premiers employés de la table HumanResources.Employee. L’instruction INSERT choisit les cinq lignes retournées par l’instruction SELECT qui répondent aux critères définis dans la clause WHERE. La clause OUTPUT affiche les lignes insérées dans la table EmployeeSales. La clause ORDER BY de l’instruction SELECT n’est pas utilisée pour déterminer les cinq premiers employés.

USE AdventureWorks2022;
GO

IF OBJECT_ID('dbo.EmployeeSales', 'U') IS NOT NULL
    DROP TABLE dbo.EmployeeSales;
GO

CREATE TABLE dbo.EmployeeSales
(
    EmployeeID NVARCHAR (11) NOT NULL,
    LastName NVARCHAR (20) NOT NULL,
    FirstName NVARCHAR (20) NOT NULL,
    YearlySales MONEY NOT NULL
);
GO

INSERT TOP (5) INTO dbo.EmployeeSales
OUTPUT
    inserted.EmployeeID,
    inserted.FirstName,
    inserted.LastName,
    inserted.YearlySales
SELECT sp.BusinessEntityID,
       c.LastName,
       c.FirstName,
       sp.SalesYTD
FROM Sales.SalesPerson AS sp
     INNER JOIN Person.Person AS c
         ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.SalesYTD > 250000.00
ORDER BY sp.SalesYTD DESC;
GO

Si vous souhaitez utiliser TOP pour insérer des lignes dans un ordre chronologique significatif, utilisez TOP avec ORDER BY dans une instruction de sous-sélection. L’exemple suivant montre comment procéder. La clause OUTPUT affiche les lignes insérées dans la table EmployeeSales. Les cinq premiers employés sont désormais insérés en fonction des résultats de la clause ORDER BY au lieu de lignes non définies.

INSERT INTO dbo.EmployeeSales
OUTPUT
    inserted.EmployeeID,
    inserted.FirstName,
    inserted.LastName,
    inserted.YearlySales
SELECT TOP (5) sp.BusinessEntityID,
               c.LastName,
               c.FirstName,
               sp.SalesYTD
FROM Sales.SalesPerson AS sp
     INNER JOIN Person.Person AS c
         ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.SalesYTD > 250000.00
ORDER BY sp.SalesYTD DESC;
GO

C. Utiliser TOP pour limiter le nombre de lignes mises à jour

L’exemple suivant utilise la clause TOP pour mettre à jour les lignes d’une table. Lorsque vous utilisez une clause TOP (<n>) avec UPDATE, l’opération de mise à jour s’exécute sur un nombre non défini de lignes. Autrement dit, l’instruction UPDATE choisit n’importe quel nombre de lignes (n) qui répondent aux critères définis dans la clause WHERE. L'exemple suivant retire 10 clients à un vendeur et les attribue à un autre vendeur.

USE AdventureWorks2022;

UPDATE TOP (10)
Sales.Store
SET SalesPersonID = 276
WHERE SalesPersonID = 275;
GO

Si vous devez utiliser TOP pour appliquer des mises à jour dans une chronologie significative, vous devez utiliser TOP avec ORDER BY dans une instruction de sous-sélection. L'exemple ci-dessous met à jour les heures de congé des 10 employés dont la date d'embauche est la plus ancienne.

UPDATE HumanResources.Employee
SET VacationHours = VacationHours + 8
FROM (SELECT TOP 10 BusinessEntityID
      FROM HumanResources.Employee
      ORDER BY HireDate ASC) AS th
WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID;
GO

Exemples : Azure Synapse Analytics et Analytics Platform System (PDW)

L’exemple suivant retourne les 31 premières lignes qui correspondent aux critères de la requête. La clause ORDER BY garantit que les 31 lignes retournées sont les 31 premières lignes en fonction d’un ordre alphabétique de la colonne LastName.

Utilisation de TOP sans spécifier de liens.

SELECT TOP (31) FirstName, LastName
FROM DimEmployee
ORDER BY LastName;

Résultat : 31 lignes sont retournées.

À l’aide de TOP, en spécifiant WITH TIES.

SELECT TOP (31) WITH TIES FirstName, LastName
FROM DimEmployee
ORDER BY LastName;

Résultat : 33 lignes sont retournées, car trois employés nommés Brown lien pour la 31e ligne.