8 votes

Bool support Oracle SQL

J'ai toujours été frustré par le fait qu'Oracle PL/SQL prenne en charge l'option bool alors qu'Oracle SQL ne le fait pas. C'est un véritable casse-tête lorsque vous souhaitez traiter une valeur de retour booléenne PL/SQL dans votre SQL de tous les jours (voir l'exemple ci-dessous).

Même le site web ask-Tom est blasé à propos de cette erreur, indiquant qu'il faut coder les colonnes booléennes comme des valeurs fixes 'Y'/'N' CHAR qui est une réponse tellement mauvaise à tant de niveaux différents que je ne sais pas par où commencer pour la critiquer. En fait, la seule qualité de cette réponse est le fait que (d'après ce que j'ai découvert récemment), de nombreux autres moteurs de base de données ne supportent pas non plus le type de données booléen.

Quoi qu'il en soit, la question...

J'ai une solution pour résoudre le problème suivant (bien qu'elle soit compliquée et verbeuse), je pose donc cette question par curiosité plutôt que par nécessité. Mais l'une des rares choses qui me surprend encore est l'ingéniosité des programmeurs intelligents, alors j'espère que l'un d'entre vous pourra trouver une solution à ce qui suit.

Dans l'exemple suivant, la fonction stock_pkg.is_in_stock() (qui fait partie intégrante de mon application) renvoie une valeur BOOL, ce qui rend le SQL invalide (rappelez-vous que SQL ne supporte pas les BOOL) :

SELECT part_no, stock_pkg.is_in_stock(part_no) in_stock
FROM   parts_table

Ce dont j'ai besoin, c'est de trouver un moyen d'utiliser l'appel de fonction ci-dessus pour générer une chaîne de caractères valide (varchar) au format :

PART_NO IN_STOCK
------- ------------
AA      YES
BB      NO
CC      NO

(Vous pouvez remplacer "oui/non" par "vrai/faux", "vert/rouge", "conservateur/travailliste" ou même par un chiffre 1/0, du moment que le résultat entre dans l'une des deux catégories distinctes).

Malheureusement, je n'ai pas le privilège de réécrire la fonction originale pour qu'elle renvoie un type de données différent. De plus, il existe des milliers de fonctions de ce type dans l'ensemble de l'application, ce qui rend impossible de les réécrire toutes.

En ce sens, la solution doit être "générique" (c'est-à-dire qu'elle n'est pas spécifique à cet appel de fonction). Par exemple, il ne suffit pas de réécrire la fonction comme suit stock_pkg.is_in_stock_chr() car cela signifierait qu'il faudrait réécrire toutes les autres fonctions similaires dans mon application.

J'ai déjà essayé :

SELECT part_no,
       CASE WHEN stock_pkg.is_in_stock(part_no) THEN 'y' ELSE 'n' END in_stock
FROM   parts_table

et même ma propre fonction wrapper :

SELECT part_no,
       my_bool_to_str(stock_pkg.is_in_stock(part_no)) in_stock
FROM   parts_table

Mais même l'intégration de booléens dans d'autres constructions fonctionnelles ne semble pas être autorisée par Oracle SQL (du moins pas dans Oracle 10g).

Il est également possible d'écrire une sous-sélection à l'intérieur de l'élément in_stock mais cela pourrait s'avérer excessivement compliqué dans des exemples extrêmes et serait également spécifique à chaque cas.

Comme je l'ai dit, j'espère qu'il existe une solution ingénieuse quelque part (ou au moins une solution très simple qui m'a échappé).

Merci pour votre temps.

6voto

A.B.Cade Points 11607

Vous pouvez écrire votre propre wrapper comme ceci :

CREATE OR REPLACE FUNCTION my_bool_to_str(f varchar2) RETURN VARCHAR2 IS

  b varchar2(2);

BEGIN

  EXECUTE IMMEDIATE 'declare bl boolean; begin bl := ' || f ||
                    '; if bl then :1 := ''y''; else :1 := ''n''; end if; end;'
    using out b;

  return b;

END;

Vous pouvez alors l'appeler comme suit :

SELECT part_no,
       my_bool_to_str('stock_pkg.is_in_stock('|| part_no|| ')') in_stock
FROM   parts_table

La différence avec votre wrapper est qu'il reçoit un varchar en entrée et non un boolean que le moteur SQL ne reconnaît pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X