7
votes

Oracle Pl / SQL: fonctions et paramètres facultatifs, comment?

Je cherche la manière optimale de créer une fonction qui ne peut accepter aucun paramètre et renvoyer tous les résultats, mais accepte également les paramètres et renvoyer ces résultats.

La norme que j'ai traitée à mon travail est-ce : xxx

Le problème est que je souhaite retourner des enregistrements ayant également un type de NULL, et en utilisant: xxx < P> Il ne renvoie que des enregistrements avec des types réels et non des enregistrements nuls. Pour des raisons évidentes. Je me demandais simplement s'il y a une façon standard de cela qui pourrait être mis en œuvre dans toutes les fonctions que nous utilisons. Par coïncidence, si je fournis un paramètre ... Je ne veux pas les valeurs nulles de ce champ.


0 commentaires

5 Réponses :


4
votes

7 commentaires

Le : = dans les déclarations de paramètres est identique à celui par défaut . Le problème semble être qu'une valeur nulle pour le paramètre signifie correspondre aux enregistrements avec une valeur null dans la colonne correspondante; Donc, quelle valeur par défaut doit être utilisée pour indiquer "tous les enregistrements"?


Ne retourne pas les enregistrements qui ont également un type de null. Je veux essentiellement égaler le type si je fournis le paramètre, sinon n'utilise pas le paramètre. Ce n'est pas dynamique SQL, vous pouvez donc voir le dilemna. Si c'était le cas, je n'exclureais pas la clause.


@Dave Costa: Merci pour l'information. J'ai toujours utilisé le mot-clé par défaut , et non le signe égal (: = ) pour définir les valeurs par défaut.


@jlrolin: Puissiez-vous fournir un exemple de code de votre corps de fonction, avec un exemple de données dans la table de données que vous extrayez les données? Cela pourrait faire ressortir d'autres idées de solutions.


@Will: Le corps de la fonction est un simple sélectionnel * à partir de la table où Type = NVL (i_type, type), étant introduit dans un ref_cursor, puis retourné.


@jlrolin: et l'échantillon de la table de données?


Deux champs: code et type. Le code n'est jamais NULL, VARCHAR2 (2 octets), type peut être NULL, VARCHAR2 (5 octets).



3
votes

Pour réitérer ma compréhension du problème: vous ne pouvez pas prendre la valeur par défaut de null pour signifier "renvoyer tous les enregistrements", car le comportement attendu actuel est qu'il ne renverra que ces enregistrements où La valeur est en réalité null.

Une possibilité est d'ajouter un paramètre booléen correspondant à chaque paramètre de recherche, ce qui indique s'il devrait être utilisé pour filtrer les résultats. Un problème potentiel avec ceci est qu'un appelant pourrait spécifier une valeur de recherche mais ne pas définir le drapeau sur true, produisant des résultats inattendus. Vous pouvez vous protéger contre cela au moment de l'exécution en soulevant une exception si le drapeau est faux pour toute valeur de recherche autre que null .

Une autre possibilité est de définir une valeur hors du domaine pour chaque colonne de recherche - par exemple. Si la chaîne 'tout' est transmise pour le paramètre, il ne filtrera pas les valeurs de cette colonne. Cela devrait fonctionner bien tant que vous pouvez trouver une valeur sensitaire valable pour chaque colonne. Je suggérerais de déclarer les valeurs sentinelles en tant que constantes de certains packages, afin que les appels à la fonction puissent ressembler à get_records (pkg.all_codes, "type1") . .


0 commentaires

5
votes

Pourquoi pas simplement ce que vous avez avec l'ajout de xxx pré>

de cette façon, lorsque le paramètre transmis est null, il cherche tout (y compris les nulls) ou la valeur spécifiée. Maintenant, si vous voulez juste que les nulls ... p>

exemple (modifiez la valeur de NULL en 5 et vous verrez la sortie) p>

DATAID                 
---------------------- 
6


3 commentaires

Je suggérerais de le changer à type = i_type ou i_type est null . C'est dans mon expérience plus susceptible de tirer parti d'un index sur type que d'utiliser NVL (). Aussi, semble plus claire pour moi.


@Dave: C'est la solution que j'ai mise en œuvre.


Cette approche n'est généralement pas sargable



5
votes

Le moyen standard de résoudre ce problème est de surcharger la fonction, au lieu d'utiliser des valeurs par défaut: xxx

Remarque: Si vous avez également besoin d'une version i_type par elle-même, vous aurez peut-être des problèmes si cela a le même type sous-jacent que i_code - auquel cas vous auriez besoin d'utiliser un nom différent pour la fonction.


1 commentaires

@OMG: Eh bien, ma solution ne dit rien de savoir si Dynamic SQL est utilisé ou non - le point est, comment dites-vous entre Get_Records (NULL, NULL) et GET_RECORDS (NULL), à moins que vous ne composiez de "valeurs magiques" pour le Paramètres par défaut? La surcharge est la meilleure façon de résoudre ce problème, imo.



1
votes

J'ai utilisé le piratage suivant (en supposant que p_product est une entrée de procédure facultative):

où t.product = décodage (p_product, null, t.product, p_product) strong> p >

procedure get_data(p_product in number := null)
...
select *
from tbl t
where t.product = decode(p_product, null, t.product, p_product);
...


0 commentaires