Nous recevons une liste de commandes, et nous validons quelle commence par certains préfixes, par exemple si OrderNumber ne commence pas par ABC, puis saffiche commander la liste à lutilisateur comme erreur. Nous utilisons existe, pour rechercher la première existence, ne voulons pas consommer beaucoup de temps de performance. Sil ny en a pas, alors nous pouvons commencer à mener une autre tâche dans le code.
Y a-t-il de toute façon dans sql pour se débarrasser de le code répétitif? Nous avons de nombreux contrôles comme celui-ci sur plusieurs tables, essayant de rendre le code plus efficace.
if exists ( select * from dbo.OrdersImport where left(OrderNumber,3) <> "ABC" ) begin select OrderNumber as OrderErrorList from dbo.OrdersImport where left(OrderNumber,3) <> "ABC" end else
Réponse
Malheureusement, jai peur en essayant déviter de répéter du code, vous pourriez finir par écrire plus de code et rendre la requête moins lisible. Mais je pense que cela peut être avantageux pour vous – prenez en compte les situations où, dans le test, vous nauriez quà rechercher dans une ou deux tables, où pour récupérer tous les détails, vous devrez en joindre plusieurs autres. Dans ces situations, vous pouvez simplifier la requête de test, ce qui la rend également plus rapide à exécuter.
Et pendant que nous y sommes, vous pouvez également envisager de changer votre instruction WHERE. Lutilisation de fonctions dans le prédicat les rend non SARGables et empêche lutilisation dindex dans ces cas. Une meilleure approche dans cet exemple serait de vérifier
WHERE OrderNumber LIKE "ABC%"
car loptimiseur effectuera une conversion en quelque chose du type
OrderNumber >= "ABC" AND OrderNumber < "ABD"
qui prend en charge lutilisation dindex. Il s’agirait donc d’une recherche d’index (en utilisant left ()) ou d’une recherche d’index (en utilisant LIKE).
Réponse
Malheureusement, pour une variété de raisons (pas seulement héritées) SQL na pas presque toutes les options et fonctionnalités de réutilisation du code que la plupart des langages client ont et certains dentre eux (comme les UDF scalaires) ont des problèmes importants. Donc, dans une large mesure, si vous voulez être un programmeur SQL efficace, vous devez vous résigner à faire beaucoup plus de réutilisation de code couper-coller que vous ne le pensez jamais dans un langage client comme C #, VB. Net ou Java.
Cela dit, vous pouvez éliminer la redondance dans votre exemple, cependant, que ce soit réellement meilleur ou non, vous « devrez décider.
Declare @OrderErrorList Table(OrderNumber varchar(32)); Insert into @OrderErrorList select OrderNumber as OrderErrorList from dbo.OrdersImport where left(OrderNumber,3) <> "ABC"; if exists ( select * from @OrderErrorList ) begin select * from @OrderErrorList end else
Commentaires
- Pourriez-vous simplifier cela davantage en vérifiant le @@ ROWCOUNT au lieu dexister?
- @mathewb Oui, mais cela doit être fait immédiatement après INSERT..SELECT. Si vous ajoutez une autre déclaration, cela cesse soudainement de fonctionner correctement et jessaie déviter les mines terrestres comme ça dans mes réponses. La solution de contournement serait denregistrer le @@ ROWCOUNT dans une variable, mais ce ne serait pas beaucoup mieux que ce que jai ci-dessus.
Réponse
Y a-t-il de toute façon en sql pour se débarrasser du code répétitif?
Pas vraiment, non. Vous pouvez reformuler la requête comme ceci, sans linstruction IF, mais ce nest pas vraiment différent de ce que vous avez:
SELECT * FROM dbo.OrdersImport o WHERE LEFT(OrderNumber, 3) <> "ABC" AND EXISTS ( SELECT * FROM dbo.OrdersImport WHERE LEFT(OrderNumber,3) <> "ABC" AND ID = o.ID )