12
votes

Comment convertir efficacement le texte en numéro dans Oracle Pl / SQL avec NLS_Numeric_Characters non par défaut?

Je suis en train de trouver un moyen générique efficace, convertir chaîne en nombre dans PL / SQL, où le contexte local pour les paramètres de NLS_NUMERIC_CHARACTERS est inpredictable - et préférable que je ne vais pas le toucher. Le format d'entrée est la norme de programmation « 123,456789 », mais avec un nombre inconnu de chiffres de chaque côté du point décimal.

CREATE OR REPLACE
FUNCTION STRING2NUMBER (p_string varchar2) RETURN NUMBER
IS
  v_decimal char;
BEGIN
  SELECT substr(VALUE, 1, 1)
  INTO v_decimal
  FROM NLS_SESSION_PARAMETERS
  WHERE PARAMETER = 'NLS_NUMERIC_CHARACTERS';
  return to_number(replace(p_string, '.', v_decimal));
END;
/

select string2number('123.456789') from dual;


1 commentaires

Même l'exemple plus difficile est de convertir '12 .34e5 '. Je n'ai trouvé aucun format qui accepte que, mais le code mono-param to_number n'a aucun problème avec l'analyse.


5 Réponses :


11
votes

Les éléments suivants doivent fonctionner:

SELECT to_number(:x, 
                 translate(:x, '012345678-+', '999999999SS'), 
                 'nls_numeric_characters=''.,''') 
  FROM dual;


1 commentaires

Il peut être utile de compléter l'argument "FMT" de TO_Number fonction comme suit: Traduire (: x, '0123456789., - +', '9999999999DG') . Cela arrête une erreur ORA-01481 sur un chiffre négatif.



3
votes

Si vous faites beaucoup de travail par session, une option peut être d'utiliser Alter Session Set Nls_numérique_Characters = '.,' Au début de votre tâche.

Bien sûr, si beaucoup d'autre code est exécuté dans la même session, vous pouvez obtenir des résultats funky :-) Cependant, nous sommes en mesure d'utiliser cette méthode dans nos procédures de chargement de données, car nous avons des programmes dédiés avec leurs propres pools de connexion pour charger les données.


0 commentaires

3
votes

Désolé, j'ai remarqué plus tard que votre question était de l'inverse. Néanmoins, il est remarquable que, pour la direction opposée, il existe une solution facile: em>

Un peu tard, mais j'ai remarqué aujourd'hui les masques de format spéciaux 'TM9' et "TME" qui sont décrits comme "le format de numéro minimal du texte modèle renvoie (en sortie décimale) le plus petit nombre de caractères possible. " sur https://docs.oracle.com/cloud/latest /db112/sqlrf/sql_elements004.htm#sqlrf00210 . p>

Il semble que TM9 ait été inventé pour résoudre ce problème particulier: P>

select to_char(1234.5678, 'TM9', 'NLS_NUMERIC_CHARACTERS=''.,''') from dual;


0 commentaires

0
votes
select to_number(translate(:X,to_char(0,'fmd')||'.','.'||to_char(0,'fmd'))) from dual;

1 commentaires

@Jammydodger Cela fait du travail et des réponses question a été posée. agréable d'obtenir -1 point pour cela. De vous, je mets. cool



0
votes

est-il réaliste que le nombre de chiffres est illimité? Si nous supposons que ce n'est donc pas une bonne raison d'examiner les exigences plus attentivement?

Si nous avons cette situation fantastique lorsque la chaîne initiale est super longue, alors ce qui suit est le truc: < Pré> xxx


0 commentaires