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 Firebird Discussion :

Sélectionner uniquement des champs numériques


Sujet :

SQL Firebird

  1. #1
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut Sélectionner uniquement des champs numériques
    Bonjour à tous

    Je travaille avec Firebird 2.1. J'ai "hérité" d'une base contenant une table ARTICLE. Cette table contient, entre autres informations, la taille de l'article. Le champ est déclaré Varchar et peut contenir des valeurs numériques (25.5, 140,...) ou alphabétiques (XXL, L,M, ...) ou autres (24M, 25P65 ,....).

    Existe-t-il une fonction ou une séquence de code qui me permettrait dans un select de ne récupérer que les lignes dont le champ TAILLE ne contient que des des valeurs numériques ? Un peu l'équivalent de IsNumeric

    ....et qui ne soit pas une usine à gaz
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 952
    Points
    40 952
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    Il y a SIMILAR TO, un équivalent pauvre des expressions régulières, pour ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT r.CODE_ART,r.TAILLE_LOC
    FROM ART_LOC r
    WHERE R.TAILLE_LOC SIMILAR TO '[0123456789.]*'
    NB. bien sûr on peut réduire en longueur 'fixe' en utilisant SIMILAR TO '[0123456789.]{4}'
    ou 'variable' SIMILAR TO ''[0123456789.]{1,4}'
    et compresser un peu l'expression [0123456789.] = [0-9.] ou encore [[:DIGIT:].]Edit : SIMILAR TO est du Firebird 2.5

    Il doit y avoir moyen en utilisant EXECUTE BLOCK (flamerobin)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SET TERM !;
    EXECUTE BLOCK RETURNS (CODE VARCHAR(6),TAILLE VARCHAR(20)) 
    AS 
    DECLARE VARIABLE N NUMERIC(15,4);
    BEGIN
    FOR SELECT CODE_ART_LOC,TAILLE_LOC FROM ART_LOC INTO :CODE,:TAILLE DO
     BEGIN
      N=CAST(:TAILLE AS NUMERIC(15,4));
      IF (N>0) THEN SUSPEND; 
      WHEN ANY DO N=0;  
     END
    END!
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut
    Heureusement SergioMaster que tu as ajouté le petit edit. J'avais trouvé SIMILAR, mais j'avais aussi trouvé le refus de Firebird 2.1

    Maintenant, j'ai une question toute simple : peut-il y avoir dans la clause when l'appel à une procédure du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    when PROC(a.TAILLE ) = 0
    La procédure PROC testant la zone et renvoyant 0 si la zone ne contient aucun caractère alpha ?
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 952
    Points
    40 952
    Billets dans le blog
    62
    Par défaut
    Je n'ai pas tout compris à cette "proc" mais je dirais non.
    Pour info le EXECUTE BLOCK fonctionnera en 2.1
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  5. #5
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut
    Je pars sur une autre piste : créer un fonction. J'ai trouvé des exemples de création d'une DLL avec Kylix et une avec Windows. En principe, je devrais y arriver, mais j'ai un doute. Voici le code de la fonction que je veux créer et ensuite des explications

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    library DLL;
     
    uses
      SysUtils,
      Classes;
     
    {$R *.res}
     
    function ISALPHA (TAILLE : string) : integer;
    var i : integer;
         x : string;
    begin
      result := 0;
      i := strlen(PChar(TAILLE));
      while (i > 0) do
         begin
            x := substr( TAILLE, i, 1);  <======
            if  ((x >= 'A') and
                (x <= 'Z')) then
               exit;
            if ((x >= 'a') and
                (x <='z')) then
               exit;
            i := i -1;
         end
       result := 1;
    end;
    begin
    end.
    Je me suis inspiré d'un exemple sous windows. Autant strlen() existe en Delphi, autant substr n'existe pas. Cette fonction existe dans un répertoire à moi. Faire la liaison ne me pose pas de problème : un copier coller dans le répertoire de la DLL et un uses bien placé et cela devrait faire, mais puis-je faire cela dans le cas d'une DLL ?
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

  6. #6
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut
    Apparemment, ma question est sans objet, quoique...

    Maintenant j'ai un autre souci : je ne peux pas la tester. En effet, voici un code tout simple mis dans une procédure

    [QUOTE]

    J'ai un beau message

    STRLEN : tocken unknown
    ce qui est incompréhensible, puisque j'ai récupéré strlen par Ctrl+Espace et que j'ai une autre procédure qui l'utilise depuis bientôt dix ans ! Alors lorsque j'utilise isalpha j'ai le même message et je ne peux aller plus loin

    Petite précision : ISALPHA est bien dans la liste des fonctions de ma base
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 245
    Points : 534
    Points
    534
    Par défaut
    Bonjour,

    Citation Envoyé par JP.NUAGE Voir le message
    Il ne manquerait pas la parenthèse de fermeture?
    Copy n'est-il pas équivalent à substring du-moins en ANSI?
    Les fonctions UDF ont pour inconvénient de nécessiter une installation supplémentaire sur chaque serveur d'une version particulière à l'OS de ce serveur. Au moins lorsque le problème est simple, je préfère utiliser une procédure stockée dans la base. Par exemple celle-ci pourrait peut-être répondre à votre problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     SET TERM ^ ;
     
    CREATE or ALTER PROCEDURE ValChamp(Valeur varchar(255)) 
    RETURNS(TypeChamp smallint
     ,ValString varchar(255)
     ,ValFloat double precision)
    AS 
    BEGIN
      begin
        valfloat=cast(trim(replace(valeur,',','.')) as double precision);
        typechamp=2;
        when any do
        begin
          typechamp=1;
          valstring=valeur;    
        end
      end
      suspend;
    END^
     
    SET TERM ; ^
    André

  8. #8
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut
    Dont acte pour la parenthèse, mais la compilation n'était pas arrivée si loin. Dix minutes après avoir posté ma réponse, la compilation a accepté strlen et m'a signalé l'erreur de parenthèse !

    Le problème n'en est pas résolu pour autant. Voici le code de la procédure destinée à tester la fonction que je viens d'installer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    PROCEDURE GENN
    RETURNS (
        J Integer )
    AS
    begin
        j = isalpha('hhhhh');  
       suspend;
    end^
    Pas d'erreur à la compilation, mais lorsque je veux l'enregistrer cela part en boucle, et me plante flamerobin. Je dois forcer l'arrêt. Et derrière, plus de Firebird...enfin si, il est toujours actif, mais inutilisable et je dois "lui taper dessus" pour l'arrêter. Ce n'est qu'après dix tentatives de Stop, qu'enfin il s'arrête et je peux le redémarrer correctement.

    Je dois avoir loupé quelque chose mais ....

    A toutes fins utiles, voici le code de la fonction isalpha et la déclaration pour sa création dans la base.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    library ALPHA;
    uses
      ShareMem,
      SysUtils,
      fonctions,
      Classes;
     
    {$R *.res}
     
    function ISALPHA (TAILLE : string) : integer;  stdcall;
    var i : integer;
        x : string;
    begin
      result := 0;
      i := strlen(PChar(TAILLE));
      while (i > 0) do
         begin
            x := Fonction.substr( TAILLE, i, 1);
            if  ((x >= 'A') and
                (x <= 'Z')) then
               exit;
            if ((x >= 'a') and
                (x <='z')) then
               exit;
            i := i -1;
         end;
       result := 1;
    end;
     
    exports
        iSALPHA;
     
    begin
    end.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DECLARE EXTERNAL FUNCTION ISALPHA
    CSTRING(10)
    RETURNS Integer BY VALUE 
    ENTRY_POINT 'ISALPHA'
    MODULE_NAME 'ALPHA';
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 952
    Points
    40 952
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    il me semble que la fonction isalpha devrait avoir comme argument un PANSICHAR (avec D7 un PChar suffirait) et non un String.


    voici ma proposition (test rapide à contrôler plus en détail)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
       function ContainAlpha(Test : PChar): Integer;
       Var x : Char;
        i : integer;
       begin
       i:=Pred(Strlen(Test));  // pour éviter le #0 de fin de chaine 
       while (i>=0) do
       begin
        x:=Test[i];
        if x in ['a'..'z','A'..'Z'] then
         begin
          Result:=-1;
          exit;
         end;
        Dec(i);
       end;
       Result:=0;
      end;
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  10. #10
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut
    Je n'ai pas pu utiliser la fonction Test : elle ne doit pas être disponible sous Firebird 2.1, mais cela n'est pas important. En revanche, j'ai fais les modification concernant le PChar. J'ai testé dans un petit module Delphi : elle fonctionne parfaitement, mais côté Firebird, j'ai le même blocage lorsque je veux enregistrer GENN (ma procédure de test)
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

  11. #11
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 952
    Points
    40 952
    Billets dans le blog
    62
    Par défaut
    Bonjour
    Citation Envoyé par JP.NUAGE Voir le message
    Je n'ai pas pu utiliser la fonction Test : elle ne doit pas être disponible sous Firebird 2.1, mais cela n'est pas important.
    quelle fonction test ?
    En revanche, j'ai fais les modification concernant le PChar. J'ai testé dans un petit module Delphi : elle fonctionne parfaitement, mais côté Firebird, j'ai le même blocage lorsque je veux enregistrer GENN (ma procédure de test)
    mais pourquoi diable une procédure ? pour tester un simple SELECT F_ISALPHA('H123') from RDB$DATABASEbien sûr il y a deux ou trois petites choses à faire au préalable :
    - avoir mis la dll au bon endroit
    - être sûr qu'il s'agit bien d'une dll de même "poids" que la version de Firebird (Firebird 32bits => dll 32 bits, Firebird 64 => dll 64bits)
    - avoir déclaré l'utilisation de la fonction (declare external, en général je mets un F_ devant pour éviter la confusion avec le nom dans la dll)
    - avoir redémarré le service firebird
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 245
    Points : 534
    Points
    534
    Par défaut
    Bonjour,

    Si l'objet de cette discussion c'est d'apprendre à créer une fonction UDF, vous avez raison de poursuivre sur cette voie, sinon c'est chercher les complications (pour pas dire les emm).
    Pour reprendre la méthode présentée précédemment par Sergio avec execute block, voici un exemple sous FB3.0 utilisant une sous-fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    set term ^;
     
    execute block
    returns(code varchar(6)
    ,taille double precision
    )
    as
    declare function valfloat(valstring varchar(20))
      returns double precision
      as
      begin
        return cast(trim(replace(valstring,',','.')) as double precision);
        when any do begin end
      end
    begin
      for select CODE_ART_LOC,valfloat(TAILLE_LOC)
      from ART_LOC
      where valfloat(TAILLE_LOC) is not null
      into code,taille
      do
      suspend;
    end^
     
    set term ;^
    Comme FB2.1 ne connait ni les sous-fonctions ni les fonctions, il suffit de transformer cette sous-fonction en procédure stockée à appeler dans un select. Plus de problème d'UDF à installer dans la bonne version.

    André

  13. #13
    Membre confirmé
    Avatar de JP.NUAGE
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    769
    Détails du profil
    Informations personnelles :
    Âge : 81
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 769
    Points : 542
    Points
    542
    Par défaut
    C'est vrai que j'aurais pu tester directement par la solution de Sergio_Master, (à condition de connaître cette astuce ) mais j'ai trouvé la solution et la procédure fonctionne (comme le select d'ailleurs), et je sais (enfin je pense savoir) pourquoi il y avait un blocage : j'ai remplacé l'appel de la fonction substr par le code (dans ce cas, très court) de substr. et plus de blocage. c'est ce que dit alanglet
    Et du même coup
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from BASE where isalpha(TAILLE) =1
    tourne comme une horloge !!!

    à tous
    Ce qui se conçoit bien s'énonce clairement
    Et les mots pour le dire viennent aisément (Boileau)

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

Discussions similaires

  1. jQuery sélectionner uniquement des lettres
    Par ceweb dans le forum jQuery
    Réponses: 3
    Dernier message: 23/12/2013, 15h14
  2. Format des champs numériques
    Par Stane dans le forum Forms
    Réponses: 4
    Dernier message: 07/07/2010, 10h54
  3. Longueur réelle des champs numériques
    Par nenekes dans le forum Cobol
    Réponses: 6
    Dernier message: 23/10/2009, 10h53
  4. Réponses: 4
    Dernier message: 20/02/2007, 16h50
  5. PROBLEME : Forcer la saisie des Champs numériques!!!!!
    Par Grozeil dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 31/03/2005, 15h22

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