Maison > base de données > tutoriel mysql > Comment puis-je éviter les évaluations de fonctions multiples lors de l'utilisation de `(func()).*` dans PostgreSQL ?

Comment puis-je éviter les évaluations de fonctions multiples lors de l'utilisation de `(func()).*` dans PostgreSQL ?

DDD
Libérer: 2025-01-10 11:19:42
original
481 Les gens l'ont consulté

How Can I Avoid Multiple Function Evaluations When Using `(func()).*` in PostgreSQL?

*Évitez d'utiliser `(func()).` dans PostgreSQL pour provoquer des appels de fonction répétés**

Dans PostgreSQL, l'utilisation de la syntaxe (func()).* pour accéder aux résultats d'une fonction qui renvoie une table ou un type composite peut entraîner des appels répétés à la fonction pour chaque colonne. Cela peut avoir un impact sur les performances, surtout si la fonction est coûteuse en calcul.

Solution

Pour éviter ce problème, vous pouvez envelopper l'appel de fonction dans une sous-requête comme celle-ci :

SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table
) sub;
Copier après la connexion
Copier après la connexion

Cela garantit que la fonction n'est appelée qu'une seule fois, quel que soit le nombre de colonnes dans le résultat. Alternativement, dans PostgreSQL 9.3 et versions ultérieures, vous pouvez utiliser la syntaxe LATERAL JOIN :

SELECT mf.*
FROM some_table
LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;
Copier après la connexion

Cause du problème

L'appel répété se produit parce que l'analyseur traite (func()).* comme un espace réservé pour une liste de noms de colonnes. Il étend la macro d'expression en une série de colonnes distinctes, ce qui entraîne plusieurs appels à la fonction.

Démo

Pour démontrer le problème et la solution, créez une fonction :

CREATE OR REPLACE FUNCTION my_func(integer)
RETURNS TABLE(a integer, b integer, c integer) AS $$
BEGIN
    RAISE NOTICE 'my_func(%)',;
    RETURN QUERY SELECT , , ;
END;
$$ LANGUAGE plpgsql;
Copier après la connexion

et un tableau contenant des données factices :

CREATE TABLE some_table AS SELECT x FROM generate_series(1,10) x;
Copier après la connexion

Comparez les résultats des requêtes suivantes :

  • Syntaxe originale :
SELECT (my_func(x)).* FROM some_table;
Copier après la connexion
  • Syntaxe de la solution :
SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table
) sub;
Copier après la connexion
Copier après la connexion

Vous remarquerez que la syntaxe d'origine génère plusieurs notifications, tandis que la syntaxe de la solution ne génère qu'une seule notification, démontrant l'effet d'éviter plusieurs appels de fonction.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal