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 :

REX : contrainte NOT NULL( FB 2.5)


Sujet :

SQL Firebird

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de qi130
    Homme Profil pro
    Expert Processus IT
    Inscrit en
    Mars 2003
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Expert Processus IT
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 3 932
    Par défaut REX : contrainte NOT NULL( FB 2.5)
    Bonjour,
    Je mets ça là, sans savoir si ça servira compte tenu de la version 2.5 concernée...

    Mon propos concerne la contrainte NOT NULL et la façon dont elle est gérée en interne par le SGBD.

    Je développe un petit couteau suisse pour gérer des trucs sur des bases FB avec UIB. J'affiche ainsi dans un grid la structure d'une table avec l'indication du NOT NULL pour les colonnes constituantes, avec pour ambition de modifier à la volée ce NOT NULL par 1 clic sur la checkbox correspondante.

    En première intention, je me fiais à la propriété "NotNull" (booléen) de chaque champ, telle que proposée par les Metadatas UIB, pour cocher ou pas cette case. Restait plus qu'à trouver les bonnes commandes pour procéder
    Une rapide recherche et je me lance, pas d'erreur dans les commandes, et dès le 1er essai pour supprimer le NOT NULL, success!
    La table:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE TATA (
       COL1 INTEGER NOT NULL,
       COL2 VARCHAR(5) NOT NULL
    );
    ALTER TABLE TATA
      ADD PRIMARY KEY (COL1)
      USING INDEX RDB$PRIMARY4;
    et pour récupérer la contrainte sur COL2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select rc.rdb$constraint_name
        from rdb$relation_constraints rc
        inner join rdb$check_constraints cc
          on rc.rdb$constraint_name = cc.rdb$constraint_name
        where rc.rdb$constraint_type = 'NOT NULL'
        and rc.rdb$relation_name = 'TATA'
        and cc.rdb$trigger_name  = 'COL2'
    débouchant sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE TATA DROP CONSTRAINT INTEG_13
    Je relance mon couteau suisse, c'est OK, la case de COL2 n'est plus cochée.

    Remettons donc en place cette contrainte, c'est tellement facile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE TATA  ADD CONSTRAINT COL2NN CHECK (COL2 IS NOT NULL)
    Je rafraichis les Metadatas UIB et ... la case n'est pas cochée

    Je fouille dans les tables système, je vois bien une contrainte avec le nom attribué (COL2NN), mais mais ... rdb$constraint_type n'est pas 'NOT NULL' mais 'CHECK' et attends ... il y a 2 contraintes en fait qui adressent 2 triggers (1 before insert et 1 before update) et il faut aller dans le source des triggers pour trouver une référence à COL2 et s'assurer que ça concerne bien le NOT NULL.

    La cause ?
    Tellement triviale : je vous sers le SQL permettant de reconstruire la table (produit par UIB)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CREATE TABLE TATA (
       COL1 INTEGER NOT NULL,
       COL2 VARCHAR(5)
    );
    ALTER TABLE TATA
      ADD PRIMARY KEY (COL1);
    ALTER TABLE TATA
      ADD CONSTRAINT COL2NN
      CHECK (COL2 IS NOT NULL);
    Il n'aura pas échappé à votre d’œil d'expert le subtil changement qui produit fonctionnellement une colonne COL2 avec la contrainte, tout comme précédemment.
    Mais techniquement, ce n'est plus la même chose.
    Du coup, le NotNull des UIB passe au travers, tout comme la jointure proposée par le Firebird Null Guide...

    J'ai donc dû embarquer les 2 possibilités dans mon couteau suisse afin que, dans cas d'un NOT NULL installé par un ALTER, le résultat soit pertinent:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
              SELECT DISTINCT RC.RDB$CONSTRAINT_NAME
                FROM RDB$RELATION_CONSTRAINTS RC
                INNER JOIN RDB$CHECK_CONSTRAINTS CC
                    ON RC.RDB$CONSTRAINT_NAME = CC.RDB$CONSTRAINT_NAME 
                INNER JOIN RDB$TRIGGERS T
                    ON CC.RDB$TRIGGER_NAME = T.RDB$TRIGGER_NAME
               WHERE RC.RDB$CONSTRAINT_TYPE = 'CHECK'
                   AND RC.RDB$RELATION_NAME = 'TATA'
                   AND T.RDB$TRIGGER_SOURCE CONTAINING 'K (COL2 IS NOT NULL'
    Je n'ai pas regardé comment cela était traité dans versions suivantes de FB.

    A bon entendeur !

    NB: pas sûr de l'utilité du 2nd inner

    PS: concernant les UIB, il faut pour chaque "fields" de la MetatTable, mouliner sur tous les "checks" pour vérifier la présence d'une référence NOT NULL pour ce fields:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    if Fields[j].NotNull then                  // lors du create de la table
       GridStructure.Cell[8,i].AsBoolean:=True
       else
       for z:=0 to ChecksCount-1 do            // via un ALTER
          if Pos('K ('+Fields[j].Name+' IS NOT NULL',checks[z].Constraint)<>0 then begin
             GridStructure.Cell[8,i].AsBoolean:=True;
             Break;
          end;

  2. #2
    Expert confirmé
    Avatar de qi130
    Homme Profil pro
    Expert Processus IT
    Inscrit en
    Mars 2003
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Expert Processus IT
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 3 932
    Par défaut Complément
    Curieusement, FB, au moins en 2.5, permet l'ajout "manuel" d'une contrainte NOT NULL sur 1 colonne définie NOT NULL dans le create de la table.

    Ce faisant il conviendrait de ramasser ces 2 contraintes via un UNION des 2 requêtes:
    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
     
     select rc.rdb$constraint_name
        from rdb$relation_constraints rc
        inner join rdb$check_constraints cc
          on rc.rdb$constraint_name = cc.rdb$constraint_name
        where rc.rdb$constraint_type = 'NOT NULL'
        and rc.rdb$relation_name = 'TATA'
        and cc.rdb$trigger_name  = 'COL2'
     UNION
     SELECT DISTINCT RC.RDB$CONSTRAINT_NAME
       FROM RDB$RELATION_CONSTRAINTS RC
       INNER JOIN RDB$CHECK_CONSTRAINTS CC
           ON RC.RDB$CONSTRAINT_NAME = CC.RDB$CONSTRAINT_NAME
       INNER JOIN RDB$TRIGGERS T
           ON CC.RDB$TRIGGER_NAME = T.RDB$TRIGGER_NAME
       WHERE RC.RDB$CONSTRAINT_TYPE = 'CHECK'
           AND RC.RDB$RELATION_NAME = 'TATA'
           AND T.RDB$TRIGGER_SOURCE CONTAINING 'K (COL2 IS NOT NULL'

Discussions similaires

  1. Alter table pour l'ajout de contrainte not null
    Par jean sami dans le forum SQL
    Réponses: 6
    Dernier message: 18/09/2008, 17h42
  2. Contraint not null
    Par Vince7-7 dans le forum Oracle
    Réponses: 5
    Dernier message: 01/10/2007, 14h50
  3. [9i] Contrainte NOT NULL
    Par Ito dans le forum Administration
    Réponses: 20
    Dernier message: 11/07/2007, 13h13
  4. Ajouter une contrainte NOT NULL à une colonne
    Par abdelghani_k dans le forum Firebird
    Réponses: 1
    Dernier message: 03/06/2007, 16h26
  5. Ajouter la contrainte NOT NULL a une colone [Firebird 1.5]
    Par crocodingo dans le forum Langage SQL
    Réponses: 2
    Dernier message: 31/01/2004, 18h52

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