Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1676 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [Résolu par voie détournée] Piloter des contraintes d'intégrité

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Résolu par voie détournée] Piloter des contraintes d'intégrité

n°1588898
belsuncett​e
Posté le 19-07-2007 à 16:05:48  profilanswer
 

Voilà, j'ai un petit problème - qui est d'ailleurs exposé dans un sujet là : http://forum.hardware.fr/hfr/Progr [...] 6359_1.htm  
Cadre : une appli VB, une base access à laquelle cette appli accède.
Il faut que je fasse un update d'une valeur, or cette valeur est une clé dans 3 tables, et du coup ça ne marche que si je supprime l'intégrité référentielle entre ces tables. Ce qui est une mauvaise chose.
 
Je voudrais donc savoir s'il est possible de coder dans VB un ordre pour désactiver l'intégrité référentielle sur la relation R, puis faire ma manip, puis remettre l'intégrité sur R.  
Est-ce que je rêve trop ou c'est faisable ?  
Car c'est dur de trouver de la doc la dessus !
 
Merci.


Message édité par belsuncette le 26-07-2007 à 14:47:30
mood
Publicité
Posté le 19-07-2007 à 16:05:48  profilanswer
 

n°1588907
Oreste
Posté le 19-07-2007 à 16:14:33  profilanswer
 

Désactiver une contrainte je sais pas si c est possible en access encore moins :) Par contre tu peux la virer et la recreer apres dans ton programme.
 
Enfin derniere chose si tu dois faire ce genre de manip :
- soit ta contrainte est inutile alors il faut la virer
- soit ta manip est dangereuse
 
Si des contraintes sont placées c est justement qu il y a une raison ;) Dans ton cas tu vas faire un update d une valeur qui n est pas référencé dans une autre table, un moment ou à un autre ca va etre le bordel dans tes données...

n°1588911
Oreste
Posté le 19-07-2007 à 16:16:56  profilanswer
 

Hop voila un lien pour desactiver une contrainte en SQL --> http://www.databasejournal.com/sql [...] hp/1490991
 
Pas sur que ca marche en Access

n°1589109
belsuncett​e
Posté le 20-07-2007 à 08:48:26  profilanswer
 

Merci je vais me plonger dans ça. Y'a pas mal de commandes SQL qui marchent depuis VB pour une base access. Il faut juste identifier laquelle gère l'intégrité référentielle.
Sinon, pas de danger normalement avec cette manip, le truc c'est que je veux changer un numéro de client partout mais qu'il faudrait pouvoir faire ça exactement en même temps dans toutes les tables où ce numéro sert de clé....
Il faut donc virer la contrainte à ce moment là, sinon quand on veut faire l'update dans une table ça refuse à cause des autres tables.  
Je ne nie pas que la base est pas top au niveau normalisation mais elle a déjà quelques années et c'est impossible de tout casser maintenant vu la quantité de données (mais pourtant ça me démange :D).  
Je ne sais pas si la contrainte est utile ailleurs, mais je ne veux pas prendre le risque de la supprimer...

n°1589118
tegu
Posté le 20-07-2007 à 09:10:09  profilanswer
 

À ma connaissnace, on ne peut pas simplement désactiver les relations d'intégrité dans Access.
Il faut supprimer puis recréer la relation (objet Relations et méthode .CreateRelation)
 
Tu peux aussi définir ta relation pour permettre la mise à jour en cascade des clés.
Ça t'éviterais d'avoir à recommencer cette manipulation.

n°1589129
belsuncett​e
Posté le 20-07-2007 à 09:20:36  profilanswer
 

La mise à jour en cascade est déjà activée. Cela fonctionne en partie quand on met à jour NumClient, clé de TableClient : les tables où NumClient est une clé étrangère ont bien la valeur mise à jour. Le problème se pose dans les tables (il y en a 2 dans ce cas) où NumClient est aussi une clé primaire : dans ce cas la mise à jour en cascade ne fonctionne pas - et du coup tout l'update est refusé.
 
La piste d'Oreste m'a conduite à trouver l'option dbInconsistent dans la méthode execute de VB (database.execute(requete)). Je suis en train de voir si ça peut marcher...


Message édité par belsuncette le 20-07-2007 à 09:20:49
n°1589145
jpcheck
Pioupiou
Posté le 20-07-2007 à 09:50:10  profilanswer
 

belsuncette a écrit :

c'est impossible de tout casser maintenant vu la quantité de données


 
impossible n'est pas francais, qté de données ou pas :p

n°1589152
belsuncett​e
Posté le 20-07-2007 à 09:54:09  profilanswer
 

Oui mais mon contrat était trop court pour me lancer dans ça même si je l'ai proposé parce que je m'arrachais les cheveux de voir ça :D

n°1589154
belsuncett​e
Posté le 20-07-2007 à 09:59:22  profilanswer
 

Rhooo, ça marche toujours pas :'(

n°1589171
tegu
Posté le 20-07-2007 à 10:20:14  profilanswer
 

dbInconsistent est un paramètre par défaut je crois et ne passe pas outre les relations d'intégrité référentielle.

 

Message cité 1 fois
Message édité par tegu le 20-07-2007 à 10:20:24
mood
Publicité
Posté le 20-07-2007 à 10:20:14  profilanswer
 

n°1589175
Oreste
Posté le 20-07-2007 à 10:23:02  profilanswer
 

Hmm belsuncette comment ca se fait que numclient soit clé primaire sur 2 tables ? je trouve ca bizarre...

n°1589177
belsuncett​e
Posté le 20-07-2007 à 10:26:13  profilanswer
 

En fait c'est la clé primaire de Client. Et puis il y a une relation 1-1 avec 2 autres tables dans lequel il sert de clé aussi... Je suis d'accord que c'est pas top mais ça a été conçu comme ça, et je pense que ça devait être par nécessité car les 2 autres tables ont énormément de champs, ça devait être pour ne pas surcharger.  
Enfin bon, je suis pas aidée par cette BD, c'est sûr !!!!  :pfff:


Message édité par belsuncette le 20-07-2007 à 10:28:17
n°1589180
belsuncett​e
Posté le 20-07-2007 à 10:28:02  profilanswer
 

tegu a écrit :

dbInconsistent est un paramètre par défaut je crois et ne passe pas outre les relations d'intégrité référentielle.
 


 
 
Tu sais pas ce qui le ferait ? Parce que en effet ça ne fait pas grand chose.  
Les trucs de type "NOCHECK" me tentaient (cf le lien d'Oreste) mais le problème c'est qu'il faut nommer les contraintes sur lesquelles on CHECK ou pas, et moi c'est pas une contrainte que j'ai créée mais une contrainte d'Access.
 
  :cry:

n°1589194
tegu
Posté le 20-07-2007 à 10:36:34  profilanswer
 

Je suis désolé de me citer mais « À ma connaissnace, on ne peut pas simplement désactiver les relations d'intégrité dans Access.  »
 
J'ai quelques années d'Access derrière moi, certes pas sur les versions les plus récentes mais j'ai un doute sur la faisabilité de ton truc sans suppression de la relation.
 
Je ne demande qu'à être contredit, ceci-dit, pour t'éviter du boulot inutile :)

n°1589212
belsuncett​e
Posté le 20-07-2007 à 10:47:26  profilanswer
 

Ouin....j'aimerais aussi que tu aies tort, mais je te fais confiance, malheureusement !
 
Tant pis ils devront continuer à aller désactiver à la main l'intégrité (ça on peut le faire par contre, en cliquant sur la relation), puis faire leur modif, et la remettre....C'est déjà un progrès vu que jusqu'à maintenant ils allaient carrément supprimer la relation, mais bon, l'idée c'était que je trouve comment faire ça plus simplement.
 
Merci quand même :)

n°1589315
tegu
Posté le 20-07-2007 à 13:32:50  profilanswer
 

Ben tu peux coder la suppression puis la recréation de la relation (objet Relations et méthode .CreateRelation).
Pas obligé de passer par l"interface et de le faire manuellement.

n°1589346
belsuncett​e
Posté le 20-07-2007 à 13:59:13  profilanswer
 

Ca me parait pas mal, ça. Est-ce que tu sais (ou connais un bon tutorial qui le dit) comment on peut désigner la relation visée ?

n°1589387
tegu
Posté le 20-07-2007 à 14:35:31  profilanswer
 

L'aide en ligne (F1) est suffisante.

n°1589397
belsuncett​e
Posté le 20-07-2007 à 14:49:21  profilanswer
 

Oui l'aide de VB est vraiment bien, mais mes relations dans la base Access n'ont pas de nom, du coup je ne vois pas comment identifier la propriété Name de la relation que je veux supprimer ? ou au moins leur numéro. La méthode Delete a besoin d'un des 2.
 
Dans l'aide d'access, que je trouve beaucoup moins bien que celle de VB, je trouve ça, pour l'instant :
 
POUR CHANGER LE NOM D'UNE RELATION :
"Dans la fenêtre Base de données, cliquez sur Schémas de base de données  sous Objets. Cliquez ensuite sur le schéma de base de données que vous souhaitez ouvrir, puis sur Modifier dans la barre d'outils de la fenêtre Base de données.  
Dans votre schéma de base de données, sélectionnez la ligne représentant la relation que vous voulez renommer.  
Cliquez avec le bouton droit sur la ligne de relation et sélectionnez Propriétés.  
Choisissez l'onglet Relations.  
Dans la zone Nom de la relation, entrez un nouveau nom."
 
mais je n'ai pas ça, moi   :na:  
Edit : c'est normal, c'est pour des projets access de type "ADP", je ne sais pas ce que c'est mais le mien est de type "MDB".
 
Je continue à chercher  :bounce:


Message édité par belsuncette le 20-07-2007 à 15:01:06
n°1589421
tegu
Posté le 20-07-2007 à 15:19:09  profilanswer
 

Les projets ADP sont des projets Access partagés.
Le nom d'une relation est la concaténation des noms des tables impliquées, de mémoire.
Sinon tu dois pouvoir parcourir la collection des relations et tester .Table et .ForeignTable


Message édité par tegu le 20-07-2007 à 15:20:30
n°1589438
belsuncett​e
Posté le 20-07-2007 à 15:31:13  profilanswer
 

Je venais de tester la concaténation, mais ça me dit "élément non trouvé dans cette collection". Je poursuis, je poursuis....Merci beaucoup de ton aide en tout cas, je vais bien finir par y arriver finalement :)

n°1589460
belsuncett​e
Posté le 20-07-2007 à 15:52:08  profilanswer
 

Bon, alors en fait, après une petite boucle qui teste .Table et .ForeignTable, j'ai pu trouver le nom des relations que je veux, et c'est effectivement une concaténation des noms des tables, mais précédée du chemin d'accès de la base, ce qui donne qqch comme :
" [C:\DossierBelsuncette\BaseClient.mdb].Table2Table1"
 
La suppression de la relation marche bien. Du coup je suis confiante pour ma mise à jour !!!


Message édité par belsuncette le 20-07-2007 à 15:52:27
n°1590024
belsuncett​e
Posté le 23-07-2007 à 12:06:07  profilanswer
 

Re moi, je garde le même sujet : j'ai du mal avec CreateRelation.
Pour l'instant je fais  
   Set Regeneration_HistoPrel = db.CreateRelation(, "HistoPrel", "Client", dbRelationUpdateCascade)
   db.Relations.Append Regeneration_HistoPrel
 
Mais ça me le refuse, et je n'arrive pas à savoir pourquoi exactement. Le message d'erreur est incomplet, il dit qu'il n'arrive pas à trouver qqch mais ne le nomme pas, et dit que c'est peut-être un mauvais alias. Je pense que ça vient du nom des tables mais je ne sais pas quoi mettre : j'ai essayé avec leur nom, puis leur nom précédé du chemin complet, mais ça ne change rien.
L'erreur se produit au moment du Append : si j'ai bien compris, il est nécessaire pour que les relations soient effectivement créées...
Je dois mal m'y prendre :/

n°1590166
tegu
Posté le 23-07-2007 à 14:16:04  profilanswer
 

Effectivement tu t'y prends mal :)
Une relation n'est pas seulement définie par le nom des tables en relation, mais surtout par la correspondance des champs de clé.
Quand tu crées un objet relation, il ne fait pas l'appariement automatiquement entre les champs clé, même si les noms sont identiques.
Tu dois passer par la création d'objets champs et les ajouter à la collection des champs de ta relation.
 

Dim fld As Field, r As Relation, db As Database
...
Set r = db.CreateRelation(,table1, table2, dbRelationUpdateCascade)
Set fld = r.CreateField("NomDuchamp1Table1" )
fld.ForeignName = "NomDuChamp1Table2"
r.Fields.Append fld
 
Set fld = r.CreateField("NomDuchamp2Table1" )
fld.ForeignName = "NomDuChamp2Table2"
r.Fields.Append fld
 
db.Relations.Append r
db.Relations.Refresh

n°1590287
belsuncett​e
Posté le 23-07-2007 à 15:50:59  profilanswer
 

J'ai toujours une erreur au moment du db.Relations.Append : la même, il dit qu'il ne trouve pas ce quelquechose qu'il nomme :   ".
Je ne sais vraiment pas d'où ça vient. J'ai essayé de spécifier les chemins : pour les tables et pour les champs, mais je ne suis pas sûre de bien le faire non plus.
Par exemple, pour les tables, je me base sur ce qui m'était renvoyé quand je recherchais les noms des relations, et ça donne donc un truc de ce style :  
"[C:\Copie_Belsuncette\Base2307.mdb].HistoDup"
Et j'essaie aussi sans chemin ; ça dit pareil.  
Est-ce qu'il faut aussi créer des TableDef ?  
 
PS : effectivement c'était bête de ne pas spécifier les champs de la relation ;)

n°1590310
tegu
Posté le 23-07-2007 à 16:12:32  profilanswer
 

Quand tu dis que tu essaies sans chemin, tu n'oublierais pas d'enlever le point aussi ?
Ton message d'erreur semble dire que le problème est lié à la mauvaise utilisation de ce caractère.

n°1590317
belsuncett​e
Posté le 23-07-2007 à 16:17:23  profilanswer
 

Sans chemin, je ne mets pas le point, et avec chemin, je le mets puisque c'était comme ça dans le nom de la relation....
Je suis près du but pourtant (de mon but initial ;)) c'est rageant :D

n°1590331
tegu
Posté le 23-07-2007 à 16:40:40  profilanswer
 

Est-ce que tes tables contiennent des enregistrements quand tu établis la relation ?
Si oui, il se peut que leur contenu soit incompatible avec cette relation.
Du genre un champ clé mal renseigné, qui n'a pas déquivalent dans la table liée.


Message édité par tegu le 23-07-2007 à 16:42:50
n°1590333
belsuncett​e
Posté le 23-07-2007 à 16:43:55  profilanswer
 

Ben vu que je supprime la relation juste avant, toutes les données devraient satisfaire la nouvelle relation identique à l'ancienne...
A savoir, le champ impliqué dans la relation que je crée est la clé pour chacune des 2 tables.

n°1590335
tegu
Posté le 23-07-2007 à 16:46:03  profilanswer
 

Oui c'est vrai.
Bon, du coup, je ne vois pas trop ce qui pose problème.
J'aimerais que tu nous montres ton code actuel pour faire un test chez nous si possible.
Au moins une version simplifiée qui ne fonctionne pas chez toi.

n°1590351
belsuncett​e
Posté le 23-07-2007 à 17:01:57  profilanswer
 

Ca me parait un peu compliqué de tout vous envoyer, alors je ne sais pas si ça serait suffisant :
il faut
- une table Client avec la clé NumClient, le reste on s'en fout
- une table HistoPrel avec la clé NumClient aussi
 
Mon code pour créer la relation :
 

Code :
  1. Dim Regeneration_HistoPrel As Relation 
  2.    Dim Fld As Field
  3.  
  4.    Set Regeneration_HistoPrel = db.CreateRelation(, "HistoPrel", "Client", dbRelationUpdateCascade + dbRelationUnique)
  5.    Set Fld = Regeneration_HistoPrel.CreateField("NumClient" )
  6.    Fld.ForeignName = "NumClient"
  7.    Regeneration_HistoPrel.Fields.Append Fld
  8.  
  9.    db.Relations.Append Regeneration_HistoPrel
  10.    db.Relations.Refresh


Il faut juste lier la base à l'appli VB, dis moi si tu as besoin d'autre chose. Ici c'est fait comme ça, avec le nom de la base dans 'bd' :
 
    Set wrkJet = CreateWorkspace("", "admin", "", dbUseJet)
    Set db = wrkJet.OpenDatabase(bd, _
      False)
 
Sinon j'ai testé et contrairement aux relations, quand il trouve les noms des tables il n'y a pas tout le préfixe, seulement le nom de la table. Alors du coup moi non plus je ne vois pas d'où ça vient !
Je n'ai pas réussi à faire la même chose pour les attributs et voir comment ils sont nommés ici - j'avais essayé un truc du style "[HistoPrel].NumClient" mais toujours pas ça....
 
Merci beaucoup pour ton aide, en tout cas !


Message édité par belsuncette le 23-07-2007 à 17:03:00
n°1590370
tegu
Posté le 23-07-2007 à 17:19:21  profilanswer
 

Résultat des courses, si j'utilise

Set Regeneration_HistoPrel = db.CreateRelation(, "HistoPrel", "Client", dbRelationUpdateCascade + dbRelationUnique)

j'obtiens la même erreur que toi.
Si je rajoute un nom à ma relation ça ne déclenche pas d'erreur.

Set Regeneration_HistoPrel = db.CreateRelation("HistoPrelClient", "HistoPrel", "Client", dbRelationUpdateCascade + dbRelationUnique)

n°1590535
belsuncett​e
Posté le 24-07-2007 à 08:44:58  profilanswer
 

Génial, merci pour ce tuyau, j'avais mis un nom à un moment mais certainement avec plein d'autres trucs faux.
 
Ce matin, gros espoir, et la : DAMNED => "Opération non gérée sur des tables attachées"...... :'(
Je vais y arriver ;) J'imagine qu'il faut aller faire ça directement dans la BD et non la BD qui lui est liée. Bizarre pourtant, le Delete marche très bien, lui.....
Bon, vais tenter d'accéder à la BD principale.


Message édité par belsuncette le 24-07-2007 à 08:48:06
n°1590540
belsuncett​e
Posté le 24-07-2007 à 09:02:50  profilanswer
 

C'est bizarre, quand je recrée, il me dit que l'objet "HistoPrelClient" existe déjà...
 
Et puis ça m'envoie bouler pour recréer la relation sous un autre nom, mais cette fois c'est parce que la BD est accédée sur d'autres postes en ce moment. Je verrai ce que ça donne quand personne n'y touche, c'est gérable. Mais je me demande si nommer la relation différemment à chaque fois a des conséquences ? Genre, il stocke toutes les relations quand même ??? Parce qu'après le Delete, elle disparaît bien du schéma avec les relations.
 
Il faut que je voie si après un renommage, la relation est bien retrouvée au passage suivant, pour savoir si ça sert à qqch de faire ça. Mais pour ça il faut que je fasse déconnecter tout le monde  :sarcastic:


Message édité par belsuncette le 24-07-2007 à 09:08:26
n°1590887
belsuncett​e
Posté le 24-07-2007 à 15:10:29  profilanswer
 

Une dernière question, tegu :
ça marche finalement (victoire !!!!), par contre il reste un petit défaut.
Je supprime les relations, je fais mes modifs, je recrée les relations.  
Si je réessaie de faire un autre changement de numéro tout de suite, il ne trouve pas la relation nouvellement recréée. Par contre, si je sors de mon appli et que j'y rerentre, il la trouve.
Saurais-tu pourquoi, car je fais des refresh et append ?  
Sinon, tant pis, c'est déjà pas mal ;) Merci ENORMEMENT de ce dépannage.

n°1590895
tegu
Posté le 24-07-2007 à 15:19:07  profilanswer
 

Si tu fais bien un db.Relations.Refresh après ton .Append, je ne vois pas pourquoi ça ne marche pas.
Essaie de faire aussi un .Refresh sur la collection des .QueryDefs de ta base. On ne sait jamais.

n°1590938
belsuncett​e
Posté le 24-07-2007 à 15:49:53  profilanswer
 

Sans le vouloir, tu m'as répondu : en fait, je faisais le Refresh dans la base distante puisqu'il faut créer les relations dedans, comme je l'ai vu plus haut.
En faisant le relations.refresh sur cette base, ça n'était pas suffisant : il faut aussi le faire sur la base locale car c'est dans cette base que les relations sont supprimées. En fermant et rouvrant l'appli, il trouvait bien toutes les relations, mais sinon la base locale restait ouverte et n'était pas mise à jour.
Et voilà, maintenant ça marche et c'est super !!!!!!!!!!!
Je ne sais pas comment te remercier !!

n°1590999
tegu
Posté le 24-07-2007 à 16:54:05  profilanswer
 

« Je ne sais pas comment te remercier !! » Oula, tu prends des risques !
Blague à part, ça fait plaisir de pousser les wagonnets avec les débutants qui s'en donnent la peine.
On est tous au fond de la même mine. Je creuse juste depuis plus longtemps :)

n°1591004
jpcheck
Pioupiou
Posté le 24-07-2007 à 16:57:17  profilanswer
 

+1  :pt1cable:

n°1591148
belsuncett​e
Posté le 25-07-2007 à 08:37:43  profilanswer
 

Et bien merci encore, de prendre du temps pour des gens comme moi :)

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [Résolu par voie détournée] Piloter des contraintes d'intégrité

 

Sujets relatifs
Mails retour automatiques rejetés (résolu)VBA [Résolu] Placer du texte obtenu par VBA dans un formulaire Outlook
[Résolu] Lancement script avec MySQL Query Browser[ASP.NET][Résolu] Problème envoi de mails
[résolu] script java qui ne fonctionne pas sous Internet explorer[résolu] récupérer 2 variables dans <option> du <select>
[résolu] Afficher données d'un txt en tableau[Resolu] C# TreeNode CheckBox
résolu[Résolu] Personalisé la page "Index of/"
Plus de sujets relatifs à : [Résolu par voie détournée] Piloter des contraintes d'intégrité


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR