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 Procédural MySQL Discussion :

Gérer l'erreur "#1406 - Data too long for column" avec un handler


Sujet :

SQL Procédural MySQL

  1. #1
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut Gérer l'erreur "#1406 - Data too long for column" avec un handler
    Bonjour,

    Je souhaite gérer les erreurs renvoyées par MariaDB dans mes procédures. J'y arrive bien avec les erreurs de contraintes (clés étrangères non satisfaites, unicité non respectée) avec ce genre de mécanisme :
    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
    	DECLARE constraint_exception CONDITION FOR SQLSTATE '23000'; -- Erreur de contrainte
    	DECLARE EXIT HANDLER FOR constraint_exception
    		BEGIN
    			GET DIAGNOSTICS @nb_errors = NUMBER;
    			GET DIAGNOSTICS CONDITION @nb_errors
    				@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
     
    			IF LOCATE('fk_tel_id_personne', @text) > 0 THEN 
    				SET @errno = 10019;
    				SET @text = 'Identifiant de la personne inconnu';
    			ELSEIF LOCATE('fk_tel_id_type_telephone', @text) > 0 THEN
    				SET @errno = 10020;
    				SET @text = 'Identifiant du type de numéro de téléphone non valide';
    			ELSEIF LOCATE('xu_tel_numero', @text) > 0 THEN 
    				SET @errno = 10022;
    				SET @text = 'Numéro de téléphone déjà enregistré pour cette personne et de ce type de numéro';
    			END IF;
     
    			SIGNAL SQLSTATE VALUE '23000'
    			SET MYSQL_ERRNO = @errno, MESSAGE_TEXT = @text;
    		END;
    Mais si la donnée, par exemple de type VARCHAR(20), fournie en entrée de ma procédure est trop longue (plus de 20 caractères), j'obtiens une erreur :
    #1406 - Data too long for column 'numero' at row 2
    J'ai essayé d'utiliser le même mécanisme que ci-dessus pour gérer ce cas d'erreur :
    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 too_long_exception CONDITION FOR SQLSTATE '22001'; -- Donnée d'entrée trop longue
    	DECLARE EXIT HANDLER FOR too_long_exception
    		BEGIN
    			GET DIAGNOSTICS @nb_errors = NUMBER;
    			GET DIAGNOSTICS CONDITION @nb_errors
    				@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
     
    			IF LOCATE('numero', @text) > 0 THEN
    				SET @errno = 10021;
    				SET @text = 'Numéro de téléphone trop court ou trop long';
    			END IF;
     
    			SIGNAL SQLSTATE VALUE '22001'
    			SET MYSQL_ERRNO = @errno, MESSAGE_TEXT = @text;
    		END;
    Mais j'obtiens toujours le message d'erreur en anglais de MariaDB plutôt que mon message personnalisé en français.

    Une idée de la cause et d'une solution ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Après investigations...

    L'erreur est provoquée par la valeur STRICT_TRANS_TABLES du paramètre global sql_mode.

    Mais si je retire cette valeur, la donnée d'entrée est tronquée à l'entrée et mon test de détection de trop grande longueur est inopérant ; la donnée est enregistrée tronquée au lieu d'être rejetée par la procédure !

    Il y a une astuce un peu sale : Autoriser en entrée de la procédure une donnée plus longue que la taille de la colonne dans laquelle la donnée sera insérée. La donnée est ainsi tronquée à une longueur qui peut ainsi être filtrée par la procédure.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    IN numero VARCHAR(21), -- par exemple, pour une colonne en VARCHAR(20)
    -- ...
    	-- Vérification du numéro de téléphone
    	IF CHAR_LENGTH(TRIM(numero)) NOT BETWEEN 4 AND 20 THEN -- un numéro plus grand que 20 caractères sera rejeté par la procédure au lieu d'être enregistré tronqué
    		SIGNAL SQLSTATE VALUE '45000'
    		SET MYSQL_ERRNO = 10021, MESSAGE_TEXT = 'Numéro de téléphone trop court ou trop long';
    	END IF;
    Mais bon... je ne trouve pas ça très propre !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 380
    Points : 19 062
    Points
    19 062
    Par défaut
    Salut CinePhil.

    Citation Envoyé par CinePhil
    Une idée de la cause et d'une solution ?
    C'est une histoire d'encapsulation !

    J'ai une procédure stockée (proc) qui va gérer les appels et entre autre, j'appelle une autre procédure stockée (test), celle que je désire tester.

    Le champs d'action d'un handler ne peut se faire qu'après sa declarative.
    Donc, il faut en premier lieu faire la déclarative, puis ensuite l'appel.
    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
    68
    69
    70
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE IF NOT EXISTS `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP PROCEDURE IF EXISTS `test`
    --------------
     
    --------------
    CREATE PROCEDURE `test` (IN _param char(10))
    DETERMINISTIC
    NO SQL
    BEGIN
            select _param as '';
    END
    --------------
     
    --------------
    DROP PROCEDURE IF EXISTS `proc`
    --------------
     
    --------------
    CREATE PROCEDURE `proc` ()
    DETERMINISTIC
    NO SQL
    BEGIN
            DECLARE too_long CONDITION FOR SQLSTATE '22001';
            DECLARE CONTINUE HANDLER FOR too_long BEGIN select "ca fonctionne !"; END;
     
            call `test`('1234567890');
            call `test`('567890123456');
            call `test`('7890123456');
     
    END
    --------------
     
    --------------
    call `proc`()
    --------------
     
    +------------+
    |            |
    +------------+
    | 1234567890 |
    +------------+
    +-----------------+
    | ca fonctionne ! |
    +-----------------+
    | ca fonctionne ! |
    +-----------------+
    +------------+
    |            |
    +------------+
    | 7890123456 |
    +------------+
    --------------
    COMMIT
    --------------
     
    Appuyez sur une touche pour continuer...
    La procédure stockée "test" affiche juste le contenu du paramètre qui est passé. Donc rien de particulier en soi.

    La procédure stockée "proc" va gérer l'appel à la procédure stockée "test". Comment ?
    En faisant une déclarative de HANDLER, juste avant l'appel à la procédure stockée "test.

    J'ai volontairement mis "continue" pour ne pas bloquer les différents appels à la procédure stockée "test".

    Autrement dit, c'est une histoire d'encapsulation.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

Discussions similaires

  1. erreur : Data too long for column
    Par GLSpirit dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 25/10/2007, 15h30
  2. Erreur Data too long For column
    Par fabrice.77 dans le forum Débuter
    Réponses: 12
    Dernier message: 12/02/2007, 09h19
  3. [NWNX ODBC2 plugin] Data too long for column ..
    Par ballestolive dans le forum Débuter
    Réponses: 1
    Dernier message: 31/10/2006, 15h01
  4. ERROR 1406 (22001): Data too long for column
    Par olive_le_malin dans le forum Requêtes
    Réponses: 6
    Dernier message: 12/06/2006, 14h27
  5. "Data truncation: Data too long for column"
    Par bibiloute dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 04/05/2006, 09h08

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