(func()).*
dans les requêtes SQLLors 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.
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.
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>
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!