Bonjour,
Avec FireDac, je copie une table mySQL lue à partir d'une chaîne de connexion mySQLConn->mySQLQuery posée sur la Form vers une base SQLite3:memory: définie par SQLiteModule->SQLiteConn ->SQLiteQuery (donc utilisant un DataModule). J'ai eu un petit peu de mal à gérer les NULL mais sinon l'ensemble est fonctionnel.
Le code utilisé actuellement est le suivant.
J'espère que la méthode est appropriée. Ce n'est pas la plus rapide. J'aurais pu imaginer par exemple, une lecture de la table mySQL directement dans une TStringGrid, puis le transfert de la TStringGrid directement dans la table SQLite3 éventuellement en insérant toutes les lignes à la fois.
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 with mySQLQuery do try with SQL do begin Clear; Add('SELECT elID, elCODE, elINSEE, elNOM, elPRENOM, elTEL,'); Add('elADRESSE, elCP, elVILLE, elCONTRAT, elPERMIS, elDATEPERMIS,'); Add('elDATEANCIENNETE, elMEMO, xxACTIF, xxPOSTE, xxUSER, xxSTAMP'); Add('FROM mysqlELV;'); end; Open; if not isEmpty then begin First; while not(EOF) do begin inc(nGauge); sbGauge.Progress := nGauge; //---Enr .[Déb] with SQLiteModule.SQLiteQuery do try Close; with SQL do begin Clear; Add('INSERT INTO lisqlELV ('); Add('elID, elCODE, elINSEE, elNOM, elPRENOM, elTEL, elADRESSE, elCP,'); Add('elVILLE, elCONTRAT, elPERMIS, elDATEPERMIS, elDATEANCIENNETE, elMEMO,'); Add('xxACTIF, xxPOSTE, xxUSER, xxSTAMP'); Add(') VALUES ('); Add(':paID, :paCODE, :paINSEE, :paNOM, :paPRENOM, :paTEL, :paADRESSE,'); Add(':paCP, :paVILLE, :paCONTRAT, :paPERMIS, :paDATEPERMIS, :paDATEANCIENNETE,'); Add(':paMEMO, :paACTIF, :paPOSTE, :paUSER, :paSTAMP'); Add(');'); end; with Params do begin ParamByName('paID').AsString := mySQLQuery.Fields[0].AsString; ParamByName('paCODE').AsString := mySQLQuery.Fields[1].AsString; ParamByName('paINSEE').AsString := mySQLQuery.Fields[2].AsString; ParamByName('paNOM').AsString := mySQLQuery.Fields[3].AsString; ParamByName('paPRENOM').AsString := mySQLQuery.Fields[4].AsString; ParamByName('paTEL').AsString := mySQLQuery.Fields[5].AsString; ParamByName('paADRESSE').AsString := mySQLQuery.Fields[6].AsString; ParamByName('paCP').AsString := mySQLQuery.Fields[7].AsString; ParamByName('paVILLE').AsString := mySQLQuery.Fields[8].AsString; ParamByName('paCONTRAT').AsString := mySQLQuery.Fields[9].AsString; ParamByName('paPERMIS').AsString := mySQLQuery.Fields[10].AsString; ParamByName('paDATEPERMIS').AsString := mySQLQuery.Fields[11].AsString; ParamByName('paDATEANCIENNETE').AsString := mySQLQuery.Fields[12].AsString; ParamByName('paMEMO').AsString := mySQLQuery.Fields[13].AsString; ParamByName('paACTIF').AsBoolean := mySQLQuery.Fields[14].AsBoolean; ParamByName('paPOSTE').AsString := mySQLQuery.Fields[15].AsString; ParamByName('paUSER').AsString := mySQLQuery.Fields[16].AsString; ParamByName('paSTAMP').AsString := mySQLQuery.Fields[17].AsString; end; ExecSQL; Close; except on E: EFDDBEngineException do ShowMessage(E.Errors[0].Message); end; //---Enr .[Fin] Next; end; end; Close; if mySQLConn.Connected then mySQLConn.Connected := False; except on E: EFDDBEngineException do ShowMessage(E.Errors[0].Message); end;
Je n'ai pas retenu cette option
- parce qu'il m'est difficile (impossible lors de la requète d'insertion multi-tuples) de faire progresser correctement une jauge (pour l'ergonomie)
- et surtout parce que j'utilise des blobs images qui contiennent pratiquement toujours des caractères NULL disséminés dans les chaînes. Or je suppose que comme en Lazarus, les cellules des TStringGrids ne contiennent que des champs de type C (qui tronquent les chaînes à la rencontre du premier caractère NULL). Je n'ai pas vérifié en Delphi, mais en Lazarus, j'ai travaillé longtemps là-dessus pour conserver la persistance des images dans une TStringGrid.
Donc j'ai décidé de parcourir ma table mySQL avec un SQLquery.Open et d'insérer les enregistrements lus dans la base SQLite3 un par un avec un SQLQuery.ExecSQL. Je pense que la méthode est classique.
J'aimerais toutefois résoudre quelques petits problèmes "basés" sur ce code.
Premièrement après l'Open:
Peut-on casser l'Open comme cela ? Je pense que oui... mais je n'ai pas osé non pas à cause du Close... je pense qu'il n'y a pas de problème à ce niveau-là mais à cause du try engagé... On peut quitter une exception par un Exit ? Hum...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 with mySQLQuery do try [...] Open; if isEmpty then begin Close; Exit; end; First; [...] except end;
Deuxièmement (anecdotique) :
Je me demandais s'il était possible de savoir s'il n'était pas "close" ? Idiot de fermer quelque chose qu'il l'est déjà...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 with SQLiteQuery do Close;
Donc if <? (pas close)?> then Close;
Troisièmement :Très pratique quand on est en production [Run]... Mais en exploitation, pour l'utilisateur final, je voudrais plutôt un
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 except on E: EFDDBEngineException do ShowMessage(E.Errors[0].Message); end;Peut-on différencier les 2 cas ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 MessageDlg( 'La base interne est indisponible. ' + 'Le programme va s''arrêter.', TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0); Application.Terminate;
Merci.
Partager