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

Développement SQL Server Discussion :

Gestion des erreurs de conversion de type de données


Sujet :

Développement SQL Server

  1. #1
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 356
    Points
    356
    Par défaut Gestion des erreurs de conversion de type de données
    [Le problème est résolu par une bidouille propre à mon cas de figure
    Mais la question de fond reste entière ......
    ]


    Bonjour,

    Je patine sur un problème d'apparence balotte, sans trouver dans la littérature de solution adéquate.

    Je suis en train de gratter une fonction qui a pour objectif de vérifier le formattage d'un champ. Celui-ci, de type CHAR() est normalement composé d'un ensemble bien codifié de séquences de lettres et de nombres, le tout séparé par des caractères spéciaux bien définis.

    Pas de pb pour récupérer individuellement chaque élément de la chaîne.

    Pas de pb non plus pour vérifier la présence la taille et le bon positionnement des séquences de lettres et des caractères spéciaux.

    Par contre, comment puis-je vérifier vérifier les nombres ? Je ne sais pas à l'avance si au lieu d'un nombre, c'est une chaîne de caractères qui par erreur ait été saisi. Et dans ce cas, si j'utilise un CAST( .... as FLOAT), je génère une erreur qui arrête l'exécution. Et comme il ni a pas de fonction système de type ISERROR() .....et que le @@ERROR ne fonctionne que pour des erreurs dans des requêtes, .... je sais pas trop comment gérer ce cas de figure


    L'une des solutions serait de passer par des RegEx mais comme la base est sous SQL 2000, faudrait passer par la librairie VBScript.RegExp ce qui pourrait poser ultérieurement des problèmes de compatibilité ascendante.

    Je précise d'avance que bien évidemment, je ne peux pas toucher à la structure de la base et que je n'ai pas la main sur la GUI de l'application (donc je ne peux faire la vérif lors de la saisie).

    Merci d'avance pour votre aide.

  2. #2
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Vous pouvez poser une contrainte de domaine sur la colonne concernée avec une fonction.
    Par exemple pour vérifier un numéro de téléphone français :

    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
    CREATE FUNCTION Fn_VerifieNumTel (@numTel VARCHAR(20))
    	RETURNS BIT
    	WITH SCHEMABINDING
    AS
    BEGIN
    	DECLARE @numTelOK BIT
    	SET @numTelOK = 0
     
    	IF @numTel LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
    	BEGIN
    		SET @numTelOK = 1
    	END
     
    	RETURN @numTelOK
    END
    à partir de là, nous pouvons créer la table suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE TbClient
    (
    	IDClient INT NOT NULL IDENTITY CONSTRAINT PK_TbClient PRIMARY KEY,
    	nomClient VARCHAR(20) NOT NULL,
    	prenomClient VARCHAR(20) NOT NULL,
    	CONSTRAINT UQ_TbClient_nomClient_prenomClient UNIQUE (nomClient, prenomClient),
    	numTelClient VARCHAR(10) NOT NULL CONSTRAINT CHK_TbClient_numTelClient CHECK(dbo.Fn_VerifieNumTel(numTelClient) = 1)
    )
    Si nous exécutons :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO dbo.TbClient VALUES ('Suket', 'El', '061234567')
    Nous obtenons l'erreur suivante :

    Msg*547, Niveau*16, État*0, Ligne*1
    L'instruction INSERT est en conflit avec la contrainte CHECK "CHK_TbClient_numTelClient". Le conflit s'est produit dans la base de données "ELSUKET", table "dbo.TbClient", column 'numTelClient'.
    L'instruction a été arrêtée.
    Et aucune ligne n'est insérée dans la table TbClient.

    Et si nous exécutons :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO dbo.TbClient VALUES ('Suket', 'El', '0612345678')
    La ligne est insérée dans la table

    Dès lors si vous tentez d'insérer un nouveau client avec une procédure stockée et avec un numéro de téléphone qui ne vérifie pas la contrainte CHK_TbClient_numTelClient, vous obtiendrez l'erreur 2627, qui annulera donc la transaction.
    L'erreur est retournée à l'applicatif

    @++

  3. #3
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 356
    Points
    356
    Par défaut
    Salut Elsuket

    Merci pour ta réponse.

    En fait tu me proposes de déplacer la vérification d'un CAST vers un INSERT où là l'erreur sera bien gérée. OK pour la gestion de l'erreur.

    Par contre, je ne sais toujours pas comment vérifier ma séquence alphanumérique avec un LIKE. Je m'explique

    Soit le formatage suivant d'un champ de type CHAR(10) :
    > Il est composé de séquences de 5 lettres suivies d'un '#' suivi d'un chiffre
    > Ces séquences sont elles-même séparées par un ';'

    Exemple 1 : 'IUYZK#1;kdbcj#0.12;pdsJS#678.33'
    Les 3 séquences respectent bien le formalisme
    'IUYZK#1'
    'kdbcj#0.12'
    'pdsJS#678.33'
    Exemple 2 : 'IUYZK#1;kdbcj#0.12;pdsJS#678.3j3'
    La dernière séquence ('pdsJS#678.3j3') ne respecte pas le formalisme (à cause d'un j s'est glissé dans le nombre)

    Avec des PATINDEX et des SUBSTRING, je sais isoler chaque séquence.

    Le LIKE me permet bien de vérifier les 6 premiers caractères (position fixe)

    Par contre, le LIKE n'est pas une fonction d'expressions régulières suffisamment puissante pour me permettre d'analyser la partie chiffrée

    Ou alors, un peu bourrinement, je vérifie toutes les combinaisons possibles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    LIKE '[0-9]'
    OR LIKE '[0-9][0-9]'
    OR LIKE '[0-9][0-9][0-9]'
    ....... etc.
    OR LIKE '[0-9].[0-9]'
    OR LIKE '[0-9].[0-9][0-9]'
    ....... etc.
    OR LIKE '[0-9][0-9].[0-9]'
    OR LIKE '[0-9][0-9].[0-9][0-9]'
    ....... etc.
    Ca en fait des cas de figures ........

    Ou alors moins bourrin, je fais un SUBSTRING avant et après l'éventuel séparateur décimal et je vérifie que la partie entière et la partie décimale ne sont constituée que de nombres. Ca fait quand même moins de combinaisons !!!

  4. #4
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 356
    Points
    356
    Par défaut
    Finalement, je me suis débrouillé avec la toute dernière méthode.

    Mais c'est de la bidouille. C'est tout de même énervant cette impossibilité d'anticiper les erreurs de conversion

    Et vivement SQL Server 2008 (la base devrait y migrer à la rentrée) !!!!

  5. #5
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Ha ben oui, tu pourras écrire une fonction d'assembly, ça te simplifiera grandement le code !
    Je ne sais pas si c'est beaucoup mieux, mais en attendant, tu pourrais peut-être vérifier la saisie directement au niveau applicatif.
    Après la migration, tu peux placer la contrainte qui va bien

    @++

  6. #6
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 356
    Points
    356
    Par défaut
    Je n'ai jamais touché à de l'assembleur et je crains que cela continue encore longtemps comme cela !

    Pour tes deux dernières suggestions, malheureusement non ! J'indiquais dans mon 1er post que je ne pouvais ni toucher au GUI de l'application, ni à la structure des tables de l'application.

    Je dois me contenter de faire des fonctions et des procédures stockées pour mouliner les données.

    A++

  7. #7
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Attention, il y a une différence entre une fonction d'assembly et de l'assembleur, langage auquel je ne connais strictement rien.
    Une fonction d'assembly est écrite soit en C#, soit en VB.NET, et permet de faire des traitement itératifs, ce pour quoi un bon SGBDR n'est pas conçu

    @++

  8. #8
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 356
    Points
    356
    Par défaut
    En passant par les proc étendues ?
    Je n'ai jamais regardé cela de près en fait. Question de temps .......

  9. #9
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Les procédures stockées étendues, c'est encore autre chose : ce sont des procédures qui sont écrites en C ou en C++ .
    L'avantage d'utiliser .NET (et donc les assembly) c'est que c'est SQL Server qui maîtrise totalement le code managé ainsi exécuté.
    Ce n'est pas le cas des procédures stockées étendues, qui, lorsqu'elles provoquent certaines erreurs graves peuvent conduire à l'arrêt du service SQL Server.
    Avec l'intégration de code .NET dans SQL Server, l'assembly s'exécute dans une aène fermée où SQL Server a le droit de vie ou de mort sur le processus exécutant l'assembly, si celui-ci vient à provoquer une erreur grave.
    Ainsi aucune instabilité au niveau de l'assembly ne vient perturber le fonctionnement du moteur de base de données.

    @++

  10. #10
    Membre à l'essai
    Inscrit en
    Juillet 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Juillet 2009
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Question bete, je suis pas sur d'avoir compris l'etendu du probleme mais tu cherche a savoir si un cast(<chaine de chiffre> as INT) vas fonctionner ou non ?

    Pourquoi ne pas tout simplement utiliser la fonction IS_NUMERIC() fournis par SQL Server ?

    http://msdn.microsoft.com/en-us/libr...2(SQL.90).aspx

  11. #11
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Le problème est que FMJ ne dispose pas seulement de chiffres, mais de champs alphanumériques délimités par un séparateur.
    D'ailleurs, il faut se méfier de la fonction ISNUMERIC(), qui retourne 1 pour les symboles opératoires - et +.

    Pour vérifier que le caractère obtenu est bien un entier, il faut procéder comme vous pouvez le voir ici, avec la fonction ASCII().

    @++

  12. #12
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 356
    Points
    356
    Par défaut
    C'est également une très bonne solution !!!
    Parser la chaîne caractère par caractère et vérifier soit que ce dernier soit 48 et 57 avec ASCII(), soit égal à '.' (le séparateur décimal).
    C'est toujours de la bidouille mais un peu plus subtile que ma méthode !

    Merci

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

Discussions similaires

  1. ERREUR D EXECUTION "3421" erreur de conversion de type de données
    Par bailamos dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 19/12/2008, 10h35
  2. erreur de conversion de type de donnée
    Par sunwind dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 05/05/2008, 10h44
  3. Réponses: 2
    Dernier message: 05/06/2007, 23h07
  4. Erreur 3421, Erreur de conversion de type de données
    Par khorn dans le forum VBA Access
    Réponses: 13
    Dernier message: 01/06/2007, 10h52
  5. Réponses: 6
    Dernier message: 09/06/2006, 12h17

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