Maison >base de données >tutoriel mysql >Comment empêcher plusieurs appels de fonction lors de l'utilisation de `(func()).*` dans les requêtes SQL ?

Comment empêcher plusieurs appels de fonction lors de l'utilisation de `(func()).*` dans les requêtes SQL ?

Linda Hamilton
Linda Hamiltonoriginal
2025-01-10 11:51:42592parcourir

How to Prevent Multiple Function Calls When Using `(func()).*` in SQL Queries?

Éviter les appels de fonction répétés à l'aide de (func()).* dans les requêtes SQL

Lors de l'utilisation de fonctions renvoyant des tables ou des types composites, la syntaxe (func(arg)).* peut conduire à des appels de fonction redondants pour chaque colonne de sortie. Ce problème survient lors de l'appel de fonctions dans des tables ou des sous-requêtes, où (func()).* est souvent la seule approche pratique.

Le problème

De façon inattendue, (func()).* déclenche plusieurs exécutions de fonctions : un nombre égal au nombre de colonnes de sortie. Par exemple, une fonction renvoyant quatre colonnes peut être appelée huit fois au lieu des deux attendues.

Solutions

Pour remédier à cela, encapsulez l'appel de fonction dans une sous-requête :

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

Cela évite généralement les appels de fonctions supplémentaires et n'introduit pas d'analyses d'exécution supplémentaires. Pour une certitude absolue, envisagez l'OFFSET 0 astuce ou exploitez les limites de PostgreSQL dans l'optimisation CTE :

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

WITH tmp(mf) AS (
    SELECT my_func(x) FROM some_table
)
SELECT (mf).* FROM tmp;</code>

PostgreSQL 9.3 et versions ultérieures offrent une solution plus élégante utilisant LATERAL :

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

Cause fondamentale

L'expansion de (func()).* par l'analyseur dans une liste de colonnes est la cause sous-jacente. L'arbre analysé révèle que (func(x)).* se transforme en :

<code>(my_func(x)).i, (my_func(x)).j, (my_func(x)).k, (my_func(x)).l</code>

Ce clonage de nœud inefficace, plutôt qu'une réplication de nœud d'appel de fonction unique, entraîne des appels répétés.

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