Travailler avec des procédures stockées

Les procédures stockées permettent aux utilisateurs de créer du code modulaire pouvant inclure une logique métier complexe en combinant plusieurs instructions SQL avec une logique procédurale.

Dans ce chapitre :

Création d’une procédure stockée

DDL de procédure stockée

Les procédures stockées sont des objets de base de données de première classe. Les commandes DDL suivantes s’appliquent aux procédures stockées :

En outre, Snowflake fournit la commande suivante pour exécuter des procédures stockées :

Conventions de dénomination pour les procédures stockées

Les procédures stockées sont des objets de base de données, c’est-à-dire qu’ils sont créés dans une base de données et un schéma spécifiés. À ce titre, ils ont un nom complet défini par leur espace de noms, sous la forme bd.schéma.nom_procédure, par exemple :

CALL temporary_db_qualified_names_test.temporary_schema_1.stproc_pi();

Lorsqu’elles sont appelées sans leur nom complet, les procédures stockées sont résolues en fonction de la base de données et du schéma utilisés pour la session.

Surcharge de noms

Snowflake prend en charge la surcharge des noms de procédure stockée. Plusieurs procédures stockées dans le même schéma peuvent porter le même nom, tant que leurs signatures diffèrent, soit par le nombre d’arguments soit par leur type. Lorsqu’une procédure stockée surchargée est appelée, Snowflake vérifie les arguments et appelle la procédure stockée correcte.

Un exemple est inclus dans Surcharge de noms de procédures stockées.

Soyez prudent lorsque vous utilisez la surcharge. La combinaison de la conversion de type automatique et de la surcharge peut favoriser la situation dans laquelle des erreurs utilisateurs mineures provoqueraient des résultats inattendus. Pour un exemple, voir Surcharge de noms de procédures stockées.

Conflits potentiels avec les fonctions définies par le système et les fonctions définies par l’utilisateur

Les procédures stockées et les fonctions définies par l’utilisateur peuvent porter les mêmes noms si leurs nombres d’arguments ou types de données d’arguments sont différents.

Cependant, Snowflake ne permet pas de créer des procédures stockées avec le même nom que les fonctions définies par le système.

Gestion des transactions

Les procédures stockées ne sont pas atomiques ; si une instruction d’une procédure stockée échoue, les autres instructions de la procédure stockée ne sont pas nécessairement annulées.

Vous pouvez utiliser des procédures stockées avec des transactions pour rendre un groupe d’instructions atomique. Pour plus de détails, voir Procédures et transactions stockées.

Conseils généraux

Code symétrique

Si vous maîtrisez la programmation en langage assembleur, l’analogie suivante peut vous être utile. En langage assembleur, les fonctions créent et annulent souvent leurs environnements de manière symétrique. Par exemple :

-- Set up.
push a;
push b;
...
-- Clean up in the reverse order that you set up.
pop b;
pop a;

Vous voudrez peut-être utiliser cette approche dans vos procédures stockées :

  • Si une procédure stockée apporte des modifications temporaires à votre session, alors cette procédure doit annuler ces modifications avant de les renvoyer.

  • Si une procédure stockée utilise la gestion des exceptions ou la création de branches, ou une autre logique pouvant avoir une incidence sur les instructions exécutées, vous devez nettoyer ce que vous avez créé, quelles que soient les branches que vous prenez lors d’un appel particulier.

Par exemple, votre code pourrait ressembler au pseudo-code présenté ci-dessous :

create procedure f() ...
    $$
    set x;
    set y;
    try  {
       set z;
       -- Do something interesting...
       ...
       unset z;
       }
    catch  {
       -- Give error message...
       ...
       unset z;
       }
    unset y;
    unset x;
    $$
    ;

Appel d’une procédure stockée

Pour exécuter une procédure stockée, utilisez une instruction CALL. Par exemple :

call stproc1(5.14::FLOAT);

Chaque argument d’une procédure stockée peut être une expression générale :

CALL stproc1(2 * 5.14::FLOAT);

Un argument peut être une sous-requête :

CALL stproc1(SELECT COUNT(*) FROM stproc_test_table1);

Vous ne pouvez appeler qu’une procédure stockée par instruction CALL. Par exemple, l’instruction suivante échoue :

call proc1(1), proc2(2);                          -- Not allowed

En outre, vous ne pouvez pas utiliser une procédure stockée CALL dans le cadre d’une expression. Par exemple, toutes les instructions suivantes échouent :

call proc1(1) + proc1(2);                         -- Not allowed
call proc1(1) + 1;                                -- Not allowed
call proc1(proc2(x));                             -- Not allowed
select * from (call proc1(1));                    -- Not allowed

Toutefois, dans une procédure stockée, la procédure stockée peut appeler une autre procédure stockée ou s’appeler elle-même de manière récursive.

Prudence

Les appels imbriqués peuvent dépasser la profondeur de pile maximale autorisée. Soyez donc prudent lors de l’imbrication des appels, en particulier lors de l’utilisation de la récursivité.

Privilèges

Les procédures stockées utilisent deux types de privilèges :

  • Privilèges directement sur la procédure stockée elle-même.

  • Privilèges sur les objets de base de données (par exemple, les tables) auxquels la procédure stockée accède.

Privilèges sur les procédures stockées

Semblables à d’autres objets de base de données (tables, vues, UDFs, etc.), les procédures stockées appartiennent à un rôle et disposent de privilèges pouvant être accordés à d’autres rôles.

Actuellement, les privilèges suivants s’appliquent aux procédures stockées :

  • USAGE

  • OWNERSHIP

Pour qu’un rôle utilise une procédure stockée, le rôle doit être le propriétaire ou avoir obtenu le privilège USAGE sur la procédure stockée.

Privilèges sur les objets de base de données accessibles par la procédure stockée

Ce sujet est traité dans Présentation des procédures stockées des droits de l’appelant et des droits du propriétaire.

Considérations relatives aux procédures stockées

  • Bien que les procédures stockées autorisent l’imbrication et la récursivité, la profondeur maximale actuelle de la pile d’appels imbriqués pour les procédures stockées définies par l’utilisateur est de 5 (y compris la procédure stockée de premier niveau) et peut être inférieure si des procédures stockées individuelles dans la chaîne d’appels consomment de grandes quantités de ressources.

  • Dans de rares cas, appeler trop de procédures stockées en même temps peut provoquer un blocage.

Injection SQL

Les procédures stockées peuvent créer dynamiquement une instruction SQL et l’exécuter. Toutefois, cela peut permettre des attaques par injection SQL, en particulier si vous créez l’instruction SQL à l’aide d’une entrée provenant d’une source publique ou non approuvée.

Vous pouvez minimiser le risque d’attaques par injection SQL en liant des paramètres plutôt qu’en concaténant du texte. Pour un exemple de liaison de variables, voir Variables de liaison.

Si vous choisissez d’utiliser la concaténation, vérifiez soigneusement les entrées lors de la construction dynamique de SQL à l’aide des entrées de sources publiques. Vous pouvez également prendre d’autres précautions, telles que l’interrogation à l’aide d’un rôle disposant de privilèges limités (par exemple, un accès en lecture seule ou un accès uniquement à certaines tables ou vues).

Pour plus d’informations sur les attaques par injection SQL, voir Injection SQL (sur Wikipédia).

Conseils de conception pour les procédures stockées

Voici quelques conseils pour concevoir une procédure stockée :

  • De quelles ressources (par exemple, les tables) cette procédure stockée a-t-elle besoin ?

  • Quels sont les privilèges nécessaires ?

    Réfléchissez aux objets de base de données auxquels vous aurez accès, aux rôles qui exécuteront votre procédure stockée et aux privilèges dont ces rôles auront besoin.

    Si la procédure doit être une procédure stockée avec droits de l’appelant, vous pouvez créer un rôle pour exécuter cette procédure spécifique ou l’une des procédures associées à un groupe. Vous pouvez ensuite accorder les privilèges requis à ce rôle, puis attribuer ce rôle aux utilisateurs appropriés.

  • La procédure stockée doit-elle être exécutée avec les droits de l’appelant ou les droits du propriétaire ? Pour plus d’informations sur ce sujet, voir Présentation des procédures stockées des droits de l’appelant et des droits du propriétaire .

  • Comment la procédure doit-elle gérer les erreurs, par exemple, que doit faire la procédure si une table requise est manquante ou si un argument n’est pas valide ?

  • La procédure stockée doit-elle consigner ses activités ou ses erreurs, par exemple en écrivant dans une table de journaux ?

  • Voir également la discussion pour savoir quand utiliser une procédure stockée et quand utiliser une UDF : Choisir de créer une procédure stockée ou une UDF.

Documentation des procédures stockées

Les procédures stockées sont généralement écrites pour être réutilisées et souvent partagées. La documentation des procédures stockées peut faciliter la gestion et l’utilisation des procédures stockées.

Vous trouverez ci-dessous des recommandations générales sur la documentation des procédures stockées.

En règle générale, au moins deux publics souhaitent avoir des informations sur une procédure stockée :

  • Utilisateurs/appelants.

  • Programmeurs/auteurs.

Pour les utilisateurs (et les programmeurs), documentez chacun des éléments suivants :

  • Nom de la procédure stockée

  • « Emplacement » de la procédure stockée (base de données et schéma).

  • Objectif de la procédure stockée.

  • Nom, type de données et signification de chaque paramètre d’entrée.

  • Nom, type de données et signification de la valeur de retour. Si la valeur de retour est un type complexe, tel qu’un VARIANT contenant des sous-champs, documentez ces sous-champs.

  • Si la procédure stockée s’appuie sur des informations issues de son environnement, par exemple des variables de session ou des paramètres de session, documentez les noms, les objectifs et les valeurs valides de ceux-ci.

  • Erreurs renvoyées, exceptions levées, etc.

  • Rôles ou privilèges requis pour exécuter la procédure. (Pour plus d’informations à ce sujet, voir la discussion sur les rôles dans Conseils de conception pour les procédures stockées.)

  • Si la procédure stockée est une procédure de droits d’appelant ou une procédure de droits de propriétaire.

  • Toutes les conditions préalables, par exemple les tables qui doivent exister avant l’appel de la procédure.

  • Toutes les sorties (en dehors de la valeur de retour), par exemple les nouvelles tables créées.

  • Tous les « effets de bord », par exemple les modifications de privilèges, la suppression d’anciennes données, etc. La plupart des procédures stockées (contrairement aux fonctions) sont appelées spécifiquement pour leurs effets de bord, et non pour leurs valeurs de retour. Assurez-vous donc de documenter ces effets.

  • Si un nettoyage est requis après l’exécution de la procédure stockée, documentez-le.

  • Si la procédure peut être appelée dans le cadre d’une transaction comportant plusieurs instructions (avec AUTOCOMMIT=FALSE) ou si elle doit être exécutée en dehors d’une transaction (avec AUTOCOMMIT=TRUE).

  • Un exemple d’appel et un exemple de ce qui est retourné.

  • Limitations (le cas échéant). Par exemple, supposons que la procédure lise une table et renvoie un VARIANT contenant des informations sur chaque ligne de la table. Il est possible que le VARIANT dépasse la taille maximale autorisée d’un VARIANT. Vous devrez donc peut-être donner à l’appelant une idée du nombre maximal de lignes de la table auxquelles la procédure accède.

  • Avertissements (le cas échéant).

  • Astuces de dépannage.

Pour les programmeurs :

  • Le ou les auteurs.

  • Expliquez pourquoi la procédure a été créée en tant que procédure de droits de l’appelant ou de droits du propriétaire. La raison peut ne pas être évidente.

  • Les procédures stockées peuvent être imbriquées, mais il existe une limite à la profondeur d’imbrication. Si votre procédure stockée appelle d’autres procédures stockées et qu’elle est susceptible d’être appelée par d’autres procédures stockées, vous pouvez spécifier la profondeur maximale connue de la pile d’appels de votre procédure stockée, afin que les appelants sachent si l’appel de votre procédure stockée peut dépasser la profondeur maximale de la pile d’appels.

  • Astuces de débogage.

L’emplacement et le format de ces informations dépendent de vous. Vous pouvez par exemple stocker les informations au format HTML sur un site Web interne. Avant de décider du lieu de stockage, pensez au lieu où votre entreprise stocke des informations similaires pour d’autres produits ou des informations similaires pour d’autres fonctionnalités Snowflake, telles que les vues, les fonctions définies par l’utilisateur, etc.

Autres astuces :

  • Incluez des commentaires dans le code source, comme vous devriez le faire pour presque tout élément de code source.

    • Rappelez-vous que la rétroingénierie du code est difficile. Décrivez non seulement le fonctionnement de votre algorithme, mais également son objectif.

  • Les procédures stockées autorisent un COMMENT (commentaire) facultatif pouvant être spécifié avec l’instruction CREATE PROCEDURE ou ALTER PROCEDURE. D’autres personnes peuvent lire ce commentaire en exécutant la commande SHOW PROCEDURES.

  • Si possible, pensez à conserver une copie maîtresse de la commande CREATE PROCEDURE de chaque procédure stockée dans un système de contrôle de code source. La fonctionnalité Time Travel de Snowflake ne s’applique pas aux procédures stockées ; par conséquent. La recherche d’anciennes versions de procédures stockées doit donc être effectuée en dehors de Snowflake. Si aucun système de contrôle de code source n’est disponible, vous pouvez en simuler partiellement un en stockant les commandes CREATE PROCEDURE dans un champ VARCHAR d’une table et en ajoutant chaque nouvelle version (sans remplacer les versions précédentes).

  • Pensez à utiliser une convention de dénomination pour fournir des informations sur les procédures stockées. Par exemple, un préfixe ou un suffixe dans le nom peut indiquer si la procédure est une procédure stockée avec droits de l’appelant ou une procédure stockée avec droits du propriétaire. (Par exemple, vous pouvez utiliser cr_ comme préfixe pour les droits de l’appelant.)

  • Pour voir les types de données et l’ordre des arguments d’entrée, ainsi que le commentaire, vous pouvez utiliser la commande SHOW PROCEDURES. Rappelez-vous cependant que cela ne montre que les noms et les types de données des arguments. Cela n’explique pas les arguments.

  • Si vous avez les privilèges appropriés, vous pouvez utiliser la commande DESCRIBE PROCEDURE pour voir :

    • Les noms et types de données des arguments.

    • Le corps de la procédure et si la procédure est exécutée en tant que propriétaire ou appelant.

    • Le type de données de la valeur renvoyée.

    • Autres informations utiles.

Revenir au début