La documentation donne une raison pour laquelle vous pouvez voir un écart (c'est moi qui souligne):
Attention :
Parce que SQL est un langage déclaratif, plutôt qu'impératif (ou procédural), vous ne pouvez pas savoir combien de fois une fonction invoquée par une instruction SQL sera exécutée — même si la fonction est écrite en PL/SQL, un langage impératif. Si votre application nécessite qu'une fonction soit exécutée un certain nombre de fois, n'invoquez pas cette fonction à partir d'une instruction SQL. Utilisez plutôt un curseur.
Par exemple, si votre application nécessite qu'une fonction soit appelée pour chaque ligne sélectionnée, ouvrez un curseur, sélectionnez des lignes à partir du curseur et appelez la fonction pour chaque ligne. Cette technique garantit que le nombre d'appels à la fonction est le nombre de lignes extraites du curseur.
Fondamentalement, Oracle ne spécifie pas combien de fois une fonction sera appelée dans une instruction sql :cela peut dépendre de la version, de l'environnement, du chemin d'accès, entre autres facteurs.
Cependant, il existe des moyens de limiter la réécriture des requêtes comme expliqué dans le chapitre Désimbrication des sous-requêtes imbriquées :
La désimbrication de sous-requête désimbrique et fusionne le corps de la sous-requête dans le corps de l'instruction qui la contient, permettant à l'optimiseur de les considérer ensemble lors de l'évaluation des chemins d'accès et des jointures. L'optimiseur peut désimbriquer la plupart des sous-requêtes, à quelques exceptions près . Ces exceptions incluent les sous-requêtes hiérarchiques et les sous-requêtes qui contiennent une pseudo-colonne ROWNUM, l'un des opérateurs d'ensemble, une fonction d'agrégation imbriquée ou une référence corrélée à un bloc de requête qui n'est pas le bloc de requête externe immédiat de la sous-requête.
Comme expliqué ci-dessus, vous pouvez utiliser ROWNUM
pseudo-colonne pour empêcher Oracle de désimbriquer une sous-requête :
SQL> WITH data AS (SELECT SYS_GUID() uuid FROM DUAL WHERE ROWNUM >= 1)
2 SELECT uuid, uuid FROM data;
UUID UUID
-------------------------------- --------------------------------
1ADF387E847F472494A869B033C2661A 1ADF387E847F472494A869B033C2661A