Disons que je dois implémenter un morceau de code T-SQL qui doit renvoyer une table en résultat. Je peux implémenter une fonction table ou bien une procédure stockée qui renvoie un ensemble de lignes. Que dois-je utiliser?
En bref, ce que je veux savoir, c'est:
Quelles sont les principales différences entre les fonctions et les procédures stockées? Quelles considérations dois-je prendre en compte pour utiliser l'un ou l'autre?
Réponses:
Si vous êtes susceptible de vouloir combiner le résultat de ce morceau de code avec d'autres tables, alors évidemment une fonction table vous permettra de composer les résultats dans une seule instruction SELECT.
Généralement, il existe une hiérarchie (Affichage <Fonction TV <Proc stocké). Vous pouvez en faire plus dans chacun d'eux, mais la capacité à composer les sorties et à permettre à l'optimiseur de s'impliquer vraiment diminue à mesure que la fonctionnalité augmente.
Utilisez donc celui qui vous permet au minimum d'exprimer le résultat souhaité.
la source
Les fonctions doivent être déterministes et ne peuvent pas être utilisées pour apporter des modifications à la base de données, alors que les procédures stockées vous permettent de faire des insertions et des mises à jour, etc.
Vous devez limiter votre utilisation des fonctions, car elles posent un énorme problème d'évolutivité pour les requêtes volumineuses et complexes. Ils deviennent une sorte de "boîte noire" pour l'optimiseur de requêtes, et vous verrez d'énormes différences de performances entre l'utilisation de fonctions et l'insertion simple du code dans une requête.
Mais ils sont certainement utiles pour les retours table dans des cas très spécifiques.
Si vous avez besoin d'analyser une liste délimitée par des virgules, pour simuler le passage d'un tableau à une procédure, une fonction peut transformer la liste en table pour vous. C'est une pratique courante avec Sql Server 2005, car nous ne pouvons pas encore passer de tables à des procédures stockées (nous le pouvons avec 2008).
la source
À partir de la documentation :
la source
Je vais écrire quelques différences intéressantes entre les procédures stockées et les fonctions.
Nous ne pouvons pas utiliser de fonctions non déterministes dans Functions mais nous pouvons utiliser des fonctions non déterministes dans les procédures stockées. Maintenant, la question se pose, quelle est la fonction non déterministe. La réponse est: -
Exception:-
Nous pouvons utiliser des instructions DML (insérer, mettre à jour, supprimer) dans une procédure stockée, mais nous ne pouvons pas utiliser d'instructions DML dans des fonctions sur des tables physiques ou des tables permanentes. Si nous voulons faire une opération DML dans des fonctions, nous pouvons le faire sur des variables de table et non sur des tables permanentes.
Nous ne pouvons pas utiliser la gestion des erreurs dans la fonction, mais nous pouvons effectuer la gestion des erreurs dans les procédures stockées.
la source
La procédure peut renvoyer zéro ou n valeurs alors que la fonction peut renvoyer une valeur qui est obligatoire.
Les procédures peuvent avoir des paramètres d'entrée / sortie alors que les fonctions ne peuvent avoir que des paramètres d'entrée.
La procédure permet de sélectionner ainsi que les instructions DML, tandis que la fonction ne permet que les instructions de sélection.
Les fonctions peuvent être appelées à partir d'une procédure alors que les procédures ne peuvent pas être appelées à partir d'une fonction.
L'exception peut être gérée par le bloc try-catch dans une procédure alors que le bloc try-catch ne peut pas être utilisé dans une fonction.
On peut opter pour la gestion des transactions en procédure alors qu'on ne peut pas aller en fonction.
Les procédures ne peuvent pas être utilisées dans une instruction select, tandis que la fonction peut être incorporée dans une instruction select.
UDF (fonction définie par l'utilisateur) peut être utilisée dans les instructions SQL n'importe où dans la section
WHERE
/HAVING
/SELECT
, contrairement aux procédures stockées.Les UDF qui renvoient des tables peuvent être traitées comme un autre ensemble de lignes. Cela peut être utilisé dans
JOIN
s avec d'autres tables.Les fonctions UDF en ligne peuvent être considérées comme des vues qui prennent des paramètres et peuvent être utilisées dans les opérations de
JOIN
s et d'autres ensembles de lignes.la source
Si vous avez une fonction, vous pouvez l'utiliser dans le cadre de votre instruction SQL, par exemple
Cela ne fonctionne pas de cette façon pour les procédures stockées.
la source
J'ai exécuté quelques tests avec un long bit de logique, avec le même bit de code (une longue instruction SELECT) fonctionnant à la fois dans une fonction de table et une procédure stockée, et un EXEC / SELECT simple, et chacun exécuté de manière identique.
À mon avis, utilisez toujours une fonction à valeur de table plutôt qu'une procédure stockée pour renvoyer un jeu de résultats, car cela rend la logique beaucoup plus facile et lisible dans les requêtes qui les rejoignent par la suite, et vous permet de réutiliser la même logique. Pour éviter trop de problèmes de performance, j'utilise souvent des paramètres "optionnels" (c'est-à-dire que vous pouvez leur passer NULL) pour permettre à la fonction de renvoyer le jeu de résultats plus rapidement, par exemple:
De cette façon, vous pouvez utiliser cette fonction dans de nombreuses situations différentes, et ne prenez pas un énorme impact sur les performances. Je pense que c'est plus efficace que de filtrer après:
J'ai utilisé cette technique dans plusieurs fonctions, parfois avec une longue liste de paramètres "optionnels" de ce type.
la source
Personnellement, j'utilise des fonctions de table lorsque tout ce que je retourne est une seule table sans effet. En gros, je les traite comme des vues paramétrées.
Si j'ai besoin de renvoyer plusieurs jeux d'enregistrements ou s'il y aura des valeurs mises à jour dans les tables, j'utilise une procédure stockée.
Mes 2 cents
la source
Comme mentionné ci-dessus, les fonctions sont plus lisibles / composables / auto-documentées, mais sont moins performantes en général, et peuvent être sérieusement moins performantes si vous vous laissez emporter par elles dans des jointures telles que
Souvent, il suffit d'accepter la redondance de code qu'un tvf pourrait éliminer (à un coût de performance inacceptable).
Un autre point que je n'ai pas encore vu mentionné est que vous ne pouvez pas utiliser de tables temporaires de changement d'état de base de données à l'intérieur d'un tvf multi-instruction. Le mécanisme le plus fonctionnellement équivalent à une table temporaire est le changement non d'état, dans la variable de table mémoire, et pour les grands ensembles de données, une table temporaire sera probablement plus performante qu'une variable de table. (D'autres alternatives incluent les tables dynamiques et les expressions communes à valeur de table, mais à un certain niveau de complexité, celles-ci cessent d'être une bonne option IMO.)
la source
Je testerais les deux performances. Il est probable que l'approche sp ou une table dérivée serait beaucoup plus rapide qu'une fonction et si c'est le cas, cette approche devrait être utilisée. En général, j'évite les fonctions car elles peuvent être des porcs de performance.
la source
Cela dépend :) Si vous souhaitez utiliser le résultat table dans une autre procédure, il vaut mieux utiliser une fonction TableValued. Si les résultats sont pour un client, la procédure stockée est généralement la meilleure solution.
la source
Les procédures stockées sont des requêtes pré-compilées qui s'exécutent plus rapidement et enregistrent des injections SQL. Ils peuvent renvoyer des valeurs 0 ou N. Nous pouvons effectuer des opérations DML à l'intérieur des procédures stockées. Nous pouvons utiliser des fonctions à l'intérieur des procédures et utiliser des fonctions dans la requête de sélection. Les fonctions sont utilisées pour renvoyer n'importe quelle valeur et les opérations DML ne sont pas possibles dans les fonctions. les fonctions sont de deux types scalaires et table. La fonction scalaire renvoie une valeur unique, une fonction table utilisée pour renvoyer des lignes de tables.
la source