web-dev-qa-db-fra.com

Fonctions vs procédures stockées

Disons que je dois implémenter un morceau de code T-SQL qui doit renvoyer une table comme résultat. Je peux implémenter une fonction table ou bien une procédure stockée qui retourne un ensemble de lignes. Que dois-je utiliser?

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'une ou l'autre?

86
Auron

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 (View <TV Function <Stored Proc). Vous pouvez faire plus dans chacun, mais la capacité à composer les sorties et à l'optimiseur de s'impliquer vraiment diminue à mesure que la fonctionnalité augmente.

Utilisez donc celui qui vous permet au moins d'exprimer le résultat souhaité.

50

Les fonctions doivent être déterministes et ne peuvent pas être utilisées pour apporter des modifications à la base de données, tandis 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ête, 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 rendements de table dans des cas très spécifiques.

Si vous devez 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 transmettre de tables aux procédures stockées (nous pouvons le faire avec 2008).

49
Eric Z Beard

À partir des documents :

Si une procédure stockée répond aux critères suivants, elle est un bon candidat pour être réécrite en tant que fonction table:

  • La logique est exprimable dans une seule instruction SELECT mais est une procédure stockée, plutôt qu'une vue, uniquement en raison de la nécessité de paramètres.

  • La procédure stockée n'effectue pas d'opérations de mise à jour, sauf pour les variables de table.

  • Il n'y a pas besoin d'instructions dynamiques EXECUTE.

  • La procédure stockée renvoie un jeu de résultats.

  • Le but principal de la procédure stockée est de générer des résultats intermédiaires qui doivent être chargés dans une table temporaire, qui est ensuite interrogée dans une instruction SELECT.

43

Je vais écrire quelques différences intéressantes entre les procédures stockées et les fonctions.

  • Nous pouvons utiliser des fonctions dans certaines requêtes, mais nous ne pouvons pas utiliser des procédures stockées dans des requêtes sélectionnées.
  • Nous ne pouvons pas utiliser de fonctions non déterministes dans les fonctions, 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 .. Ans est: -

    Une fonction non déterministe est cette fonction qui renvoie différentes sorties pour les mêmes valeurs d'entrée à différents moments, comme getdate (). Il renvoie toujours une valeur différente chaque fois qu'il est exécuté.

    Exception:-

    Les versions antérieures de SQL Server avant SQL 2000 ne permettent pas d'utiliser la fonction getdate () dans les fonctions définies par l'utilisateur, mais la version 2005 et les versions ultérieures nous permettent d'utiliser la fonction getdate () dans une fonction définie par l'utilisateur.

    Newid () est un autre exemple de fonction non déterministe mais ne peut pas être utilisé dans des fonctions définies par l'utilisateur mais nous pouvons l'utiliser dans une procédure stockée.

  • Nous pouvons utiliser des instructions DML (insérer, mettre à jour, supprimer) dans une procédure stockée, mais nous ne pouvons pas utiliser des instructions DML dans des fonctions sur des tables physiques ou des tables permanentes. Si nous voulons faire une opération DML dans les 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 faire la gestion des erreurs dans les procédures stockées.

12
Neeraj Kumar Yadav
  1. La procédure peut retourner zéro ou n valeurs tandis que la fonction peut retourner une valeur qui est obligatoire.

  2. 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.

  3. La procédure autorise les instructions select et DML, tandis que la fonction autorise uniquement les instructions select.

  4. Les fonctions peuvent être appelées depuis la procédure alors que les procédures ne peuvent pas être appelées depuis la fonction.

  5. 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.

  6. On peut opter pour la gestion des transactions en procédure alors qu'on ne peut pas aller en fonction.

  7. 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.

  8. UDF (fonction définie par l'utilisateur) peut être utilisée dans les instructions SQL n'importe où dans la section WHERE/HAVING/SELECT alors que les procédures stockées ne le peuvent pas.

  9. Les FDU qui renvoient des tables peuvent être traitées comme un autre ensemble de lignes. Cela peut être utilisé dans JOINs avec d'autres tables.

  10. Les FDU en ligne peuvent être considérées comme des vues qui prennent des paramètres et peuvent être utilisées dans JOINs et d'autres opérations d'ensemble de lignes.

8
nathan1138

Si vous avez une fonction, vous pouvez l'utiliser dans le cadre de votre instruction SQL, par exemple

SELECT function_name(field1) FROM table

Cela ne fonctionne pas de cette façon pour les procédures stockées.

6
Ilya Kochetov

J'ai exécuté des tests avec un peu de logique longue, avec le même bit de code (une longue instruction SELECT) s'exécutant à la fois dans une fonction de valeur de table et une procédure stockée, et un EXEC/SELECT direct, et chacun exécuté de manière identique.

À mon avis, utilisez toujours une fonction de valeur de table plutôt qu'une procédure stockée pour renvoyer un ensemble 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 un trop grand impact sur les performances, j'utilise souvent des paramètres "facultatifs" (c'est-à-dire que vous pouvez leur passer NULL) pour permettre à la fonction de renvoyer l'ensemble de résultats plus rapidement, par exemple:

CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int)
AS
RETURN 
    SELECT DISTINCT SiteID, PersonID
    FROM dbo.SiteViewPermissions
    WHERE (@optPersonID IS NULL OR @optPersonID = PersonID)
    AND (@optSiteID IS NULL OR @optSiteID = SiteID)
    AND @RegionID = RegionID

De cette façon, vous pouvez utiliser cette fonction pour de nombreuses situations différentes, et ne prenez pas un énorme coup de performance. Je pense que c'est plus efficace que le filtrage ultérieur:

SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1

J'ai utilisé cette technique dans plusieurs fonctions, parfois avec une longue liste de paramètres "optionnels" de ce type.

5
Paul Grimshaw

Comme mentionné ci-dessus, les fonctions sont plus lisibles/composables/auto-documentées, mais sont moins performantes en général, et peuvent être considérablement moins performantes si vous vous laissez emporter par elles dans des jointures telles que

SELECT *
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2
    ON (tvf1.JoinId = tvf2.JoinId)

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-instructions. Le mécanisme le plus fonctionnellement équivalent à une table temporaire est la variable sans é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 de valeur de table communes, mais à un certain niveau de complexité, celles-ci cessent d'être une bonne option OMI.)

4
6eorge Jetson

Personnellement, j'utilise des fonctions de valeur de table lorsque tout ce que je retourne est une seule table sans effets. Fondamentalement, je les traite comme des vues paramétrées.

Si j'ai besoin de plusieurs jeux d'enregistrements retournés ou s'il y aura des valeurs mises à jour dans les tables, j'utilise une procédure stockée.

Mes 2 cents

4
wcm

Je testerais les deux à la fois. Il est probable que l'approche sp ou une table dérivée soit significativement 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.

1
HLGEM

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, le proc stocké est généralement la meilleure façon de procéder.

1
edosoft