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 :

Procédure dans une requête


Sujet :

SQL Firebird

  1. #1
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut Procédure dans une requête
    Bonjour à tous.
    J'essaye de faire une procédure qui me renvoie une valeur en utilisant EXECUTE STATEMENT.
    Ma proc est:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SET TERM ^ ;
     
    create or alter procedure CalFormula(
    Formula_str varchar(1024))
    returns ( xValue numeric(16,2))
    as
    declare variable SQL varchar(1024);
    begin
    SQL = 'select '||Formula_str||' from Table1 ';
    EXECUTE STATEMENT SQL into :xValue;
      suspend;
    end^
     
    SET TERM ; ^

    sachant que j'ai deux tables


    Table1
    --------------------------
    Field_Name | Field_Value
    --------------------------
    Value1.......|.......50
    Value2.......|.......30
    Value3.......|.......10
    Value4.......|.......70


    Table2
    ----------------------------------------------
    Formula_Name | Formula_Value
    ----------------------------------------------
    Formula1 .......|.......Value1*2
    Formula2 .......|.......Value2*Value1/10
    Formula3 .......|.......Value3*Value2/Value1
    Formula4 .......|.......Value14/Value3


    L'utilisateur peut ajouter d'autres formules.


    J'ai essaye le test dans une requete,quand j'utilise un parametre predifinie comme:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select 
    Formula_Name,
    xValue
    from Table2, CalFormula ('Value1*2')

    sa marche tres bien,


    mais quand j'ai essaye d'execute la requete suivante j'obtiens un message d'erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select 
    Formula_Name,
    xValue
    from Table2, CalFormula (Table2.Formula_Value)

  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 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je ne comprend pas trop la logique, pour des formules complexe j'ai pris l'habitude d'utiliser une UDF http://rfunc.sourceforge.net/

    J'ai essaye le test dans une requête,quand j'utilise un paramètre prédéfini CalFormula ('Value1*2')
    ça marche très bien,
    pas chez moi, à la rigueur CalFormula('50*2') oui

    j'ai créé les tables et mis des données, puis enregistré la procédure et chez moi aucune des requêtes ne fonctionne
    et cela me semble logique d'ailleurs
    - Value1 est un texte pas une valeur
    pour obtenir la valeur de Value1 il faudrait écrire SELECT FIELD_VALUE FROM TABLE1 WHERE FIELD_NAME='Value1'
    pour la procédure on est loin du compte !

    à la rigueur on pourrait peut être utiliser la fonction REPLACE de Firebird pour transformer les formules de la manière suivante

    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
    SET TERM ^ ;
    ALTER PROCEDURE CALFORMULA (
        FORMULA_STR Varchar(1024) )
    RETURNS (
        xvalue numeric(16,2)
    AS
    declare variable SQL varchar(1024);
    declare variable    NAME Varchar(20),
    declare variable    VALEUR Numeric(16,2),
    begin
    -- remplacement des noms dans la formule
    FOR SELECT FIELD_NAME,FIELD_VALUE FROM TABLE1 INTO :Name,:Valeur
      DO   FORMULA_STR=REPLACE(FORMULA_STR,:NAME,:VALEUR);
     
     SQL='SELECT CAST('|| ||' AS NUMERIC(16,2)) FROM RDB$DATABASE';
    EXECUTE STATEMENT SQL into :xValue;
     suspend;
    end^
    SET TERM ; ^
    Testé par bout et non en globalité, faute de la description exacte des tables Table1 et Table2 ce n'est qu'une approximation

    et ATTENTION à la CASSE des valeurs FIELD_NAME dans les formules

    on peut ensuite facilement faire la requête suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select 
    Formula_Name,
    (SELECT XVALUE FROM CalFormula (Formula_Value)) 
    from Table2
    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
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    Merci a votre réponse;

    J'ai essaye avec des amis dans un autre forum de complexe les choses et en même temps trouver une solution efficace;
    voici les étapes:

    1/ les tables

    Table1
    --------------------------
    Field_Name | Field_Value
    --------------------------
    Value1.......|.......50
    Value2.......|.......30
    Value3.......|.......10
    Value4.......|.......70

    Table2
    ----------------------------------------------
    Formula_Name | Formula_Value
    ----------------------------------------------
    Formula1 .......|.......Value1*2
    Formula2 .......|.......Formula1*Value1/10 ....... // (Formula1 resultat de Value1*2)
    Formula3 .......|.......Formula2*Value2/Value1 .......// (Formula2 resultat def Formula1*Value1/10)
    Formula4 .......|.......Formula3*Formula2/Value3 .......// (Formula3 resultat de Formula2*Value2/Value1)


    on a créer une procédure qui marche très bien

    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
    35
    36
    37
    38
    39
    40
    SET TERM ^ ;
     
    create or alter procedure NEW_PROCEDURE
    returns (
        VALUE1 numeric(15,2),
        SQL varchar(400))
    as
    declare variable FIELD_NAME1 varchar(100);
    declare variable FIELD_VALUE1 varchar(100);
    declare variable FORMULA_VALUE1 varchar(400);
    declare variable FORMULA_NAME1 varchar(100);
    declare variable FORMULA_VALUE2 varchar(400);
    declare variable FORMULA_NAME2 varchar(400);
    begin
    for select Formula_Name, Formula_Value FROM Table2 into :Formula_Name1, :Formula_Value1 do
    Begin
    while ((select Out_field from check_field(:Formula_Value1)) =1) do
    begin
    For select Formula_Name, Formula_Value FROM Table2
    Where (position(Formula_name, :Formula_Value1) > 0)
    into :Formula_Name2, :Formula_Value2 do
    begin
    formula_value1 = replace(:Formula_Value1, :Formula_Name2, '('||cast(:Formula_Value2 as varchar(40))||')');
    end
     
    For select Field_Name, Field_Value from table1
    Where (position(Field_name, :Formula_Value1) > 0)
    into :Field_Name1, :Field_Value1 do
    begin
    formula_value1 = replace(:Formula_Value1, :Field_Name1, '('||cast(:Field_Value1 as varchar(40))||')');
    end
    end
    sql =  'SELECT ' || :Formula_Value1 || ' from RDB$DATABASE' ;
    execute statement sql into :value1;
    end
      suspend;
    end
    ^
     
    SET TERM ; ^
    la procédure CHECK_FIELD qui permet d’assurée qu'il y a pas un champ référencé a un autre champ
    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
     
    SET TERM ^ ;
     
    create or alter procedure CHECK_FIELD (
        IN_FIELD varchar(400))
    returns (
        OUT_FIELD numeric(1,0))
    as
    declare variable I integer;
    BEGIN
      In_Field = UPPER(In_Field);
      Out_Field =0;
      i=65; -- A
      while (i <91 ) do -- to Z
      begin
        if (In_Field containing ASCII_CHAR(i)) then
        begin
         Out_field = 1;
         break;
         end
       i = i + 1;
      end
      SUSPEND;
    END
    ^
     
    SET TERM ; ^

    mais il y a des observations :

    1- Quand on exécute la procédure ou en l'appel dans SQL nous donne une seule lignes (dernier ligne);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select
        new_procedure.value1,
        new_procedure.sql
    FROM new_procedure

    2- et quand en ajoute un paramètre d’Entrée la procédure ne marche pas et affiche une erreur;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select 
        new_procedure.value1,
        new_procedure.sql,
        table2.formula_name,
        table2.formula_value
    from table2, new_procedure(table2.formula_name)
    erreur evec IbExpert
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Error Message:
    ----------------------------------------
    Unsuccessful execution caused by a system error that precludes successful execution of subsequent statements.
    Dynamic SQL Error.
    Input parameter mismatch for procedure NEW_PROCEDURE_PARAM.
    Erreur avec FlameRobin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SQL Message: -508
    The cursor identified in the UPDATE or DELETE statement is not positioned on a row.
    Engine Code : 335544348
    Engine Message: no current record for fetch operation
    la procédure a été modifier:
    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
    begin
    select Formula_Name, Formula_Value FROM Table2 where Formula_Name= :Input_param into :Formula_Name1, :Formula_Value1 ;
    Begin
    while ((select Out_field from check_field(:Formula_Value1)) =1) do
    begin
    For select Formula_Name, Formula_Value FROM Table2
    Where (position(Formula_name, :Formula_Value1) > 0)
    into :Formula_Name2, :Formula_Value2 do
    begin
    formula_value1 = replace(:Formula_Value1, :Formula_Name2, '('||cast(:Formula_Value2 as varchar(40))||')');
    end
     
    For select Field_Name, Field_Value from table1
    Where (position(Field_name, :Formula_Value1) > 0)
    into :Field_Name1, :Field_Value1 do
    begin
    formula_value1 = replace(:Formula_Value1, :Field_Name1, '('||cast(:Field_Value1 as varchar(40))||')');
    end
    end
    sql =  'SELECT ' || :Formula_Value1 || ' from table2' ;
    execute statement sql into :value1;
    end
      suspend;
    end
    fichier de la base de donnée est jointe pour la tester
    Fichiers attachés Fichiers attachés

  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 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    ça pour complexifier, c'est sur vous complexifiez ! des formules dans les formules il fallait oser !
    j'ai remarquer que finalement vous utiliser le REPLACE, mais je remarque que votre expression SQL reste sur une table alors que RDB$DATABASE est tout aussi efficace

    pour ce qui est de cette formulation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select 
        new_procedure.value1,
        new_procedure.sql,
        table2.formula_name,
        table2.formula_value
    from table2, new_procedure(table2.formula_name)
    j'ai horreur de ce type de jointure non définie et non normalisée. Si vous aviez utiliser la normalisation vous auriez vite compris que le problème vient de l'absence d'expression de jointure
    ... from table2 JOIN new_procedure(table2.formula_name) ON ????et que donc il manquerait en sortie une valeur égale par exemple au nom_formule (égal au paramètre d'entrée) pour faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT p.Value1,p.SQL,t.Formula_Name,t.Formula_value 
    FROM table2 t join new_procedure(t.formula_name) p on t.Formula_Name=p.nom_formule
    pour ce qui est de gérer les formules dans des formules j'utiliserai SIMILAR TO
    avec l'expression égale à SELECT LIST(FORMULA_NAME,'|') FROM TABLE2 pour tester si j'ai encore des formules dans l'expression


    Quelque chose comme ça (que je n'ai pas encore pris la peine de tester)
    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
     
    declare variable regex  VARCHAR(1000) ; // limite le nombre de formules 
    declare variable FNOM VARCHAR(50);
    declare variable VNOM VARCHAR(50);
    declare variable FVALEUR VARCHAR(150);
    declare variable VALEUR  NUMERIC(15,2);
    ...
    SELECT LIST(FORMULA_NAME,'|') FROM TABLE 2 INTO :regex;
    WHILE (FORMULA_STR SIMILAR TO :REGEX)  DO
      BEGIN
          FOR SELECT FORMULA_NAME, FORMULA_VALUE FROM TABLE2 INTO :FNOM,:FVALEUR DO
               FORMULA_STR=REPLACE(FORMULA_STR,:FNOM,:FVALEUR); 
      END
    FOR SELECT FIELD_NAME, FIELD_VALUE FROM TABLE1  INTO :VNOM,:VALEUR DO
       FORMULA_STR=REPLACE(FORMULA_STR,:VNOM,:VALEUR);
    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
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    Bonjour, et Merci de votre réponse.

    Citation Envoyé par SergioMaster Voir le message

    j'ai horreur de ce type de jointure non définie et non normalisée. Si vous aviez utiliser la normalisation vous auriez vite compris que le problème vient de l'absence d'expression de jointure
    ... from table2 JOIN new_procedure(table2.formula_name) ON ????et que donc il manquerait en sortie une valeur égale par exemple au nom_formule (égal au paramètre d'entrée) pour faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT p.Value1,p.SQL,t.Formula_Name,t.Formula_value 
    FROM table2 t join new_procedure(t.formula_name) p on t.Formula_Name=p.nom_formule
    J'ai fait quelque modification en ajoutant un paramètre de sortie, mais toujours il me renvoi le dernier ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select 
        new_procedure_param.value1,
        new_procedure_param.sql,
        table2.formula_name,
        table2.formula_value
    from table2
     join new_procedure_param(table2.formula_name) on (table2.formula_name = new_procedure_param.output_param)

    pour ce qui est de gérer les formules dans des formules j'utiliserai SIMILAR TO
    avec l'expression égale à SELECT LIST(FORMULA_NAME,'|') FROM TABLE2 pour tester si j'ai encore des formules dans l'expression
    ça marche pas a cause de SIMILAR TO

    Exp:
    'Formula1' SIMILAR TO 'Formula1|Formula2|Formula3|Formula4|' ------ Vrais
    'Formula1*50' SIMILAR TO 'Formula1|Formula2|Formula3|Formula4|' ------ Faux

  6. #6
    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 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je n'avais pas encore testé, il est vrai que l'expression régulière est (pour l'instant) fausse, je planche dessus et viens à l'instant de trouver

    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
     
    -- procédure permettant de parser une formule en montrant les étapes
    SET TERM ^ ;
    CREATE PROCEDURE PARSE_FORMULA (
        FORMULE_STR Varchar(1024) )
    RETURNS (
        FORMULE Varchar(2048) )
    AS
    declare variable regex varchar(1024);
    declare variable fnom varchar(50);
    declare variable fvaleur varchar(150);
    BEGIN
      SELECT LIST(FORMULA_NAME||'_*','|') FROM TABLE2 INTO :REGEX;
      FORMULE=:REGEX;
      SUSPEND;
      WHILE (FORMULE_STR SIMILAR TO :REGEX) DO
        BEGIN
           FOR SELECT FORMULA_NAME,FORMULA_VALUE
                 FROM TABLE2 INTO :FNOM,:FVALEUR DO
              FORMULE_STR=REPLACE(FORMULE_STR,:FNOM,:FVALEUR);
           FORMULE=FORMULE_STR;
           SUSPEND;
        END
     
    END^
    SET TERM ; ^
    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

  7. #7
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Bonjour,

    je n'avais pas encore tester, il est vrai que l'expression régulière est (pour l'instant) fausse, je planche dessus et viens à l'instant de trouver
    WooW, sa marche très bien.

    Je teste la jointure et je vous rapelle

  8. #8
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    A ce que est intéresse a ce sujet

    La procedure en état finale
    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
    begin
    FOR SELECT FORMULA_NAME
                 FROM TABLE2 INTO :formule_str DO
    BEGIN
      SELECT LIST(FORMULA_NAME||'_*','|') FROM TABLE2 INTO :REGEX;
      FORMULE=:REGEX;
      sql = :formule_str;
      WHILE (FORMULE_STR SIMILAR TO :REGEX) DO
        BEGIN
           FOR SELECT FORMULA_NAME,FORMULA_VALUE
                 FROM TABLE2 INTO :FNOM,:FVALEUR DO
              FORMULE_STR=REPLACE(FORMULE_STR,:FNOM,:FVALEUR);
        END
      SELECT LIST(FIELD_NAME||'_*','|') FROM TABLE1 INTO :REGEX;
      FORMULE=:REGEX;
      WHILE (FORMULE_STR SIMILAR TO :REGEX) DO
        BEGIN
           FOR SELECT FIELD_NAME,FIELD_VALUE
                 FROM TABLE1 INTO :FNOM,:FVALEUR DO
              FORMULE_STR=REPLACE(FORMULE_STR,:FNOM,'('||:FVALEUR||')');
        END
      FORMULE='select '||formule_str||' from rdb$database';
      execute statement formule into :valeur;
      formule = :sql;
      suspend;
      end
    END

    Et la jointure qui rende la liste des champs et les valeurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select 
        table2.formula_name,
        table2.formula_value,
        parse_formula.valeur
    from table2
    join parse_formula on (table2.formula_name = parse_formula.formule)

    Merci infiniment au SergioMaster .

  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 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par BESTWAIL Voir le message
    A ceux intéressés par ce sujet
    La procédure dans son état final
    AMHA , il y a beaucoup de déchet encore dans cette procédure !
    et tant qu'à faire il aurait fallu en écrire la totalité (partie CREATE/ALTER , plus les variables déclarées)

    Ayant donné les directions je m'attendais à quelque chose de plus abouti !

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    /******************* PROCEDURES ******************/
     
    SET TERM ^ ;
    CREATE PROCEDURE SERGIOMASTERPROC (
        FORMULE Varchar(50) )
    RETURNS (
        VALEUR Numeric(15,2) )
    AS
    BEGIN SUSPEND; END^
    SET TERM ; ^
     
    /******************** TABLES **********************/
     
    CREATE TABLE VALEURS
    (
      FIELD_NAME Varchar(50) NOT NULL,
      FIELD_VALUE Numeric(15,2),
      CONSTRAINT PK_TABLE1_1 PRIMARY KEY (FIELD_NAME)
    );
    CREATE TABLE FORMULES
    (
      FORMULA_NAME Varchar(50) NOT NULL,
      FORMULA_VALUE Varchar(150),
      CONSTRAINT PK_TABLE2_1 PRIMARY KEY (FORMULA_NAME)
    );
    COMMIT;
    INSERT INTO VALEURS (FIELD_NAME, FIELD_VALUE) VALUES ('Value1', '50.00');
    INSERT INTO VALEURS (FIELD_NAME, FIELD_VALUE) VALUES ('Value2', '30.00');
    INSERT INTO VALEURS (FIELD_NAME, FIELD_VALUE) VALUES ('Value3', '10.00');
    INSERT INTO VALEURS (FIELD_NAME, FIELD_VALUE) VALUES ('Value4', '70.00');
    COMMIT;
    INSERT INTO FORMULES (FORMULA_NAME, FORMULA_VALUE) VALUES ('Formula1', 'Value1*2');
    INSERT INTO FORMULES (FORMULA_NAME, FORMULA_VALUE) VALUES ('Formula2', 'Formula1*Value1/10');
    INSERT INTO FORMULES (FORMULA_NAME, FORMULA_VALUE) VALUES ('Formula3', 'Formula2*Value2/Value1');
    INSERT INTO FORMULES (FORMULA_NAME, FORMULA_VALUE) VALUES ('Formula4', 'Formula3*Formula2/Value3');
    COMMIT;
     
    SET TERM ^ ;
    ALTER PROCEDURE SERGIOMASTERPROC (
        FORMULE Varchar(50) )
    RETURNS (
        VALEUR Numeric(15,2) )
    AS
    declare variable REGEX VARCHAR(1000) ; 
    declare variable FORMULE_STR VARCHAR(2048);  
    declare variable FNOM VARCHAR(50);          
    declare variable VNOM VARCHAR(50);
    declare variable FVALEUR VARCHAR(150);
    declare variable VVALEUR  NUMERIC(15,2);
    declare variable SQLSTMT VARCHAR(2048);  
    BEGIN
       FORMULE_STR=:FORMULE; 
       SELECT LIST(FORMULA_NAME||'_*','|') FROM FORMULES INTO :REGEX; -- Table des formules
       WHILE (FORMULE_STR SIMILAR TO :REGEX) DO
        BEGIN
           FOR SELECT FORMULA_NAME,FORMULA_VALUE
                 FROM FORMULES INTO :FNOM,:FVALEUR DO
              FORMULE_STR=REPLACE(FORMULE_STR,:FNOM,:FVALEUR);
        END
       FOR SELECT FIELD_NAME,FIELD_VALUE FROM VALEURS INTO :VNOM,:VVALEUR DO    -- Table des Valeurs
                  FORMULE_STR=REPLACE(FORMULE_STR,:VNOM,:VVALEUR);    
       SQLSTMT='SELECT CAST('||FORMULE_STR||' AS NUMERIC(15,2)) FROM RDB$DATABASE';
       EXECUTE STATEMENT SQLSTMT INTO :valeur;
       SUSPEND;
    END^
    SET TERM ; ^
    avec cette requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT 
     T.FORMULA_NAME,
     T.FORMULA_VALUE,
     (SELECT VALEUR FROM SERGIOMASTERPROC(T.FORMULA_NAME)) AS VALEUR 
    FROM FORMULES T
    on obtiendra
    Formula1 Value1*2 100.00
    Formula2 Formula1*Value1/10 500.00
    Formula3 Formula2*Value2/Value1 300.00
    Formula4 Formula3*Formula2/Value3 15000.00
    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
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Bonjour,


    AMHA , il y a beaucoup de déchet encore dans cette procédure !
    et tant qu'à faire il aurait fallu en écrire la totalité (partie CREATE/ALTER , plus les variables déclarées)

    Ayant donné les directions je m'attendais à quelque chose de plus abouti !
    Nom : 47211821_1249589988_02.gif
Affichages : 313
Taille : 15,0 Ko Nom : best20smiley.gif
Affichages : 1842
Taille : 41,9 Ko

  11. #11
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    SergioMaster j'ai une petite observation qui concerne SIMILAR TO

    'Formula2*Value2/Value1' SIMILAR TO :REGEX ----------> vrais
    'Value2*Formula2/Value1' SIMILAR TO :REGEX ----------> faux

    Sa cause un erreur dans la procedure

    Merci.

  12. #12
    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 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonsoir,

    'Value2*Formula2/Value1' SIMILAR TO :REGEX ->Faux
    cas intéressant,
    peut être faut-il modifier le regex ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT LIST('_*'||FORMULA_NAME||'_*','|') FROM TABLE2 INTO :REGEX;
    mais je n'ai pas le temps de vérifier, du moins pas avant l'année prochaine

    Bonne fêtes de fin d'année
    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

  13. #13
    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 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je reviens avec cette nouvelle écriture de PARSE_FORMULA

    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
    SET TERM ^ ;
    ALTER PROCEDURE PARSE_FORMULA (
        FORMULE_STR Varchar(1024) )
    RETURNS (
        FORMULE Varchar(2048) )
    AS
    declare variable regex varchar(1024);
    declare variable fnom varchar(50);
    declare variable fvaleur varchar(150);
    BEGIN
      SELECT LIST('_*'||FORMULA_NAME||'_*','|') FROM TABLE2 INTO :REGEX;
      FORMULE=:REGEX;
      WHILE (FORMULE_STR SIMILAR TO :REGEX) DO
        BEGIN
           FOR SELECT FORMULA_NAME,FORMULA_VALUE
                 FROM TABLE2 INTO :FNOM,:FVALEUR DO
              FORMULE_STR=REPLACE(FORMULE_STR,:FNOM,'('||:FVALEUR||')');
           FORMULE=FORMULE_STR;
           SUSPEND;
        END
     
    END^
    SET TERM ; ^
    à noter le changement dans LIST pour créer l'expression régulière, mais aussi l'utilisation des '(' ')' pour remplacer le nom de la formule par sa valeur
    une correction identique serait à appliquer sur la procédure SERGIOMASTERPROC que j'ai proposé
    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

  14. #14
    Nouveau membre du Club
    Profil pro
    Developper
    Inscrit en
    Juillet 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juillet 2007
    Messages : 19
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Bonjour,

    je reviens avec cette nouvelle écriture de PARSE_FORMULA

    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
    SET TERM ^ ;
    ALTER PROCEDURE PARSE_FORMULA (
        FORMULE_STR Varchar(1024) )
    RETURNS (
        FORMULE Varchar(2048) )
    AS
    declare variable regex varchar(1024);
    declare variable fnom varchar(50);
    declare variable fvaleur varchar(150);
    BEGIN
      SELECT LIST('_*'||FORMULA_NAME||'_*','|') FROM TABLE2 INTO :REGEX;
      FORMULE=:REGEX;
      WHILE (FORMULE_STR SIMILAR TO :REGEX) DO
        BEGIN
           FOR SELECT FORMULA_NAME,FORMULA_VALUE
                 FROM TABLE2 INTO :FNOM,:FVALEUR DO
              FORMULE_STR=REPLACE(FORMULE_STR,:FNOM,'('||:FVALEUR||')');
           FORMULE=FORMULE_STR;
           SUSPEND;
        END
     
    END^
    SET TERM ; ^
    à noter le changement dans LIST pour créer l'expression régulière, mais aussi l'utilisation des '(' ')' pour remplacer le nom de la formule par sa valeur
    une correction identique serait à appliquer sur la procédure SERGIOMASTERPROC que j'ai proposé
    Merci, j'ai déjà corrigé, et ajouté les parenthèses.

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

Discussions similaires

  1. [WD15] Procédure dans une requête
    Par kinansoag dans le forum WinDev
    Réponses: 4
    Dernier message: 13/01/2015, 13h08
  2. Réponses: 2
    Dernier message: 08/02/2013, 12h10
  3. Réponses: 2
    Dernier message: 21/12/2012, 13h14
  4. utiliser une procédure stockées dans une requête SQL
    Par Issam dans le forum Développement
    Réponses: 3
    Dernier message: 21/11/2011, 10h18
  5. Appeler une procédure dans une requête
    Par gold15 dans le forum PL/SQL
    Réponses: 4
    Dernier message: 13/01/2009, 14h08

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