SQL procédural : traiter les conditionnelles

Résolu/Fermé
arscy - 12 oct. 2022 à 22:57
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 - 16 oct. 2022 à 00:26

Bonsoir cher(e)s adeptes du numérique,

Je fais mes premiers pas dans le SQL procédural et me confronte notamment à la finesse syntaxique de ce langage (c'est si joliment dit...).
Je suis en train de tourner en rond avec une séquence d'erreur identifiée dans mon code, mais je ne saisis pas ce qui pose problème dans la séquence.
 

DROP FUNCTION IF EXISTS calc_age;
DELIMITER //
CREATE FUNCTION calc_age(ddn DATE) RETURNS INT
BEGIN
    DECLARE AGE INT DEFAULT 0;
    DECLARE MONTHDIFF INT DEFAULT 0;
    DECLARE DAYSDIFF INT DEFAULT 0;
    
    SET AGE:=(SELECT YEAR(CURDATE()) - YEAR(ddn));
    SET MONTHDIFF:=(SELECT MONTH(CURDATE()) - MONTH(ddn));
    SET DAYSDIFF:=(SELECT DAY(CURDATE())-DAY(ddn));
    
    IF (SELECT MONTH(CURDATE()) - MONTH(ddn)) > 0 THEN
        SET AGE:=(AGE-1);
        RETURN AGE;
    ELSE IF MONTHDIFF=0 AND DAYSDIFF>0 THEN
        SET AGE:=(AGE-1);
        RETURN AGE;
            ELSE
        RETURN AGE;
    END IF;
END ;
//
DELIMITER ;

Ce que j'ai fait : à la base j'avais tout chargé dans mes conditionnelles, mais à force de garder le nez dans le bitume j'ai défini des variables pour pouvoir aérer un peu tout ça. J'ai pu corriger quelques horreurs, mais il en reste toujours.
PhpMyAdmin considère mes variables légales testées isolément, mais la fonction entière coince sur une "erreur de syntaxe ligne 20".
Comme je respecte les espaces je suppose que le souci se trouve ailleurs et ne parvient pas à être identifié par l'application.

J'ai amputé la fonction de la section "ELSE IF" et phpMyAdmin valide la requête. Donc le souci se trouve là, mais je ne n'arrive pas à l'identifier. Je présume que c'est la formulation de ma conditionnelle qui n'est pas légale?

Sauriez-vous m'éclairer s'il vous plaît?
De plus, auriez-vous des suggestions sur les petits "plus" qui permettent d'avoir un code propre et de limiter les erreurs de syntaxe avec ce langage?
Merci d'avance pour vos lumières!

A voir également:

3 réponses

yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 506
14 oct. 2022 à 18:11

bonjour,

Peut-être est-il nécessaire d'avoir un "end if" correspondant à chaque "if"?

Tu ne nous montres pas ce que tu as essayé et qui fonctionne.  "amputé la fonction de la section", c'est très peu précis.

Bonsoir,

Merci pour la suggestion, malheureusement un tuto 'spécial nul' me dit que ce n'est pas le cas.

Je viens de résoudre ma problématique via ce même tuto à l'instant d'ailleurs.

En cause : attention, en SQL PSL c'est un 'ELSEIF'. Saloperie de syntaxe.
Voici le code fonctionnel en corrigé, avec la correction de bourdes sur la logique de mes conditionnelles _ format à graver dans du marbre :

 

#DROP FUNCTION IF EXISTS calc_age;
DELIMITER //
CREATE FUNCTION calc_age(ddn DATE) RETURNS INT
BEGIN
    DECLARE AGE INT DEFAULT 0;
    DECLARE MONTHDIFF INT DEFAULT 0;
    DECLARE DAYSDIFF INT DEFAULT 0;
    
    SET AGE:=(SELECT YEAR(CURDATE()) - YEAR(ddn));
    SET MONTHDIFF:=(MONTH(ddn) - SELECT MONTH(CURDATE()) );
    SET DAYSDIFF:=(SELECT DAY(ddn) - DAY(CURDATE()) );
    
    IF (SELECT MONTH(ddn) - MONTH(CURDATE()) ) > 0 THEN
        SET AGE:=(AGE-1);
        RETURN AGE;
    ELSEIF MONTHDIFF=0 AND DAYSDIFF>0 THEN
        SET AGE:=(AGE-1);
        RETURN AGE;
	ELSE
        RETURN AGE;
    END IF;
END ;
//
DELIMITER ;

Merci pour ton temps!

yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 506
15 oct. 2022 à 09:30

S'agit-il de PL/SQL, donc rien à voir avec MySQL?

Tu as maintenant un "end if" correspondant à chaque "if"!

Je pensais que tu voulais imbriquer des IF, ce qui est légal en PL/SQL.

0
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 9
15 oct. 2022 à 12:50

Il s'agit bien de PL/SQL aka SQL procédural oui,
Je viens de comprendre ton allusion à du IF qui n'aurait pas son END IF : le ELSE du post initial s'était perdu en matière d'indentation.
Par contre la dernière version de fonction postée pourrait être optimisée en enlevant le ELSE et tous les RETURN, puis en plaçant un RETURN AGE juste après le END IF.

Il me reste 2 points techniques sur les conventions :
[1]  Faut-il forcément un DECLARE par variable? (on ne peut pas faire de DECLARE varA typeA, varB type B etc?)
[2] toute manipulation de variable doit-elle forcément être précédée d'un SET (après initialisation?)
--> sur le tuto que j'ai consulté j'ai trouvé des écritures que je n'ai pas réussi à  appliquer (signalées comme erreurs)

yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 506
15 oct. 2022 à 13:01

Tu trouveras ici des exemples d'utilisation de DECLARE: http://sql.bdpedia.fr/plsql.html

Il n'est pas toujours nécessaire d'utiliser SET.

1
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 9 > yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024
15 oct. 2022 à 23:30

Et bien c'est assez perturbant, mais actuellement,
sur phpMyAdmin v5.1.3 avec MariaDB v10.5.12,

Je ne peux réaliser mes DECLARE en amont de mes BEGIN,
et mes changements de valeurs de variables semblent devoir être précédées d'un SET :-(
Ma structure-type de fonction doit donc répondre à ce schéma:
CREATE FUNCTION ...
BEGIN
   DECLARE mes variables,
   mes opérations, avec un SET devant toute variable qui serait actualisée

END ;

Contrairement à ce que j'ai pu lire à propos de ce qui est légal comme opération, où il était proposé un
CREATE FUNCTION...
DECLARE les variables (avec 1 seul déclare pour n variables //ça ne passe pas chez moi :-(
BEGIN
   opérations
END ;

0
yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 506 > arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023
16 oct. 2022 à 00:15

MariaDB ne supporte qu'une partie de la syntaxe PL/SQL.

0
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 9 > yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024
16 oct. 2022 à 00:26

Maria est une ingrate.

Effectivement, j'ai remarqué que certaines manipulations ne passaient pas (ex: concaténation via || parmi tout le reste déjà décrit...).
Merci pour ton temps!

0