IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Ora-01858 caractère non numérique


Sujet :

SQL Oracle

  1. #1
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut Ora-01858 caractère non numérique
    Bonjour à tous,
    je suis en cours de tests après migration d'une BD Oracle 8 vers 10g.
    La migration a été effectuée sans soucis (apparement) avec les outils d'export et d'import de dump.
    J'en arrive au problème. J'ai une requete qui sélectionne des données sur plusieurs tables et suivant la clause WHERE, j'obtiens le superbe message :
    ORA-01858: Caractère non numérique trouvé à la place d'un caractère numérique
    J'ai identifié la table d'où provient cette erreur, mais je ne vois pas comment je peux obtenir un tel message avec un SELECT tout basique.
    SELECT champ1, champ2, ....
    FROM table1, table2, ...
    WHERE (table1.PK = table2.FK)
    AND ...
    (TO_DATE(TO_CHAR(DATEFACTURATION,'DD/MM') || '/2007','DD/MM/YYYY') >= TO_DATE('30/06/2007','DD/MM/YYYY')) AND
    (TO_DATE(TO_CHAR(DATEFACTURATION,'DD/MM') || '/2007','DD/MM/YYYY') <= TO_DATE('31/07/2007','DD/MM/YYYY'))


    Si j'enleve la partie rouge du WHERE, la requete fonctionne.
    Si j'ajoute au SELECT TO_DATE(TO_CHAR(DATEFACTURATION,'DD/MM') || '/2007','DD/MM/YYYY') , la requete fonctionne encore

    Cette erreur est-elle en rapport avec une migration incorrecte ?

    Comment peut-on avoir ce message avec un SELECT ?

    Le paramètre NLS_DATE_FORMAT peut-il changer qq chose ?

    Je précise que toutes mes dates ont le format DD/MM/YYYY (ou semblent l'avoir).



    Toute piste est la bienvenue. Merci

    Merci

  2. #2
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT TO_DATE(TO_CHAR(TO_DATE(NULL),'DD/MM') || '/2007','DD/MM/YYYY')
    FROM dual
    => ORA-01858 a non-numeric character was found where a numeric was expected

  3. #3
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    Bien tenté, mais ce n'est pas possible, car :
    - dans mon WHERE, j'ai DATEFACTURATION IS NOT NULL
    - et cela ne fonctionnerait pas dans le select non plus
    - et cela ne fonctionnerait pas non plus sur ma base en Oracle 8

    Une autre idée ?

  4. #4
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    Apres avoir creusé un peu (beaucoup), je pense que l'erreur vient du WHERE.

    DATEFACTURATION IS NOT NULL ne semble pas exécuté avant le TO_DATE(...
    Effectivement, dans ce cas là, ca pause soucis.
    Je sais que je peux eviter d'avoir des valeurs nulles en utilisant la fonction NVL, mais je devrais mettre une valeur par défaut dans ce cas...et je ne peux pas (le résultat de la requete serait faux à certaines périodes).
    Le plan d'éxécution de la requete est donc différent entre Oracle 8 et 10g.

    Comment puis-je m'assurer que mon 1er WHERE soit exécuté avant le TO_Date(... ?

  5. #5
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    WITH t AS (SELECT TO_DATE(NULL) AS dtenulle FROM dual)
    SELECT 1
    FROM t
    WHERE dtenulle IS NOT NULL
    AND TO_DATE(TO_CHAR(dtenulle,'DD/MM') || '/2007','DD/MM/YYYY') > SYSDATE
    ORA-01858 a non-numeric character was found where a numeric was expected

    Les conditions WHERE sont toutes vérifiées en même temps (donc datefacturation peut être null).
    Donc c'est tout a fait normal que ça marche dans ton select.
    Bref,
    - dans mon WHERE, j'ai DATEFACTURATION IS NOT NULL
    Fallait le dire au début, pô bien de cacher des infos

  6. #6
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    Pourquoi ma requete fonctionnait tres bien avant en Oracle 8 ?
    Il y a un paramétrage pour éviter ce genre de chose ?

  7. #7
    Rédacteur

    Homme Profil pro
    Développeur et DBA Oracle
    Inscrit en
    Octobre 2006
    Messages
    878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur et DBA Oracle

    Informations forums :
    Inscription : Octobre 2006
    Messages : 878
    Par défaut
    Salut,

    Essaie d'éliminer les nulls avant c'est a dire dans ta clause from
    Essaie ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SQL> WITH t AS (SELECT TO_DATE(NULL) AS dtenulle FROM dual)
      2  SELECT 1
      3  FROM ( SELECT * FROM  t WHERE dtenulle IS NOT NULL) T
      4  WHERE  TO_DATE(TO_CHAR(dtenulle,'DD/MM') || '/2007','DD/MM/YYYY') 
    > SYSDATE;
    
    aucune ligne sélectionnée

  8. #8
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    Je suis entierement d'accord avec toi pour la requete.
    Maintenant, ce que je voudrez comprendre, c'est pourquoi ce genre de requete fonctionnait en Oracle8 et ne fonctionne plus en Oracle10g. Cela me permettrait de mieux détecter les problèmes dans le cadre de ma migration.
    Merci

  9. #9
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    Citation Envoyé par pascalT
    Je suis entierement d'accord avec toi pour la requete.
    Maintenant, ce que je voudrez comprendre, c'est pourquoi ce genre de requete fonctionnait en Oracle8 et ne fonctionne plus en Oracle10g.
    je ne suis pas du tout d'accord avec la requête. Le fait que la requête fonctionne une fois ne veut pas dire que le code soit robuste. Il ne s'agit pas là de version mais bien de stabilité.

    en effet, la sous-requête peut être fusionée avec la requête principale par l'optimiseur, donc pas de chance dans ce cas.

    le seul code que je considère comme bon est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT * FROM  t 
    WHERE decode(dt,null,null, 
      TO_DATE(TO_CHAR(dt,'DD/MM') || '/2007','DD/MM/YYYY') 
      > SYSDATE;
    Là on est vraiment sûr que le to_date ne sera pas executé.

    Bon bien sûr ca boggue quand dt=29/02/2004 !!!

  10. #10
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    S'il ne s'agit pas de comportements différents à cause de la version, il s'agit bien de comportements différents entre les optimiseurs des 2 versions.
    Quelles sont les différences principales des 2 optimiseurs ?
    Sinon, comment puis-je savoir les différences des 2 optimiseurs ?

  11. #11
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    Là n'est pas le problème... C'est vrai que si tu employais le RULE BASED optimizer en 8i et que tu employes maintenant le COST BASED, ça peut faire la différence. Avec le RULE BASED, le plan pour une requête était constant. Avec le CBO, ça ne marche plus, le plan peut changer à tout moment, selon les statistiques etc...

    Quoi que même en RBO, ça tient du miracle que ta requête n'ait jamais planté

  12. #12
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    Merci de ta réponse Laurent, je venais de découvrir aussi ta réponse.
    Y a t-il un moyen de passer (temporairement même si cela n'est pas propre) une base 10g en RBO ?

  13. #13
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 52
    Par défaut
    Je viens de trouver la réponse à ma question.
    Un petit ALTER SESSION suffit.
    Merci à tous de votre aide

  14. #14
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 4
    Par défaut
    Bonjour,

    J'ai le même problème (ORA-01858), mais c'est un peu spécial.
    Je m'explique:

    Je dois insérer plusieurs milliers de lignes dans la base avec python (cx_Oracle), et donc j'ai voulu utiliser la méthode cursor.executemany (query, param).
    Mais lorsque j'execute mon scripte, il me sort cette erreur (ORA-01858: a non-numeric character was found where a numeric was expected),
    alors que (ce que je n'ai pas encore compris), lorsque j'insère ligne par ligne, eh bien ça marche.

    Voici le bout de code (une table de test):

    Creation table:
    CREATE TABLE MKT_DATA.test
    (
    name VARCHAR2(20),
    dt DATE
    )

    Python qui marche:
    cursor.execute("INSERT INTO MKT_DATA.TEST_MEHDI(NAME,DT) VALUES('mon_nom',TO_DATE('2008-08-13','YYYY-MM-DD'))")

    Python qui NE marche PAS:
    cursor.executemany("INSERT INTO MKT_DATA.TEST_MEHDI(NAME,DT) VALUES(:NAME,T)",[('mon_nom', "TO_DATE('2008-08-13','YYYY-MM-DD')")])

    j'ai même essayé:
    cursor.execute("INSERT INTO MKT_DATA.TEST_MEHDI(NAME,DT) VALUES(:NAME,T)",[('mon_nom', "TO_DATE('2008-08-13','YYYY-MM-DD')")])

    Mais, MEME problème.

    Pouvez-vous m'aider la dessus?

    Merci d'avance

  15. #15
    Membre averti
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Par défaut
    cursor.executemany("INSERT INTO MKT_DATA.TEST_MEHDI(NAME,DT) VALUES(:NAME,T)",[('mon_nom', "TO_DATE('2008-08-13','YYYY-MM-DD')")])

    Salut,
    tu as essayé sans les guillemets ?

  16. #16
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 4
    Par défaut
    Je ne peux pas, puisque python cherchera la méthode TO_DATE, et il ne trouveras pas...

    Merci quand même.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [PL/SQL] Supprimer les caractères non numériques
    Par Oliveuh dans le forum PL/SQL
    Réponses: 6
    Dernier message: 25/06/2015, 12h13
  2. Réponses: 2
    Dernier message: 16/05/2011, 18h43
  3. Réponses: 1
    Dernier message: 03/06/2008, 09h05
  4. Interdire une frappe d'un caractére non numérique
    Par fatati dans le forum C++Builder
    Réponses: 13
    Dernier message: 12/12/2006, 09h56
  5. Réponses: 8
    Dernier message: 22/06/2005, 10h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo