Je comprends qu'avant SQL Server 2005, vous pouviez "tromper" SQL Server pour permettre l'utilisation d'un ordre dans une définition de vue, en incluant également TOP 100 PERCENT
dans la clause SELECT. Mais j’ai vu un autre code dont j’ai hérité qui utilise SELECT TOP 100 PERCENT
... dans des instructions SQL dynamiques (utilisé dans ADO dans ASP.NET apps, etc.). Y a-t-il une raison quelconque pour cela? Le résultat n'est-il pas identique à not incluant le TOP 100 PERCENT
?
Il a été utilisé pour " matérialisation intermédiaire (recherche Google) "
Bon article: Adam Machanic: Exploration des secrets de la matérialisation intermédiaire
Il a même soulevé un MS Connect afin que cela puisse se faire de manière plus propre
Mon point de vue n'est "pas fondamentalement mauvais", mais ne l'utilisez pas à moins de 100%. Le problème est que cela ne fonctionne que lorsque vous le faites et probablement pas plus tard (niveau de patch, schéma, index, nombre de lignes, etc.).
Cela peut échouer car vous ne savez pas dans quel ordre les objets sont évalués
SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1 AND CAST(foo AS int) > 100
Et cela peut aussi échouer parce que
SELECT foo
FROM
(SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1) bar
WHERE
CAST(foo AS int) > 100
Toutefois, cela n'a pas été le cas dans SQL Server 2000. La requête interne est évaluée et mise en file d'attente:
SELECT foo
FROM
(SELECT TOP 100 PERCENT foo From MyTable WHERE ISNUMERIC (foo) = 1 ORDER BY foo) bar
WHERE
CAST(foo AS int) > 100
Notez que cela fonctionne toujours dans SQL Server 2005
SELECT TOP 2000000000 ... ORDER BY...
TOP (100) PERCENT n'a aucune signification dans les versions récentes de SQL Server et est ignoré par le processeur de requête (avec ORDER BY correspondant, dans le cas d'une définition de vue ou d'une table dérivée).
Vous avez raison, il était une fois, cela pouvait être utilisé comme une astuce, mais même alors, ce n'était pas fiable. Malheureusement, certains des outils graphiques de Microsoft ont mis cette clause dénuée de sens.
Quant à savoir pourquoi cela pourrait apparaître en SQL dynamique, je n'en ai aucune idée. Vous avez raison de dire qu'il n'y a pas de raison, et le résultat est le même sans elle (et encore, dans le cas d'une définition de vue ou d'une table dérivée, sans les clauses TOP et ORDER BY).
... autorise l'utilisation de ORDER BY dans une définition de vue.
Ce n'est pas une bonne idée. Une vue ne doit jamais avoir un ORDER BY défini.
Un ORDER BY a un impact sur les performances - son utilisation dans une vue signifie que ORDER BY apparaîtra dans le plan Expliquer. Si vous avez une requête dans laquelle la vue est jointe à quoi que ce soit dans la requête immédiate ou référencée dans une vue en ligne (CTE/factorisation de sous-requête), ORDER BY est toujours exécuté avant le dernier ORDER BY (en supposant qu'il ait été défini). Il n'y a aucun avantage à commander des lignes qui ne sont pas le résultat final lorsque la requête n'utilise pas TOP (ou LIMIT pour MySQL/Postgres).
Considérer:
CREATE VIEW my_view AS
SELECT i.item_id,
i.item_description,
it.item_type_description
FROM ITEMS i
JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
ORDER BY i.item_description
...
SELECT t.item_id,
t.item_description,
t.item_type_description
FROM my_view t
ORDER BY t.item_type_description
... équivaut à utiliser:
SELECT t.item_id,
t.item_description,
t.item_type_description
FROM (SELECT i.item_id,
i.item_description,
it.item_type_description
FROM ITEMS i
JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
ORDER BY i.item_description) t
ORDER BY t.item_type_description
C'est mauvais parce que:
ORDER BY item_type_description, item_description
S'il n'y a pas de clause ORDER BY
, alors TOP 100 PERCENT
est redondant. (Comme vous le mentionnez, c'était le "truc" avec des vues)
[Espérons que l'optimiseur optimisera cela.]
Aucune raison mais indifférence, je suppose.
De telles chaînes de requête sont généralement générées par un outil de requête graphique. L'utilisateur joint quelques tables, ajoute un filtre, un ordre de tri et teste les résultats. Étant donné que l'utilisateur peut vouloir enregistrer la requête sous forme de vue, l'outil ajoute un TOP 100 POUR CENT. Dans ce cas, cependant, l'utilisateur copie le code SQL dans son code, paramètre la clause WHERE et masque tout dans une couche d'accès aux données. Loin des yeux, loin des yeux.
J'ai vu un autre code dont j'ai hérité qui utilise SELECT TOP 100 PERCENT
La raison en est simple: Enterprise Manager essayait d’être utile et formaterait votre code pour l’inclure à votre place. Il était inutile d'essayer de l'enlever car cela ne faisait vraiment pas mal et la prochaine fois que vous alliez le changer, EM l'insérerait à nouveau.
Veuillez essayer ci-dessous, j'espère que cela fonctionnera pour vous.
SELECT TOP
( SELECT COUNT(foo)
From MyTable
WHERE ISNUMERIC (foo) = 1) *
FROM bar WITH(NOLOCK)
ORDER BY foo
WHERE CAST(foo AS int) > 100
)
L'erreur dit tout ...
Msg 1033, Niveau 15, Etat 1, Procédure TestView, Ligne 5 La clause ORDER BY n'est pas valide dans les vues, les fonctions en ligne, les tables dérivées, les sous-requêtes et les expressions de table communes, sauf si TOP, OFFSET ou FOR XML est également spécifié.
N'utilisez pas TOP 100 PERCENT
, utilisez TOP n
, où N est un nombre
Le TOP 100 POUR CENT (pour des raisons que je ne connais pas) est ignoré par SQL Server VIEW (versions post-2012), mais je pense que MS l'a conservé pour des raisons de syntaxe. TOP n est préférable. Elle fonctionne dans une vue et la trie comme vous le souhaitez lorsqu’une vue est utilisée au départ, mais soyez prudent .
Essayez ceci, cela s’explique presque tout seul. Vous ne pouvez pas créer une vue avec ORDER BY sauf si ...
CREATE VIEW v_Test
AS
SELECT name
FROM sysobjects
ORDER BY name
GO
Msg 1033, Niveau 15, Etat 1, Procédure TestView, Ligne 5 La commande ORDER BY La clause n'est pas valide dans les vues, les fonctions en ligne, les tables dérivées, sous-requêtes et expressions de table communes, sauf TOP, OFFSET ou FOR XML est également spécifié.
Je suppose que vous pouvez utiliser une variable dans le résultat, mais mis à part obtenir la pièce ORDER BY dans une vue, vous ne verrez aucun avantage en indiquant implicitement "TOP 100 POUR CENT":
declare @t int
set @t=100
select top (@t) percent * from tableOf