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

Adaptive Server Enterprise Sybase Discussion :

[ASE 12.0.3] Comment tester les valeurs nulles (T-SQL)


Sujet :

Adaptive Server Enterprise Sybase

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 254
    Points : 80
    Points
    80
    Par défaut [ASE 12.0.3] Comment tester les valeurs nulles (T-SQL)
    Bonjour
    Suite à ma migration ASE de V11.0 en V12.0, je suis confrontée aux erreurs d'exécutions de procédures stockées ( plus de 1500 procédures à migrer).
    Ces problèmes sont liés, me seble-t-il à la gestion des varchar et plus particulièrement de valeurs nulles ou composées d'espaces uniquement.
    Par exemple:
    En V11 : right('abcd ',2) donne ''cd' alors qu'en V12 il donne 'd '. Je constate aussi que le résultat des tests de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "if (@var is null or ltrim(rtrim(@var)) !="")
    n'est pas le même en V11 qu'en V12. S'agît-il du paramétrage ou de vraie évolution de ASE ?

    Vu le nombre de mes procédures, je me demande si cela ne pouvait se régler par un paramétrage (option un peu "magique" du serveur.

    J'ai fait de nombreux tests (trop pour les citer tous), en voici un le plus simple:

    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
    set nocount on
    print '                                 AINSINULL OFF'
    GO
    set ANSINULL OFF
    declare @vnull varchar(1)
    select @vnull=''
    print "select @vnull=''"
      IF (@vnull IS NOT null)   print "TEST IS :  vnull IS NOT null " ELSE print "TEST IS :  vnull IS null "
      IF (@vnull != null    )   print "TEST =  :  vnull != null "     ELSE print "TEST =  :  vnull =null "
    select @vnull=NULL
    print "***"
    select @vnull=NULL
    print "select @vnull=null"
      IF (@vnull IS NOT null)   print "TEST IS :  vnull IS NOT null " ELSE print "TEST IS :  vnull IS null "
      IF (@vnull != null    )   print "TEST =  :  vnull != null "     ELSE print "TEST =  :  vnull =null "
     
    --
    set ANSINULL ON
    select @vnull=''
    print ""
    print '                                AINSINULL ON'
    print "select @vnull=''"
      IF (@vnull IS NOT null)   print "TEST IS :  vnull IS NOT null " ELSE print "TEST IS :  vnull IS null "
      IF (@vnull != null    )   print "TEST =  :  vnull != null "     ELSE print "TEST =  :  vnull =null "
    print "***"
    select @vnull=NULL
    print "select @vnull=null"
      IF (@vnull IS NOT null)   print "TEST IS :  vnull IS NOT null " ELSE print "TEST IS :  vnull IS null "
      IF (@vnull != null    )   print "TEST =  :  vnull != null "     ELSE print "TEST =  :  vnull =null "
    GO
    Ce script "croise" les 2 modes AINSINULL/2 types d'initialisation/2 types de tests.
    Le résultat varie en fonction du mode (je peux l'admettre) mais aussi en fonction du type d'affectation: ='' et =null produisent par la suite des réultats différents du test de la valeur nulle.
    Je ne trouve pas d'explication au résultat obtenu:
    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
     
                                     AINSINULL OFF
    select @vnull=''
    TEST IS :  vnull IS NOT null 
    TEST =  :  vnull != null 
    ***
    select @vnull=null
    TEST IS :  vnull IS null 
    TEST =  :  vnull =null 
     
                                    AINSINULL ON
    select @vnull=''
    TEST IS :  vnull IS NOT null 
    TEST =  :  vnull =null 
    ***
    select @vnull=null
    TEST IS :  vnull IS null 
    TEST =  :  vnull =null
    Je présente ce cas d'école, parce que je cherche à comprendre pourquoi mes procédures en V12 ne donnent pas le même résultat qu'en V11. Pour ce qui concerne ce premier test, le résultat en V11 et V12 est identique. J'en ai fait d'autres où je trouve de différences entre versions. Mais avant d'en parler, pouvez-vous m'aider à interpréter le résultat cité ci-dessus ?

    Dans notre application écrite pour V11:
    • la plupart de tests est faite avec = null / != null.
    • les affectation sont faits souvent par ='' (et non =null)
    • la valeur AINSINULL par défaut (selon la doc) est bien OFF

    Cela ne devait donc pas bien marcher (cf. mon test) et pourtant ça fonctionne. Je ne l'explique pas au vu de mon résultat.

    Est-ce qu'on peut paramétrer AINSINULL au niveau du serveur ?
    De façon générale, comment connaitre la valeur courante d'une option "set" sans avoir à tester et deviner par déduction ?

    Merci d'avance
    msomso
    P.S.
    En pièces jointes le code sql est résultat en V11 et V12.

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    Sur un serveur 12.5.3 j'ai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    [21] SYBASE.master.1> select right('abcd ', 2);
     
     -----
     d
    donc il semble qu'il s'agit d'une évolution (ou que le précédent comportement soit considéré comme un bug).

    Pour les problème de NULL il faudra attendre demain - je regarderai cela d'un peu plus près.

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  3. #3
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    Pour les NULLs (et non pas pour les nulls

    Lorsque ANSINULL est en marche, on ne peut jamais utiliser = pour faire une comparaison avec NULL, ce qui veut dire que ton test:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      IF (@vnull != null    )   print "TEST =  :  vnull != null "     ELSE print "TEST =  :  vnull =null "
    n'est pas complet. Considère ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    [46] LOCALHOST.my_db.1> set ansinull on;
    [47] LOCALHOST.my_db.1> declare @f int
    [47] LOCALHOST.my_db.2> select case when @f = null then "null" when @f != null then "not null" else "ni l'un ni l'autre" end;
     
     ------------------
     ni l'un ni l'autre
    [48] LOCALHOST.my_db.1>
    Comme je n'ai rien assigné à @f cette valeur est NULL. Les tests = et != sont tous les deux faux!
    Si ne mets ANSINULL off:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    [51] LOCALHOST.my_db.1> declare @f int
    [51] LOCALHOST.my_db.2> select case when @f = null then "null" when @f != null then "not null" else "ni l'un ni l'autre" end;
     
     ------------------
     null
    [52] LOCALHOST.my_db.1>
    Pour ce qui est des varchar() où l'on assigne '':

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    [53] LOCALHOST.my_db.1> declare @f varchar(1)
    [53] LOCALHOST.my_db.2> select @f = ''
    [53] LOCALHOST.my_db.3> select char_length(@f)
    [53] LOCALHOST.my_db.4> select case when @f = null then "null" when @f != null then "not n
    ull" else "ni l'un ni l'autre" end;
     
     -----------
               1
     
     
     ------------------
     not null
    [54] LOCALHOST.my_db.1>
    Un varchar() n'est jamais vide. Il contient au moins un espace, mais il contient au plus un "trailing" espace (je ne sais comment on dit cela en français - la chaine "aabbcc " devient "aabbcc ").

    Donc un varchar() auquel on assigne '' devient ' ' est n'est en conséquence pas NULL.

    En résumé: pour tester la nullitude d'une valeur/variable il est très fortement recommendé d'utiliser IS NULL/IS NOT NULL pour éviter toute confusion.

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 254
    Points : 80
    Points
    80
    Par défaut
    Bonjour
    il semble qu'il s'agit d'une évolution (ou que le précédent comportement soit considéré comme un bug)
    Dans le premier temps, moi aussi, j'ai crû qu'il s'agissait d'une correction d'un bug de V11 en V12. J'ai fait donc des corrections au cas par cas.
    Mais par la suite j'ai découvert d'autres incompatibilités.
    Par exemple, pour une @var variable varchar(1) étant nulle ou contenant un espace, le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (@var != null and ltrim(rtrim(@var)) !="")
    retourne VRAI en V12 et FAUX en V11.

    Notre @var est un paramétre IN d'une procédure stockée "P1".
    Cette procédure est appellée par Power Builder qui lui affecte la valeur d'un champ sur écran (champ "vide" en occurence). Elle appelle ensuite la procédure stockée "P2". La variable @var ne subit aucune transformation entre IHM et "P2".
    Le but du test est d'exclure du traitement les cas de valeurs nulls ou composées uniquement d'un blanc. Ceci marche en V11, mais en V12 le traitement se declenche et se termine en erreur car il ne s'attend pas à cette valeur compte tenu du test avant son appel.

    Je pense qu'après avoir corrigé ce cas, j'en trouverai d'autres cas: j'ai >600 tests de nulls avec =/!= dans mes procs.
    Personnellement, je teste tjrs par is null/is not null , mais je voudrais éviter des corrections en masse du code existant. D'autant plus que même en V12 le résultat depend, semblait-il, de type d'affectation: selon mon test cité au début, select @var='' ou select @var=null ne donnent pas la même chose dans le mode ainsinull off.

    Je voudrais donc trouver une solution générale à mon problème de migration de procédures stockées.

    Merci
    msomso
    P.S.
    Michael, je reprends tes tests et je vais continuer mes refléxions.
    Est-il possible de positionner option AINSINULL au niveau serveur ?

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    En fait, la solution semble assez simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    [25] LOCALHOST.master.1> declare @f varchar(1)
    [25] LOCALHOST.master.2> select @f = ''
    [25] LOCALHOST.master.3> select rtrim(ltrim(@f));
    (1 row affected)
     
     -
     NULL
     
    (1 row affected)
    Donc ton test:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IF (@var is not NULL AND ltrim(rtrim(@var)) is not null)
    et tu devrais avoir le bon comportement.

    Pour ANSINULL il faut que je regarde - en principe c'est un paramètre de connexion. Il peut être positionné par défaut pour une session "OpenClient" via le fichier ocs.cfg (%SYBASE%/OCS-12_0/config/ocs.cfg), mais ce n'est de loins pas sûr que cela marche avec PowerBuilder.

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 254
    Points : 80
    Points
    80
    Par défaut
    Bonsoir
    En effet ce que tu suggéres Michael, fonctionne !
    Moi, entre temps j'ai appliqué le test de acsii(@var) != null and ascii(@var) != 32.
    Le problème s'est éclairci dans ma tête: il fallait tester/exclure la chaîne vide (= null ou bien composé d'un espace).

    Ouff !

    Ceci étant dit, je rencontre d'autres "particularité", divergeances dans le test des valeurs null entre V11 et V12. Je commence à me résigner à les corriger au cas par cas.

    Merci
    msomso
    Saurais-tu me dire comment faire un CD avec la doc complète de V12 à partir du site que tu m'as indiqué: http://sybooks.sybase.com/nav/detail.do?docset=1145

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    Citation Envoyé par msomso Voir le message
    Saurais-tu me dire comment faire un CD avec la doc complète de V12 à partir du site que tu m'as indiqué: http://sybooks.sybase.com/nav/detail.do?docset=1145
    Je crois qu'il faut télécharger chaque PDF (ou au moins ceux qui sont importants - cad le manuel de référence, le guide admin système, le troubleshooting guide, et le performance et tuning).

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 254
    Points : 80
    Points
    80
    Par défaut
    Merci beaucoup
    msosmo

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

Discussions similaires

  1. Comment supprimer les valeurs nulls dans un champ
    Par souhail72 dans le forum Formules
    Réponses: 3
    Dernier message: 15/01/2014, 10h13
  2. comment remplir les valeurs nulles d'une colonne par des zeros '0'
    Par sinoun dans le forum Développement de jobs
    Réponses: 2
    Dernier message: 21/09/2011, 16h38
  3. Réponses: 0
    Dernier message: 21/07/2010, 10h04
  4. Comment tester la valeur nulle d'un TDateTime
    Par kolac dans le forum Langage
    Réponses: 3
    Dernier message: 17/01/2006, 18h09
  5. Comment gérer les valeur Nulles dans une requête ?
    Par sondo dans le forum Bases de données
    Réponses: 3
    Dernier message: 16/03/2005, 11h02

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