Oracle
 sql >> Base de données >  >> RDS >> Oracle

Pourquoi la sélection à partir d'une procédure stockée n'est-elle pas prise en charge dans les bases de données relationnelles ?

TL;DR :vous pouvez sélectionnez à partir de fonctions (tables) ou à partir de n'importe quel type de fonction dans PostgreSQL. Mais pas à partir de procédures stockées.

Voici une explication « intuitive », quelque peu indépendante de la base de données, car je pense que SQL et ses nombreux dialectes sont trop un langage / un concept développé de manière organique pour qu'il y ait une explication fondamentale et « scientifique » à cela.

Procédures vs Fonctions, historiquement

Je ne vois pas vraiment l'intérêt de choisir parmi les procédures stockées, mais je suis biaisé par des années d'expérience et j'accepte le statu quo, et je vois certainement comment la distinction entre les procédures et fonctions peut être déroutant et comment on souhaiterait qu'ils soient plus polyvalents et puissants. Plus précisément dans SQL Server, Sybase ou MySQL, les procédures peuvent renvoyer un nombre arbitraire d'ensembles de résultats/comptes de mises à jour, bien que ce ne soit pas la même chose qu'une fonction qui renvoie un type bien défini.

Considérez les procédures comme des routines impératives (avec effets secondaires) et de fonctions comme pures routines sans effets secondaires. Un SELECT l'instruction elle-même est également "pure" sans effets secondaires (mis à part les effets de verrouillage potentiels), il est donc logique de considérer les fonctions comme les seuls types de routines pouvant être utilisées dans un SELECT déclaration.

En fait, considérez les fonctions comme des routines avec de fortes contraintes de comportement, alors que les procédures sont autorisées à exécuter des programmes arbitraires.

Langages 4GL et 3GL

Une autre façon de voir cela est du point de vue de SQL étant un langage de programmation de 4ème génération (4GL) . Un 4GL ne peut fonctionner raisonnablement que s'il est fortement limité dans ce qu'il peut faire. Expressions de table communes rendues SQL turing-complete , oui, mais la nature déclarative de SQL l'empêche toujours d'être un langage à usage général d'un point de vue pratique et quotidien.

Les procédures stockées sont un moyen de contourner cette limitation. Parfois, vous voulez être complet et pratique. Ainsi, les procédures stockées deviennent impératives, ont des effets secondaires, sont transactionnelles, etc.

Les fonctions stockées sont un moyen intelligent d'introduire certaines 3GL / fonctionnalités de langage procédural dans le monde 4GL plus pur au prix d'interdire les effets secondaires à l'intérieur (sauf si vous voulez ouvrir la boîte de pandore et avoir SELECT complètement imprévisible déclarations).

Le fait que certaines bases de données autorisent leurs procédures stockées à renvoyer un nombre arbitraire d'ensembles de résultats / curseurs est une caractéristique de leur comportement arbitraire, y compris les effets secondaires. En principe, rien de ce que j'ai dit n'empêcherait ce comportement particulier également dans les fonctions stockées, mais il serait très peu pratique et difficile à gérer s'ils étaient autorisés à le faire dans le contexte de SQL, le langage 4GL.

Ainsi :

  • Les procédures peuvent appeler des procédures, n'importe quelle fonction et SQL
  • Les fonctions "pures" peuvent appeler des fonctions "pures" et SQL
  • SQL peut appeler des fonctions "pures" et SQL

Mais :

  • Les fonctions "pures" appelant des procédures deviennent des fonctions "impures" (comme les procédures)

Et :

  • SQL ne peut pas appeler de procédures
  • SQL ne peut pas appeler des fonctions "impures"

Exemples de fonctions table "pures" :

Voici quelques exemples d'utilisation de fonctions table "pures" :

Oracle

CREATE TYPE numbers AS TABLE OF number(10);
/

CREATE OR REPLACE FUNCTION my_function (a number, b number)
RETURN numbers
IS
BEGIN
    return numbers(a, b);
END my_function;
/

Et ensuite :

SELECT * FROM TABLE (my_function(1, 2))

SQL Server

CREATE FUNCTION my_function(@v1 INTEGER, @v2 INTEGER)
RETURNS @out_table TABLE (
    column_value INTEGER
)
AS
BEGIN
    INSERT @out_table
    VALUES (@v1), (@v2)
    RETURN
END

Et puis

SELECT * FROM my_function(1, 2)

PostgreSQL

Laissez-moi vous parler de PostgreSQL.

PostgreSQL est génial et donc une exception. C'est aussi bizarre et probablement 50% de ses fonctionnalités ne devraient pas être utilisées en production. Il ne prend en charge que les "fonctions", pas les "procédures", mais ces fonctions peuvent agir comme n'importe quoi. Consultez les éléments suivants :

CREATE OR REPLACE FUNCTION wow ()
RETURNS SETOF INT
AS $$
BEGIN
    CREATE TABLE boom (i INT);

    RETURN QUERY
    INSERT INTO boom VALUES (1)
    RETURNING *;
END;
$$ LANGUAGE plpgsql;

Effets secondaires :

  • Un tableau est créé
  • Un enregistrement est inséré

Pourtant :

SELECT * FROM wow();

Rendements

wow
---
1