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
DDDoriginal
2025-01-10 11:19:42477parcourir

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 :

<code class="language-sql">SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table
) sub;</code>

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 :

<code class="language-sql">SELECT mf.*
FROM some_table
LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;</code>

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 :

<code class="language-sql">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;</code>

et un tableau contenant des données factices :

<code class="language-sql">CREATE TABLE some_table AS SELECT x FROM generate_series(1,10) x;</code>

Comparez les résultats des requêtes suivantes :

  • Syntaxe originale :
<code class="language-sql">SELECT (my_func(x)).* FROM some_table;</code>
  • Syntaxe de la solution :
<code class="language-sql">SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table
) sub;</code>

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