Bonjour le forum.
Aidez moi à contrôler la clé d'une table à 3 champs dans le boucle while. J'ai utilisé findkey mais ça ne marche pas correctement
Bonjour le forum.
Aidez moi à contrôler la clé d'une table à 3 champs dans le boucle while. J'ai utilisé findkey mais ça ne marche pas correctement
Bonjour
Un indice sur la structure de la table, le type de boucle, le traitement qui y est fait ?
Stocker ( codpro,DatStock,heure,
Nature,QteIni,Qte,QteFin)
La boucle est lié à une table tampon que j'ai créé mais qui prends les données qui correspondent aux données de la table stocker
La clé est Codpro, datstock, nature
Bonjour,
Contrôler une clé Qu'est-ce que vous entendez par là ?
légère éclaircie dans le flou du premier post il s'agirait donc de savoir si le triplet Codpro, datstock, nature existe déjà dans la table cible.La boucle est liée à une table tampon que j'ai créé mais qui prends les données qui correspondent aux données de la table stocker
donc, en consultant ma boule de cristal pas complétement cassée la matin je vois un traitement de ce type
et vous auriez des difficultés avec la partie "si destination existe" que vous traitez en utilisant un findkey.tant que source n'est pas en fin de fichier
faire
si destination existe alors traitement en modification sinon traitement en insertion
enregistrement suivant de source
fin faire
Cette technique de findkey aurait pu fonctionner sur un fichier Paradox ou si toute la table destination avait été chargée dans un Dataset, mais dans le cadre d'un SGBD cela n'est pas forcément le cas (ni le besoin) de plus le SQL existe autant s'en servir
Remplacez findkey par sur une table par Select dans une requête paramétrée exemple :
SELECT Codpro, datstock, nature from Stocker where codepro=:c and datastock=:d and nature:=nsi codepro est null, ou le nombre d'enregistrement=0 alors la clé n'existe pas
bien sûr toute la phrase
peut aussi se traiter de manière plus "SQL" exemplesi destination existe alors traitement en modification sinon traitement en insertion
Remarquez l'utilisation extensive de paramètres
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 INSERT INTO table (Codpro,datstock,heure,nature,QteIni,Qte,qtefin) VALUES(:code,:datestock,:heure,:nature,:qteini,:qte,:qtefin) ON DUPLICATE KEY UPDATE ...Qte=Qte+:qte, <autres>
Attention quand même, je ne suis pas un spécialiste MySQL et le DUPLICATE KEY doit certainement s'appliquer sur une clé unique , lisez la doc
ma boule de cristal ne sait pas lire
En conclusion : Donner toutes les informations dans votre demande apportera de bien meilleures réponses
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
Peut être faire une requête via un select distinct sur les trois première colonne citées et des fonction d'agrégation pour les autres colonnes
Justement c'est ce que ça affiche comme message quand je lance l'exécutable "duplicate key" et ça bloque le processus en cours. Au faites dans la boucle de la table tampon le champ codpro de la table stocker prend la valeur code de la table tampon pour faire le contrôle. Ce qui n'a pas marché. Utiliser Query n'est pas la solution.
Tant que vous ne nous mettrez pas un tant soit peu de votre code nous ne pourrons que spéculer !
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
Je vous envoie le code écris alors :
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 Tampon1.First; While not Tampon1.Eof do begin If Produit.FindKey([Tampon1.Fields[0].asstring]) then begin Produit.Edit; Produit.FieldByName('Stock').AsFloat := Produit.FieldByName('Stock').AsFloat-Tampon1.Fields[3].asfloat; Produit.Post; end; Vente.AppendRecord([Edit5.Text, Tampon1.Fields[0].AsString, Tampon1.Fields[3].AsFloat, Tampon1.Fields[5].Asfloat, Tampon1.Fields[6].Asfloat]); som := som + Tampon1.Fields[6].AsInteger; //Tot := Tot + Tampon1.Fields[7].AsInteger; tampon.First; while not tampon.Eof do begin if (tampon.FieldByName('CodTam').AsString = Tampon1.Fields[0].asstring)then begin tampon.Edit; tampon.Fields[3].AsFloat := tampon1.FieldByName('QteFin').AsFloat; tampon.Post; break; end else tampon.Next; end; Stocker.First; if Stocker.FindKey([Tampon1.Fields[0].AsString, Datetimepicker1.DateTime, 'Sortie']) then begin Stocker.Edit; Stocker.FieldByName('Qte').AsFloat := Stocker.FieldByName('Qte').AsFloat + tampon1.FieldByName('Qte').AsFloat; Stocker.FieldByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.FieldByName('Heure').AsString := edit12.Text; Stocker.Post; end else begin Stocker.Insert; Stocker.FieldByName('CodPro').AsString := Tampon1.Fields[0].AsString; Stocker.FieldByName('DatStock').AsDateTime := Datetimepicker1.DateTime; Stocker.FieldByName('Heure').AsString := edit12.Text; Stocker.FieldByName('Nature').AsString := 'Sortie'; Stocker.FieldByName('QteIni').AsFloat := tampon1.FieldByName('QteIni').AsFloat; Stocker.FieldByName('Qte').AsFloat := tampon1.FieldByName('Qte').AsFloat; Stocker.FieldByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.Post; end; Tampon1.Next; end;
Locate serait plus lisible ! non ?
Avez-vous vérifier in IndexName ou IndexFieldNames qu'ils sont bien comme prévu pour FindKey
Il ne serait pas plus simple d'écrire un script SQL avec quelques paramètres, au besoin une table temporaire ?
Cela sera en plus nettement plus performant pour ce type de recodage de masse
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
Les lignes 26 à 46 sont remplaçables par le INSERT INTO .... ON DUPLICATE UPDATE
ne sachant pas de quels composants de données il s'agit difficile de faire un code exact.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 // en dehors de la boucle Stocker.SQL.text:='INSERT INTO table (Codpro,datstock,heure,nature,QteIni,Qte,qtefin) '; Stocker.SQL.add(VALUES(:codepro,:datestock,:heure,:nature,:qteini,:qte,:qtefin)); Stocker.SQL.add('ON DUPLICATE KEY UPDATE Qte=Qte+:uqte,qtefin=:uqtefin,Heure=:uheure'); Stocker.Prepare;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 Stocker.FieldByName('uQte').AsFloat := tampon1.FieldByName('Qte').AsFloat; Stocker.ParamByName('uQteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.ParamByName('uHeure').AsString := edit12.Text; Stocker.ParamByName('CodPro').AsString := Tampon1.Fields[0].AsString; Stocker.ParamByName('DatStock').AsDateTime := Datetimepicker1.DateTime; Stocker.ParamByName('Heure').AsString := edit12.Text; Stocker.ParamByName('Nature').AsString := 'Sortie'; Stocker.ParamByName('QteIni').AsFloat := tampon1.FieldByName('QteIni').AsFloat; Stocker.ParamByName('Qte').AsFloat := tampon1.FieldByName('Qte').AsFloat; Stocker.ParamByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.ExecSQL;
Les lignes 13 à 25 me posent beaucoup de doutes
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 Tampon1.First; While not Tampon1.Eof do begin //If Produit.FindKey([Tampon1.Fields[0].asstring]) then // begin //Produit.Edit; //Produit.FieldByName('Stock').AsFloat := Produit.FieldByName('Stock').AsFloat-Tampon1.Fields[3].asfloat; //Produit.Post; //end; remplacable par, si firedac, un simple FDConnexion.ExecSQL('UPDATE PRODUIT SET STOCK=STOCK+:Q WHERE CODEPRO=:C',[Tampon1.Fields[3].asfloat,Tampon1.Fields[0].asstring]); sinon par une requête, un passage de paramètre et un execsql
un petit pour ShaiLeTroll et son Locate, en effet je suis parti sur le fait que Codpro,datstock,nature formaient la clé primaire mais il faudrait me le prouver
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
C'est un peu normal !!!
Les blocs try except c'est fait pour ça... Mais je vois dans ton code qu'il n'y en a pas... Donc la procédure en cours d'exécution stoppe tout simplement sur l'erreur
Et tu n'a pas de transaction non plus, bonjour l'intégrité de ta base...
On doit fait ceci lorsque l'on traite des mises à jour de base de données :
Après faut lire aussi la doc MySQL...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 try // Début de transaction // Boucle // Execution des requêtes ici // Fin de boucle // Validation de la transaction except on E:Exception do begin // Annuler la transaction // Traiter l'erreur (affiche un message, autre traitement, etc... end; end;
Comme te l'a dit SergioMaster plus haut : INSERT IGNORE et INSERT... ON DUPLICATE UPDATE... ça doit bien servir à quelque chose... Ou alors ils l'ont juste fait pour se faire plaisir à toi de voir....
Monsieur Sergio Merci pour votre appui mais j'ai essayé votre code mais ça ne prends pas. il me dit même ExecSQL n'est pas declaré. je fais comment
Comment integré alors la fonction Try alors
Oui, j'ai fait une erreur en recopiant bêtement tout les fieldByname pour garder une cohérence avec votre programme et ai oublié de les remplacer par des ParambyName. Oubli qui est réparé
En nous disant déjà de quel type de composant de connexion aux bases de données il s'agit !il me dit même ExecSQL n'est pas declaré. je fais comment
pour moi , avec Firedac ce serait : un FDConnection, Stocker : un FDQuery
@Sergio_is_Back je n'ai même pas voulu m'embarquer dans les parties transactions, et même les possibilités d'ArrayDML de Firedac ou encore plus étonnant le LocalSQL, on n'a même pas la version de Delphi utilisée
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
il y a pas une autre fonction a part Query sinon j'ai essayé le remplaçant mais ça n'a pas marché
sinon au faite ça fait le contrôle mais ça ratte par moment et bloque le processus d'établissement de la facture.
je veux aussi vous faire comprendre que Mysql fonctionne ici comme paradox
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
excusez moi j'utilise delphi7
Non MySQL ne fonctionnera jamais comme Paradox !!!
C'est comme si tu prend une voiture et un hélicoptère : c'est un moyen de transport mais ça marche pas pareil !
T'as déjà essayé de prendre une autoroute avec un hélicoptère, le péage ça doit être coton !!!
Faut déjà commencer par implémenter des try except dans ton code, exemple plus concret, si je reprend un bout de ton code :
On transforme comme ça
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 Stocker.First; if Stocker.FindKey([Tampon1.Fields[0].AsString, Datetimepicker1.DateTime, 'Sortie']) then begin Stocker.Edit; Stocker.FieldByName('Qte').AsFloat := Stocker.FieldByName('Qte').AsFloat + tampon1.FieldByName('Qte').AsFloat; Stocker.FieldByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.FieldByName('Heure').AsString := edit12.Text; Stocker.Post; end else begin Stocker.Insert; Stocker.FieldByName('CodPro').AsString := Tampon1.Fields[0].AsString; Stocker.FieldByName('DatStock').AsDateTime := Datetimepicker1.DateTime; Stocker.FieldByName('Heure').AsString := edit12.Text; Stocker.FieldByName('Nature').AsString := 'Sortie'; Stocker.FieldByName('QteIni').AsFloat := tampon1.FieldByName('QteIni').AsFloat; Stocker.FieldByName('Qte').AsFloat := tampon1.FieldByName('Qte').AsFloat; Stocker.FieldByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.Post; end;
Bon alors bien sur, j'écris ça brut sans tester, faudra peu être adapter un peu, mais ça devrai aller sans faire de gros changements
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 try Stocker.Insert; Stocker.FieldByName('CodPro').AsString := Tampon1.Fields[0].AsString; Stocker.FieldByName('DatStock').AsDateTime := Datetimepicker1.DateTime; Stocker.FieldByName('Heure').AsString := edit12.Text; Stocker.FieldByName('Nature').AsString := 'Sortie'; Stocker.FieldByName('QteIni').AsFloat := tampon1.FieldByName('QteIni').AsFloat; Stocker.FieldByName('Qte').AsFloat := tampon1.FieldByName('Qte').AsFloat; Stocker.FieldByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.Post; except on E:Exception do // Si on tombe ici, il y a eu une erreur, il faut savoir laquelle !!! begin if Pos('DUPLICATE',E.Message)>0 then begin // C'est juste une clé dupliquée, on fait alors un update Stocker.CancelUpdates; Stocker.Edit; Stocker.FieldByName('Qte').AsFloat := Stocker.FieldByName('Qte').AsFloat + tampon1.FieldByName('Qte').AsFloat; Stocker.FieldByName('QteFin').AsFloat := tampon1.FieldByName('QteFin').AsFloat; Stocker.FieldByName('Heure').AsString := edit12.Text; Stocker.Post; end else begin // C'est pas une valeur dupliquée, c'est plus grave MessageDlg(E.Message,mtError,[mbOk],0); end; end; end;
Du coup plus besoin du Find, ça va drôlement accélérer ta routine !!!
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager