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

C++Builder Discussion :

Enlever la contrainte "Required" d'un champ dans MS Access


Sujet :

C++Builder

  1. #1
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Par défaut Enlever la contrainte "Required" d'un champ dans MS Access
    Bonjour à tous,

    J'ai un champ numérique dans une table Access et j'aimerai lui enlever la contrainte "Required" depuis C++ Builder. J'ai cherché des solutions sur internet mais sans succès: les trois méthodes que j'ai trouvées échouent toutes:

    1) Avec une requête SQL "ALTER TABLE table ALTER COLUMN column type NULL" je n'ai pas d'erreur mais l'état du champ ne change pas

    2) Avec l'attribut "Attributes" de la colonne en ADOX, là aussi pas d'erreur mais aucun changement

    3) Avec la propriété "Nullable" de la colonne en ADOX, j'ai une erreur lorsque j'essaye d'écrire dans sa propriété "Value" (exception "")

    Est-ce que quelqu'un trouverait l'erreur ou aurait une autre méthode?

    Voici le code avec les trois méthodes (j'ai remplacé mon objet interne par un TADOConnection pour le rendre plus lisible):
    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    //---------------------------------------------------------------------------
    //! Create the SQL command to set/remove constraint on a field to be required
    AnsiString CDBUpdateInterpreterAccess::RequiredFieldSQL(TADOConnection* database,
                                                         const AnsiString& tableName,
                                                         const SFieldDefinition& field) {
     
      //creates an OLE object using the class name
      Variant adox = Variant::CreateObject("ADOX.Catalog");
     
      //Open connection
      adox.OlePropertySet("ActiveConnection",database);
     
      //Get tables collection
      Variant vTables    = adox.OlePropertyGet("Tables");
      Variant table      = vTables.OlePropertyGet("Item",tableName.c_str());
      Variant vColumns   = table.OlePropertyGet("Columns");
      Variant column     = vColumns.OlePropertyGet("Item",field.name.c_str());
     
      // Get the "Required" state to assign to the field
      bool newRequired=false;
     
      // METHOD 1: via "Jet OLEDB:Allow Zero Length" AND "ALTER TABLE"
      // http://stackoverflow.com/questions/3409561/change-columns-properties-values
      {
        Variant property   = column.OlePropertyGet("Properties")
                                   .OlePropertyGet("Item","Jet OLEDB:Allow Zero Length");
        bool allowZero     =(bool)property.OlePropertyGet("Value");
        if (allowZero==newRequired) {   // "allowZero" is inverse of "Required"
          // Apply new value
          property.OlePropertySet("Value",!newRequired);
          // Also change the "NULL" / "NOT NULL" property of the field in ADO
          AnsiString sql=" ALTER TABLE "+tableName
                     +" ALTER COLUMN "+field.name
                     +" "+GetFieldType(field)
                     +" "+(newRequired?"NOT NULL":"NULL");
         TADOQuery* qry=new TADOQuery();
         qry->Connection=database;
         qry->SQL=sql;
         qry->ExecSQL();
         delete qry; qry=NULL;
        }
     
      }
     
     
      // METHOD 2: via the "Attributes" of the column
      // http://msdn.microsoft.com/en-us/library/ms681024%28v=VS.85%29.aspx
      //
      {
        int  attributes    = (int)column.OlePropertyGet("Attributes");
        bool oldRequired   = !(attributes&2);  //adColNullable=2 (inverse of NOT NULL)
        // Compare it to the new state to set
        if (oldRequired!=newRequired) {
          // Different: set the new state
          int newValue=(newRequired?attributes^2:attributes|2); //adColNullable=2 (inverse of "Required")
          column.OlePropertySet("Attributes",newValue);
        }
        // Test if change was applied
        attributes    = (int)column.OlePropertyGet("Attributes");
      }
     
     
      // METHOD 3: via the "Nullable" property of the column
      // http://msdn.microsoft.com/en-us/library/ms676554%28v=VS.85%29.aspx
      // http://www.pcreview.co.uk/forums/re-change-field-required-property-adox-t1685138.html
      {
        Variant property   = column.OlePropertyGet("Properties")
                                   .OlePropertyGet("Item","Nullable");
        bool nullable      =(bool)property.OlePropertyGet("Value");
        if (nullable==newRequired)) {    // "nullable" is inverse of "Required"
          try {
            property.OlePropertySet("Value",!newRequired); // Also tried to replace true by "True"
          } catch (...) {
            int error=1;
          }
        }
        // Test if change was applied
        nullable   =(bool)property.OlePropertyGet("Value");
      }
     
     
      // Close connection
      adox = Unassigned;
     
      //Refresh connection
      RefreshConnection(database);
     
      // No additionnal command to execute
      return AnsiString();
     
    }

  2. #2
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Salut Patrick Seuret
    Si c'est une table Access, dans la FAQ Access il est dit que l'on peut verrouiller les modifications (ajout suppression modification), c'est peut etre une piste, si Fbartolo passe il aura peut etre une solution

  3. #3
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Par défaut
    Bonjour Blondelle,

    Merci pour ta proposition, mais je n'ai pas l'impression que c'est ça car ma base n'est pas protégée (j'arrive à changer le flag manuellement depuis Access et aussi à renommer des colonnes avec ADOX comme dans mon code).

    Sinon, pour information, concernant la méthode 1, j'ai essayé d'exécuter la commande suivant depuis Access:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    currentdb.Execute "ALTER TABLE myTable ALTER COLUMN myColumn INTEGER NULL;"
    Et ça ne change rien alors que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    currentdb.Execute "ALTER TABLE myTable ALTER COLUMN myColumn INTEGER NOT NULL;"
    Met la propriété "Required" au champ sans probème.

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 010
    Par défaut
    J'ignore si cette syntaxe existe en ACCESS
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE myTable ALTER COLUMN myColumn DROP NOT NULL
    essaye aussi sans le spécificateur
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE myTable ALTER COLUMN myColumn INTEGER
    sur la MSDN, NOT NULL existe mais pas NULL seul !
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE table {ADD {COLUMN field type[(size)] [NOT NULL]     [CONSTRAINT index] |     ALTER COLUMN field type[(size)] |     CONSTRAINT multifieldindex} |     DROP {COLUMN field I CONSTRAINT indexname} }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Par défaut
    Bonjour ShaiLeTroll,

    Merci pour tes propositions, je les ai essayées directement depuis la console d'Access mais elles ne fonctionnent malheureusement pas (erreur de syntax dans la requête lorsqu'on fait le "DROP NOT NULL" et aucun changement avec la première syntaxe) :-(

    Patrick

  6. #6
    Membre chevronné

    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 531
    Par défaut
    Citation Envoyé par Patrick Seuret Voir le message
    Bonjour Blondelle,

    Merci pour ta proposition, mais je n'ai pas l'impression que c'est ça car ma base n'est pas protégée (j'arrive à changer le flag manuellement depuis Access et aussi à renommer des colonnes avec ADOX comme dans mon code).

    Sinon, pour information, concernant la méthode 1, j'ai essayé d'exécuter la commande suivant depuis Access:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    currentdb.Execute "ALTER TABLE myTable ALTER COLUMN myColumn INTEGER NULL;"
    Et ça ne change rien alors que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    currentdb.Execute "ALTER TABLE myTable ALTER COLUMN myColumn INTEGER NOT NULL;"
    Met la propriété "Required" au champ sans probème.

    Bonjour, je note le même problème que toi sous Access 2007, donc avec un AdoQuery cela donne la même chose évidamment.
    Pô facile ton truc, peut être création d'une table temporaire dynamique et recopie avant de constituer l'origine, mais bonjours les délais..

    A voir aussi en OLE., mais je ne vois pas..

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Par défaut
    Oui, le Ole semblait prometteur car des forums semblaient indiquer que ça marche en ADOX (mais sous VBA dans les exemples que j'ai trouvés, voir mes références dans le code), mais ça plante chez moi

    Je me suis demandé si ma syntaxe pour modifier la valeur d'une propriété est bonne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    column.OlePropertyGet("Properties")
           .OlePropertyGet("Item","Nullable")
           .OlePropertySet("Value",true); // aussi essayé avec "True"
    Mais comme le getter fonctionne, je ne vois pas pourquoi ça n'irait pas... En plus j'utilise un code similaire pour changer le nom de la colonne si nécessaire et ça marche (enfin, marchait, du vieux code que je devrais peut-être vérifier):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    column.OlePropertySet("Name",newName);

  8. #8
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Peu etre en executant une Macro comme decrit ici

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