web-dev-qa-db-fra.com

Comment puis-je déterminer si une chaîne 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 ceci?

13
AndyGeek

Vous pouvez utiliser REGEXP_LIKE:

SELECT 1 FROM DUAL
WHERE REGEXP_LIKE('23.9', '^\d+(\.\d+)?$', '') 
27
Chandu

Vous pouvez essayer ceci:

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

où string1 est ce que vous évaluez. Il retournera null s'il est numérique. Regardez ici pour plus de précisions 

5
Adrian Carneiro

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


 CREATE OR REPLACE FUNCTION is_numeric (p_val VARCHAR2) 
 RETURN NUMBER 
 IS 
 V_val NUMBER; 
 BEGIN 
 COMMENCER
 SI p_val IS NULL OR TRIM (p_val) = '' 
 PUIS
 RETOUR 0; 
 FIN SI;

 SELECT TO_NUMBER (p_val) 
 INTO v_val 
 DE DOUBLE; 

 RETOUR 1; 
 EXCEPTION
 QUAND AUTRES 
 PUIS
 RETOUR 0; 
 END; 
 END; 


 SELECT is_numeric ('333.5') est_numeric 
 DE DOUBLE; 

J'ai supposé que vous vouliez que les valeurs nulles/vides soient considérées comme FAUX.

2
Evan Haas

Comme l'a souligné Tom Kyte dans http://asktom.Oracle.com/pls/apex/f?p=100:11:::::P11_QUESTION_ID:7466996200346537833 , si vous utilisez le logiciel intégré dans TO_NUMBER dans une fonction définie par l'utilisateur, vous aurez peut-être besoin d'un peu plus de tromperie pour la 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 optimiseur peut reconnaître que le résultat du TO_NUMBER n’est utilisé nulle part et l’optimiser.

Tom dit (son exemple portait sur les dates plutôt que sur les chiffres):

la désactivation de la fonction inlining le fera appeler check_date DOIT être appelé en tant qu'appel de fonction - afin que le DATE doit être placé sur la pile d'appels. Il n'y a aucune chance pour le optimisation du compilateur pour supprimer l’appel de to_date dans ce cas. Si la L'appel à to_date nécessaire pour l'appel de check_date échoue pour tout raison, nous savons que l’entrée de chaîne n’était pas convertible à cette date format.

2
SQB

Voici une méthode pour déterminer numeric qui peut faire partie d'une requête simple, sans créer de fonction. Comptes pour les espaces incorporés, + - 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
John Ryan