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?
Vous pouvez utiliser REGEXP_LIKE:
SELECT 1 FROM DUAL
WHERE REGEXP_LIKE('23.9', '^\d+(\.\d+)?$', '')
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
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.
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.
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;