Comment puis-je déterminer si une chaîne de caractères est numérique en SQL?

dans une requête SQL sur Oracle 10g, je dois déterminer si une chaîne est numérique ou non. Comment puis-je faire cela?

12
demandé sur Sergey Glotov 2011-04-14 21:13:06

7 réponses

vous pouvez utiliser REGEXP_LIKE:

SELECT 1 FROM DUAL
WHERE REGEXP_LIKE('23.9', '^\d+(\.\d+)?$', '') 
26
répondu Chandu 2011-04-14 17:30:03

you can try this:

SELECT LENGTH(TRIM(TRANSLATE(string1, ' +-.0123456789', ' '))) FROM DUAL

où string1 est ce que vous évaluez. Il retournera nul si numérique. Regardez ici pour plus de précisions

5
répondu Adrian Carneiro 2011-04-14 17:23:47

Je n'ai pas accès à une instance 10G pour tester, mais cela fonctionne en 9i:


CREATE OR REPLACE FUNCTION is_numeric (p_val VARCHAR2)
   RETURN NUMBER
IS
v_val   NUMBER;
BEGIN
   BEGIN
      IF p_val IS NULL OR TRIM (p_val) = ''
      THEN
         RETURN 0;
      END IF;

      SELECT TO_NUMBER (p_val)
        INTO v_val
        FROM DUAL;

      RETURN 1;
   EXCEPTION
      WHEN OTHERS
      THEN
         RETURN 0;
   END;
END;


SELECT is_numeric ('333.5') is_numeric
  FROM DUAL;

j'ai supposé que vous vouliez que nulls/empties soit considéré comme faux.

2
répondu Evan Haas 2011-04-14 17:27:03

comme le souligne Tom Kyte dans http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:7466996200346537833 , si vous utilisez le TO_NUMBER intégré dans une fonction définie par l'utilisateur, vous pouvez avoir besoin d'un peu de ruse supplémentaire pour le faire fonctionner.

FUNCTION is_number(x IN VARCHAR2)
RETURN NUMBER
IS
    PROCEDURE check_number (y IN NUMBER)
    IS
    BEGIN
        NULL;
    END;
BEGIN
    PRAGMA INLINE(check_number, 'No');
    check_number(TO_NUMBER(x);
    RETURN 1;
EXCEPTION
    WHEN INVALID_NUMBER
    THEN RETURN 0;
END is_number;

le problème est que le compilateur d'optimisation mai reconnaître que le résultat du TO_NUMBER n'est pas utilisé n'importe où et l'optimiser loin.

dit Tom (son exemple concernait les dates plutôt que les nombres):

la désactivation de la fonction inlining fera l'appel à check_date doit être fait comme une fonction l'appelant pour que le La DATE doit être placée sur la pile d'appels. Il n'y a aucune chance pour l' compilateur optimisant pour supprimer l'appel à to_date dans ce cas. Si l' l'appel à to_date nécessaire pour l'appel à check_date échoue raison, nous savons que la chaîne d'entrée n'était pas convertible à cette date format.

2
répondu SQB 2014-08-20 17:59:15

Voici une méthode pour déterminer numérique qui peut faire partie d'une requête simple, sans créer une fonction. Comptes pour des espaces, +- pas le premier caractère, ou un deuxième point décimal.

var v_test varchar2(20);
EXEC :v_test := ' -24.9 ';

 select
 (case when trim(:v_test) is null then 'N' ELSE   -- only banks, or null
 (case when instr(trim(:v_test),'+',2,1) > 0 then 'N' ELSE  -- + sign not first char
 (case when instr(trim(:v_test),'-',2,1) > 0 then 'N' ELSE  -- - sign not first char
 (case when instr(trim(:v_test),' ',1,1) > 0 then 'N' ELSE  -- internal spaces
 (case when instr(trim(:v_test),'.',1,2) > 0 then 'N' ELSE  -- second decimal point
 (case when LENGTH(TRIM(TRANSLATE(:v_test, ' +-.0123456789',' '))) is not null then 'N' ELSE  -- only valid numeric charcters.
  'Y'
  END)END)END)END)END)END) as is_numeric
  from dual;
0
répondu John Ryan 2015-09-24 23:09:09

j'ai trouvé que la solution

LENGTH(TRIM(TRANSLATE(string1, ' +-.0123456789', ' '))) is null

permet les blancs encastrés ... il accepte "123 45 6789" qui, pour moi, n'est pas un nombre.

un autre niveau de trim/translate corrige cela. Ce qui suit détectera un champ de chaîne de caractères contenant des chiffres consécutifs avec des blancs de début ou de fin tels que to_number(trim (string1)) ne échouera pas

LENGTH(TRIM(TRANSLATE(translate(trim(string1),' ','X'), '0123456789', ' '))) is null
-1
répondu Peter DeGregorio 2014-08-19 14:25:47

pour les entiers, vous pouvez utiliser ce qui suit. La première translate change les espaces pour être un caractère et la seconde change les nombres pour être des espaces. Le Trim retournera alors null si seuls les nombres existent.

TRIM(TRANSLATE(TRANSLATE(TRIM('1 2 3d 4'), ' ','@'),'0123456789',' ')) is null
-1
répondu zlsmith86 2015-01-21 17:53:39