Partage
  • Partager sur Facebook
  • Partager sur Twitter

[ORACLE]Calcul sur dates dans une colonne texte

Sujet résolu
    14 novembre 2017 à 11:28:18

    Bonjour à tous,

    J'ai dans ma base de données une colonne qui contient des comptes rendus.

    Au sein de ces comptes rendus textuels il peut y avoir de une à x dates qui sont sous la forme JJ/MM/AAAA.

    Le but serait de changer ces dates en enlevant par exemple 300 jours à l'ensemble des dates.

    J'arrive a masquer les dates en utilisant l'expression régulière suivante:

    UPDATE ma_table SET compterendu = regexp_replace(compterendu,'([0-9]+/[0-9]+/[0-9]+)','**/**/****);


    En revanche, il semble impossible de réaliser des calculs ou d'utiliser des variables dans un regexp_replace ou un replace.

    UPDATE ma_table SET compterendu = regexp_replace(compterendu,'([0-9]+/[0-9]+/[0-9]+)','/1'-300);

    J'obtiens l'erreur ORA-01722: invalid number.

    Je vais donc certainement devoir écrire une procédure pour résoudre ce problème, mais n'ayant pas un très bon niveau en PL/SQL j'ai du mal à voir de quelle manière procéder.

    Auriez vous des pistes sur la meilleure façon de résoudre ce problème?

    Merci !

    • Partager sur Facebook
    • Partager sur Twitter
      14 novembre 2017 à 12:06:02

      Bonjour,

      Si l'on passe sur le problème de conception qui t'oblige aujourd'hui à rechercher dans une chaîne de caractères, des dates, pour lesquelles des fautes de frappes sont plausibles (par exemple 32/12/0217 au lieu de 31/12/2017), il faut considérer que regexp_replace travaille sur une chaîne de caractères, pas un nombre et encore moins une date ...

      Il te faut donc explicitement caster cette chaîne avec un TO_DATE puis un - 300 puis un TO_CHAR là dessus.

      Genre :

      REGEXP_REPLACE(
      	compterendu,
      	'([0-9]+/[0-9]+/[0-9]+)',
      	TO_CHAR( TO_DATE( '/1', 'DD/MM/YYYY' )-300, 'DD/MM/YYYY' )
      );

      Je n'ai pas Oracle dispo, donc à tester ;)

      • Partager sur Facebook
      • Partager sur Twitter
      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
        14 novembre 2017 à 12:56:33

        Bonjour Benzouye,

        Je ne suis malheureusement pas à l'origine de la conception. Je suis bien d'accord avec vous il y aura certainement des fautes de frappes mais déjà résoudre ce problème enlèverai 90% du problème.

        En ce qui concerne ta suggestion, j'ai oublié de le préciser dans mon premier message mais j'avais déjà essayé de rajouter un TO_CHAR(TO_DATE)) sans plus de succès. :(

        J'obtiens l'erreur ORA-01858:a non-numeric character was found where a numeric was expected

        Il semble impossible de modifier des valeurs exprimée sous la forme '/1'.

        En revanche le code ci-dessous marche... et me remplace toute mes dates par le 08/12/1959

        REGEXP_REPLACE(
            compterendu,
            '([0-9]+/[0-9]+/[0-9]+)',
            TO_CHAR( TO_DATE( '03/10/1960', 'DD/MM/YYYY' )-300, 'DD/MM/YYYY' )
        );



        Merci en tout cas de votre aide !

        -
        Edité par nekrash 14 novembre 2017 à 13:28:54

        • Partager sur Facebook
        • Partager sur Twitter
          14 novembre 2017 à 13:45:25

          Backslash au lieu du slash, non ? https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions130.htm

          REGEXP_REPLACE(
              compterendu,
              '([0-9]+/[0-9]+/[0-9]+)',
              TO_CHAR( TO_DATE( '\1', 'DD/MM/YYYY' )-300, 'DD/MM/YYYY' )
          );

          -
          Edité par Benzouye 14 novembre 2017 à 13:45:52

          • Partager sur Facebook
          • Partager sur Twitter
          Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
            14 novembre 2017 à 14:55:24

            J'avais bien un backslash dans mon code :(
            • Partager sur Facebook
            • Partager sur Twitter
              14 novembre 2017 à 16:23:44

              Ton problème m'intrigue ... J'ai creusé un peu et il semble en effet qu'Oracle n'accepte pas les fonctions sur la variable '\1' ...

              Du coup, je pense que tu devrais créer une table avec une seule colonne, contenant la liste des dates trouvées :

              CREATE TABLE dates_temp AS
              SELECT DISTINCT
              	REGEXP_SUBSTR(
              		compterendu,
              		'([0-9]{2}/[0-9]{2}/[0-9]{4})'
              	) AS date_trouvee
              FROM ma_table;

              Regarde ce que cela donne en quantité ... Si ce n'est pas trop énorme, alors tu peux faire un UPDATE avec un REPLACE dans un curseur, genre :

              DECLARE v_old_char AS NVARCHAR2(10);
              DECLARE v_new_char AS NVARCHAR2(10);
              DECLARE v_date AS DATE;
              
              CURSOR boucle_dates IS
              SELECT date_trouvee FROM dates_temp;
              
              OPEN boucle_dates;
              LOOP
              	FETCH boucle_dates INTO v_old_char;
              	EXIT WHEN NOT boucle_dates%FOUND;
              	
              	SET v_date = TO_DATE( v_date_char, 'DD/MM/YYYY' )-300;
              	SET v_new_char = TO_CHAR( v_date, 'DD/MM/YYYY' );
              	
              	UPDATE ma_table
              	SET compterendu = REPLACE( compterendu, v_old_char, v_new_char)
              	WHERE compterendu LIKE '%'||v_old_char||'%';
              END LOOP;
              CLOSE boucle_dates;

              C'est bourrin, mais ça devrait faire le taff ... avec un peu de patience si la table est grosse et que le nombre de dates est important ...

              • Partager sur Facebook
              • Partager sur Twitter
              Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                14 novembre 2017 à 17:50:52

                Oui c'est bien ce que je craignais il n'y a pas de solution directe à partir du REGEXP_REPLACE dans mon cas.

                Je teste ta solution dès demain matin et je te dis ce qu'il en ressort.

                Merci pour ton aide et bonne soirée!

                -
                Edité par nekrash 14 novembre 2017 à 17:51:48

                • Partager sur Facebook
                • Partager sur Twitter
                  16 novembre 2017 à 8:15:35

                  Bonjour,

                  Je viens donner des nouvelles.

                  La procédure après quelques ajustements fonctionne parfaitement.

                  En revanche pour ce qui est de la table, REGEXP_SUBSTR ne permet de récupérer que le premier enregistrement de la ligne, je me retrouve donc avec seulement la première date de chaque ligne dans la table dates_temp.

                  J'ai trouvé une piste pour résoudre le problème:

                  https://stackoverflow.com/questions/37931856/inconsistent-datatypes-expected-got-clob-for-table-join

                  Mais pour mon cas cela semble relativement lourd...

                  J'ai testé de créer directement une table calendrier contenant l'ensemble des jours sur une période donnée, ça reste bourrin comme méthode mais ça fait le taff...


                  Edit: Merci pour l'aide, bonne continuation à toi aussi!


                  -
                  Edité par nekrash 16 novembre 2017 à 9:46:14

                  • Partager sur Facebook
                  • Partager sur Twitter
                    16 novembre 2017 à 8:44:49

                    nekrash a écrit:

                    REGEXP_SUBSTR ne permet de récupérer que le premier enregistrement de la ligne

                    Oui ... Je n'avais pas réfléchi à cela ...

                    nekrash a écrit:

                    J'ai testé de créer directement une table calendrier contenant l'ensemble des jours sur une période donnée, ça reste bourrin comme méthode mais ça fait le taff...

                    C'est vrai que c'est bourrin :D ... En plus le curseur doit durer du coup ...

                    Mais bon c'est juste l'histoire d'une fois, de temps en temps ...

                    Bonne continuation.

                    PS: Tu peux passer le sujet à résolu (bouton en haut à droite du sujet) ;)

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL

                    [ORACLE]Calcul sur dates dans une colonne texte

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown