Sign in Join
Wiki copytemporary

SQLite/fr: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## SQLite et prise en charge par FPC/Lazarus
22
33SQLite est une base de données mono-utilisateur incorporée (sans server) qui peut être utilisée dans des applications FPC et Lazarus (mais pas seulement). Divers pilotes peuvent être utilisés pour accéder à SQLite depuis des programmes FPC/Lazarus. Tous les pilotes demandent la bibliothèque/dll SQLite dans le répertoire de l'application qui, pour fonctionner, peut être votre répertoire de projet ou p.ex. (projectdir)/lib/architecture/ selon vos réglages de projet Lazarus et distribué avec votre exécutable.
44
55Win64: veuillez voir l'avertissement [[Windows Programming Tips/fr|ici]] sur l'impossibilité d'utiliser certaines versions de FPC/Lazarus Win64.
66
77### Accès direct à SQLite
88
99Vous pouvez utiliser une manière simple pour vous connecter à SQLite avec Lazarus. Les SQLite Data Access Components (LiteDAC) sont une bibliothèque de composants qui fournissent une connectivité native à SQLite depuis Lazarus (et Free Pasacal) sur Windows, Mac OS X, iOs, Androïd, Linux et FreeBSD à la fois pour les plates-formes 32-bit et 64-bit. LiteDAC est conçu pour les programmeurs pour développer des applications de bases de données SQLite de bureau ou mobiles réellement multi plate-forme sans nécessité de déployer des bibliothèques supplémentaires.
1010
1111Vous pouvez télécharger une version d'essai du produit commercial depuis [Composants Lazarus](https://www.devart.com/litedac/download.html).
1212
1313### SQLDB intégré
1414
1515FPC/Lazarus offre des composants SQLdb intégrés qui incluent la prise en charge des bases de données SQLite ([[TSQLite3Connection/fr|TSQLite3Connection]]) depuis l'[[SQLdb tab/fr|onglet SQLdb]] de la [[Component Palette/fr|palette de composants]], ce qui vous permet par exemple de créer des IHM avec des composants de base de données tels que des [[TDBGrid/fr|TDBGrids]]. L'avantage est qu'il devient très facile de passer à une autre base de données telle que Firebird ou PostgreSQL sans trop changer votre programme. Voir plus bas pour des détails.
1616
1717#### Prise en charge de Spatialite
1818
1919Spatialite sont des extensions SIG à SQLite que vous pouvez utiliser à partir de SQLdb. Voyez [[Spatialite/fr|Spatialite]].
2020
2121#### Prise en charge du chiffrement
2222
2323Dans les versions récentes de FOC (implémentée en mas 2012), SQLdb inclut la prise en charge de certaines versions étendues de SQLite qui crypte le fichier de base de données de SQLite en utilisant l'algorithme AES. Utilisez la propriété Password pour définir le clé de chiffrement.
2424
2525Exemples:
2626
2727- [SQLCipher](http://sqlcipher.net/) : open source, mais les binaires ne sont pas libres (vous devez les compilez vous-mêmes).
2828- [System.Data.SQLite](http://system.data.sqlite.org/) : open source, binaires Windows (32, 64, CE) disponibles, téléchargez p.ex. un des binaires précompilés et renommez SQLite.Interop.dll en sqlite3.dll (Si vous en utilisez un statiquement lié, vous devriez probablement renommer system.Data.SQLite.DLL en sqlite3.dll).
2929- [wxSQLite3](http://wxcode.sourceforge.net/docs/wxsqlite3/): open source, certains binaires Linux sont disponibles (ex: <https://launchpad.net/ubuntu/oneiric/+package/libwxsqlite3-2.8-0>)
3030
3131#### sqlite3backup
3232
3333sqlite3backup est une unité avec FPC (pas dasn Lazarus pais peut être utilisé par programmation) qui fournit une fonctionnalité de sauvegarde/restauration pour SQLite3. Elle utilise sqlite3conn de SQLdb.
3434
3535### Cas de Debian Jessie
3636
3737(Décrit depuis Lazarus 1.8RC3 + FPC 3.0.3, à vérifier pour d'autres versions) L'installation du paquet sqlite3laz.0.4 depuis la Debian Jessie pose problème. En effet, lors de la reconstruction de l'EDI, une erreur générique de liaison bloquante survient alors. Il s'avère que le fichier /usr/share/fpcsrc/3.0.3/packages/sqlite/src/sqlite3.inc attend la nom de bibliothèque libsqlite3.so mais la Debian Jessie ne propose que le lien symbolique libsqlite3.so.0. Deux solutions :
3838
3939- soit changer le nom dans le source du fichier .inc, mais cela est risqué et devra être fait à nouveau à chaque réinstallation de Lazarus et induit une différence non pertinente avec la version officielle.
4040- soit créer un lien symbolique avec ce nom dans le répertoire des bibliothèques (/usr/lib/x86_64-linux-gnu pour mon cas).
4141
42-`sudo ln -s libsqlite3.so.0 libsqlite3.so `
42+```text
43+sudo ln -s libsqlite3.so.0 libsqlite3.so
44+```
4345
4446La contrainte réside dans le déploiement, il faut en effet s'assurer que le lien ou nom de fichier direct existe sur le système cible et au besoin le créer.
4547
4648Cela résoud aussi les problèmes rencontrés lors de l'installation de la bibliotèque ZeosLib qui provoquait la même erreur.
4749
4850### Zeos
4951
5052[Zeos](https://sourceforge.net/projects/zeoslib/)
5153
5254### SQLitePass
5355
5456Composants [SqlitePass](http://source.online.free.fr/) . Etat: inconnu.
5557
5658### TSQLite3Dataset et TSQLiteDataset
5759
5860Il y a des paquets séparés pour TSQLiteDataset (unité sqliteds) et TSQLite3Dataset (unité sqlite3ds) ; voyez ci-dessous pour une description sur la façon de les utiliser. Visitez la [sqlite4fpc page d'accueil](http://sqlite4fpc.yolasite.com/) pour trouver l'API de référence et plus de tutoriels.
5961
6062TSqliteDataset et TSqlite3Dataset sont des descendants de [[TDataSet/fr|TDataSet]] qui accèdent, respectivement aux bases de données SQLite 2.8.x et 3.x.x. Pour de nouveaux projets, vous supposeriez utiliser TSQlite3Dataset en tant que version actuelle de SQLite 3.x.
6163
6264Ci-dessous est une liste des principaux avantages et inconvénients comparés à d'autres méthodes d'accès/pilotes SQLite pour FPC/Lazarus :
6365
6466Avantages :
6567
6668- Flexible : Les programmeurs peuvent choisir d'utiliser ou pas le langage SQL, leur permettant de travailler avec un schéma de simple table ou des schémas plus compliqués tels que SQLite le permet.
6769
6870Inconvénients :
6971
7072- Le changement vers une autre base de données est plus difficile si vous utilisez les composants SQLDB ou Zeos.
7173
7274> **Note:** Selon ci-dessus, des utilisateurs utiliseront SQLdb ou Zeos pour leurs avantages à moins d'avoir besoin des accès bas-niveaux de la bibliothèque SQLite
7375
7476## Utilisation des composants SQLdb avec SQLite
7577
7678Ces directives font le point sur les spécificités de SQLdb pour SQLDB (le composant TSQLite3Connection). Pour une vue d'ensemble, jetez un œil sur [[SqlDBHowto/fr|SqlDBHowto]] qui continet des informations intéressantes sur les composants SQLdb.
7779
7880Voyez le [[SQLdb Tutorial1/fr|SQLdb_Tutorial1]] pour un tutoriel sur la création d'un programme IHM relié aux données qui est écrit pour SQLite/SQLDB (et tout aussi bien pour Firebird/SQLDB, PostgreSQL/SQLDB, et d'une façon générale pour tout SGBDR que SQLDB prend en charge).
7981
8082Nous utiliserons une combinaison de trois composants dans l'onglet SQLdb : TSQLite3Connection, TSQLTransaction et TSQLQuery. Le TSQLQuery agit comme notre TDataSet ; dans le cas le plus simple il représente juste une de nos tables. Par simplicité, assurez-vous d'avoir une base de données SQLite et de ne pas avoir besoin d'en créer une maintenant. TSQLite3Connection peut être trouvé dans l'unité *sqlite3conn*, si vous voulez le déclarez vous-mêmes ou si vous travaillez avec FreePascal.
8183
8284Les trois composants sont connectés entre eux comme d'habitude : dans l'ensemble TSQLQuery, définissez les propriétés Database et Transaction, dans le TSQLTransaction, définissez la propriété Database. Il n'y a pas grand chose d'autre à faire dans les composants Transaction et Connection, les choses les plus intéressantes seront faites dans le TSQLQuery. Configurez les composants comme suit :
8385
8486TSQLite3Connection :
8587
8688- DatabaseName : mettez-y le nom (avec un chemin absolu!) de votre fichier SQLite. Malheureusement, vous ne pouvez pas simplement utiliser un chemin relatif qui resterait inchangé à la conception et à l'exécution *** est-ce toujours vrai ? Ne pouvez-vous pas seulement copier le fichier de base de données à l'aide d'un script post-construction ou définir un lien symbolique ? ***. Vous devrez vous assurer que quand l'application démarre, le chemin vers le fichier est défini correctement par programmation, sans tenir compte de la valeur de conception.
8789
8890Note : Pour définir le chemin d'accès complet à la bibliothèque (si vous placez votre dll/so/dylib de SQLite où votre système ne le trouvera pas, telle que le dossier de l'application dans Linux ou OS/X), vous pouvez employer la propriété *SQLiteLibraryName* (avant qu'une connexion ne soit établie p.ex. dans l'événement OnCreate de la fiche principale), comme ceci :
8991
9092``` pascal
9193SQLiteLibraryName:='./sqlite3.so';
9294```
9395
9496TSQLQuery :
9597
9698- SQL : placez-y une simple rerquête SELECT sur l'une de vos tables. P.ex., si vous avez une table 'foo' et voulez que le DataSet représente cette table, mettez-y seulement :
9799 ``` SQL
98100 SELECT * FROM foo
99101 ```
100102
101103- Active : Mettez-la à True depuis l'EDI pour voir si tout marche correctement. Cela active automatiquement les objets transaction et connexion. Si vous recevez une erreur, soit le Databasename de la connection n'est pas correct ou la requête SQL est fausse. Plus tard, lorsque nous finissons d'ajouter les champs (voir ci-dessous), tous les objets sont de nouveau inactifs, nous ne voulons pas que l'IDE verrouille la base de données SQLite (un seul utilisateur!) Lors du test de l'application.
102104
103105- *Sans doute pas nécessaire pour une opération propre - devra être contrôlé (juin 2012)* Maintenant nous pouvons ajouter des champs à notre TSQLQuery. Pendant que le composant est toujours actif , cliquez-droit et "Editer les champs..." . Cliquez sur le le bouton "+" et ajoutez les champs. Cela ajoutera tous les champs que votre requêtes SQL a retourné. Ajouté chaque chaque dont vous avez besoin, vous pouvez aussi ajouter des champs de référence (*lookup fields*) ici ; dans ce cas assurez d'avoir ajouter tous les champs requis dans les autres DataSets avant d'ajouter les champs qui leur feront référence. Si votre table a des champs qui ne vous intéresse pas, vous pouvez les enlever, vous pouvez aussi rendre votre requête un peu plus spécifique (remplacez SELECT * par un SELECT avec la liste des champs voulus).
104106
105107- Dans votre code, vous avez besoin d'appeler SQLQuery.ApplyUpdates et SQLTransaction.Commit, les événements TSQLQuery.AfterPost et AfterInsert sont les bons endroits pour cela quand vous utilisez des contrôles sensibles aux données mais bien sûr, vous pouvez aussi remettre à plus tard ces appels. Si vous ne les appelez pas, la base de données ne sera pas mise à jour.
106108
107109- Database is locked" : L'EDI pourrait encore bloquer la base de données (SQLite est une base de données mono-utilisateur), vous avez sans doute oublié de mettre les composants à inactif et de vous déconnecter après avoir défini tous les champs de vos objets TSQLQuery. Utilisez l'événement OnCreate de la fiche pour définir le chemin d'accès et activer les objets à l'exécution seulement. La plupart des choses que vous réglez dans TSQLQuery depuis l'EDI ne nécessitent pas (et même ne le permettent pas pour certaines) qu'il soit actif en conception, la seule exception est quand vous voulez lire la structure de la table, ainsi l'état normal en conception est inactif.
108110
109111- Vos tables devraient toutes avoir une clé primaire et vous devez vous assurez que les champs correspondants ont pfInKey et rien d'autre dans leurs PoviderFlags (ces drapeaux contrôlent comment et où le champ est utilisé en cas de construction automatique de requêtes de mise à jour et de suppression).
110112
111113- Si vous utilisez des champs de référence :
112114 - Assurez-vous que le ProviderFlags pour le champ de référence est complétement vide, comme ça, son nom ne sera pas utilisé dans une requête de mise à jour. Le champ de référence lui-même n'est pas un champ de données, il agit seulement sur la valeur d'un autre champ, le champ clé correspondant, et seulement ce champ clé sera plus tard utilisé dans les requêtes de mise à jour. Vous pouvez masquer le champ clé car la plupart du temps vous ne voudrez pas le voir dans votre interface utilisateur mais il doit être défini.
113115 - LookupCache doit être mise à True. Au moment de la rédaction, pour certaines raisons, le champ Lookup n'affichera rien d'autre (mais fonctionnera encore) et étrangement à l'exact opposé du TSQLite3Dataset ou d'autres composants TXXXDataset pour lesquels elle doit être mise à False. Je ne suis pas encore sûr de savoir si cela est un comportement intentionnel ou un bug.
114116
115117- Habituellement avec de simples tables, vous n'aurez besoin de définir aucune des propriétés InsertSQL, UpdateSQL et DeleteSQL, il suffit de les laisser vides. Si vous avez défini correctement les propriétés ProviderFlags de tous vos champs, les requêtes seront créées à la volée. Pour plus de détails sur InsertSQL, UpdateSQL et DeleteSQL, voyez [[http://wiki.lazarus.freepascal.org/Working With TSQLQuery/fr|http://wiki.lazarus.freepascal.org/Working_With_TSQLQuery/fr#InsertSQL.2C_UpdateSQL_et_DeleteSQL_-_Utilisation_basique_des_param.C3.A8tres]].
116118
117119Après que ce qui précède est correctement mis en place, vous devriez maintenant être capable d'utiliser le TSQLQuery comme tout autre TDataSet, soit en le manipulant par code soit en plaçant un TDataSource sur la fiche, le connectant à un TDataSet et en utilisant un contrôle comme une grille etc.
118120
119121### Création d'une base de données
120122
121123La méthode [TSQLite3Connection.CreateDB](http://www.freepascal.org/docs-html/fcl/sqldb/tsqlconnection.createdb.html) héritée de la classe parent ne fait actuellement rien ; pour créer une base de données si aucun fichier n'existe, vous devez simplement écrire les données de la table comme dans l'exemple suivant :
122124
123125(Code extrait de l'exemple sqlite_encryption_pragma fourni avec Lazarus 1.3)
124126
125127``` pascal
126128var
127129 newFile : Boolean;
128130begin
129131
130132 SQLite3Connection1.Close; // Ensure the connection is closed when we start
131133
132134 try
133135 // Since we're making this database for the first time,
134136 // check whether the file already exists
135137 newFile := not FileExists(SQLite3Connection1.DatabaseName);
136138
137139 if newFile then
138140 begin
139141 // Create the database and the tables
140142 try
141143 SQLite3Connection1.Open;
142144 SQLTransaction1.Active := true;
143145
144146 // Here we're setting up a table named "DATA" in the new database
145147 SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
146148 ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
147149 ' "Current_Time" DateTime NOT NULL,'+
148150 ' "User_Name" Char(128) NOT NULL,'+
149151 ' "Info" Char(128) NOT NULL);');
150152
151153 // Creating an index based upon id in the DATA Table
152154 SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');
153155
154156 SQLTransaction1.Commit;
155157
156158 ShowMessage('Succesfully created database.');
157159 except
158160 ShowMessage('Unable to Create new Database');
159161 end;
160162 end;
161163 except
162164 ShowMessage('Unable to check if database file exists');
163165 end;
164166 end;
165167```
166168
167169### Création de collations personnalisées
168170
169171``` pascal
170172// utf8 case-sensitive compare callback function
171173function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
172174var S1, S2: AnsiString;
173175begin
174176 SetString(S1, data1, len1);
175177 SetString(S2, data2, len2);
176178 Result := UnicodeCompareStr(UTF8Decode(S1), UTF8Decode(S2));
177179end;
178180
179181// utf8 case-insensitive compare callback function
180182function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
181183var S1, S2: AnsiString;
182184begin
183185 SetString(S1, data1, len1);
184186 SetString(S2, data2, len2);
185187 Result := UnicodeCompareText(UTF8Decode(S1), UTF8Decode(S2));
186188end;
187189
188190// register collation using SQLite3 API (requires sqlite3dyn unit):
189191sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
190192// or using method of TSQLite3Connection:
191193CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);
192194
193195// now we can use case-insensitive comparison in SQL like:
194196// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'á'
195197
196198// but this does not work for LIKE operator
197199// in order to support also LIKE operator we must overload default LIKE function using sqlite3_create_function()
198200// http://www.sqlite.org/lang_corefunc.html#like
199201```
200202
201203### Création de fonctions personnalisées
202204
203205``` pascal
204206// example overloading default LOWER() function with user supplied function
205207procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
206208var S: AnsiString;
207209begin
208210 SetString(S, sqlite3_value_text(V[0]), sqlite3_value_bytes(V[0]));
209211 S := UTF8Encode(AnsiLowerCase(UTF8Decode(S)));
210212 sqlite3_result_text(ctx, PAnsiChar(S), Length(S), sqlite3_destructor_type(SQLITE_TRANSIENT));
211213end;
212214
213215// register function LOWER() using SQLite3 API (requires sqlite3dyn unit):
214216sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);
215217```
216218
217219### SQLite3 et les dates
218220
219221- SQLite 3 ne stocke pas les dates comme des valeurs spéciales. Il peut les stocker comme des String, de Double or Integer - voyez [1](http://www.sqlite.org/datatype3.html#datetime).
220222- Dans les String, le séparateur de date est '-' comme dans la norme SQL ISO 8601. Ainsi, vous pouvez faire un INSERT en utilisant la fonction intégrée DATE, ce sera stocké en quelque chose comme 'YYYY-MM-DD'.
221223- La lecture d'une valeur DateTime peut causer des problèmes pour DataSets si elles sont enregistrées sous forme de String : la propriété .AsDateTime peut se bloquer sur une 'string date' de SQLite, mais cela peut être surmonté en utilisant quelque chose comme `strftime(`*`%d/%m/%Y`*`,recdate) AS sqlite3recdate` dans votre ordre SQL, ce qui force SQLite3 à retourner l'enregistrement Date dans un format spécifique (la chaîne de format %d/%m/%d correspond à votre configuration locale de date que .AsDateTime comprendra) **==\> veuillez ouvrir une rapport de bug avec un exemple d'application démontrant le problème si cela est la cas**.
222224- En comparant des dates enregistrées en chaîne (en utilisant p.ex. la fonction BETWEEN), souvenez-vous que la comparaison sera toujours une comparaison de string, et donc dépendra de comment vous avez enregistré la valeur de date.
223225
224226#### Valeurs par défaut en temps local au lieu de UTC
225227
226228CURRENT_TIME, CURRENT_DATE et CURRENT_TIMESTAMP retournent la date UTC et/ou l'heure. Pour des dates et/ou heures locales, vous pouvez utilisez :
227229
228-` DEFAULT (datetime('now','localtime')) pour les valeurs datetime formatées en YYYY-MM-DD HH:MM:SS`\
229-` DEFAULT (date('now','localtime')) pour les valeurs date formatées en YYYY-MM-DD`\
230-` DEFAULT (time('now','localtime')) pour les valeurs time formatées en HH:MM:SS.`
230+```text
231+ DEFAULT (datetime('now','localtime')) pour les valeurs datetime formatées en YYYY-MM-DD HH:MM:SS
232+ DEFAULT (date('now','localtime')) pour les valeurs date formatées en YYYY-MM-DD
233+ DEFAULT (time('now','localtime')) pour les valeurs time formatées en HH:MM:SS.
234+```
231235
232236### Résolution de problème sur SQLDB et SQLite
233237
234238- Gardez à l'esprit que pour pouvoir fonctionner en conception (champs, inidex etc), Lazarus doit trouver sqlite3.dll aussi.
235239- La même chose pour le nom de fichier de la base de données. Utilisez toujours des chemins absolus si vous utilisez des composants pour extraire p.exe les noms des champs en conception. Sinon, l'EDI créera un fichier vide dans son dossier. En cas de problème, vérifiez si le dossier /lazarus détient une copie vide du fichier de base de données.
236240- Si vous avez une relation maître/détail, vous avez besoin de rafraichir le DataSet maître après chaque insertion, en vue d'obtenir la valeur de la clé étrangère pour le DataSet détail. Vous pouvez faire cela dans l'événement AfterPost du DataSet maître, en appelant l'une de ces méthodes redéfinies :
237241
238242``` pascal
239243interface
240244 procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);overload;
241245 procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);overload;
242246
243247implementation
244248
245249procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
246250//This procedure refreshes a dataset and positions cursor to last record
247251//To be used if Dataset is not guaranteed to be sorted by an autoincrement primary key
248252var
249253 vLastID: Integer;
250254 vUpdateStatus : TUpdateStatus;
251255begin
252256 vUpdateStatus := pDataset.UpdateStatus;
253257 //Get last inserted ID in the database
254258 pDataset.ApplyUpdates;
255259 vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
256260 //Now come back to respective row
257261 if vUpdateStatus = usInserted then begin
258262 pDataset.Refresh;
259263 //Refresh and go back to respective row
260264 pDataset.Locate(pKeyField,vLastID,[]);
261265 end;
262266end;
263267
264268procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
265269//This procedure refreshes a dataset and positions cursor to last record
266270//To be used only if DataSet is guaranteed to be sorted by an autoincrement primary key
267271var
268272 vLastID: Integer;
269273 vUpdateStatus : TUpdateStatus;
270274begin
271275 vUpdateStatus := pDataset.UpdateStatus;
272276 pDataset.ApplyUpdates;
273277 vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
274278 if vUpdateStatus = usInserted then begin
275279 pDataset.Refresh;
276280 //Dangerous!
277281 pDataSet.Last;
278282 end;
279283end;
280284
281285procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
282286begin
283287 RefreshADatasetAfterInsert(Dataset as TSQLQuery); //If your dataset is sorted by primary key
284288end;
285289
286290procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
287291begin
288292 RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //if you are not sure that the dataset is always sorted by primary key
289293end;
290294```
291295
292296### Vacuum et autres opérations qui doivent être faites en dehors d'une transaction
293297
294298SQLdb semble demander toujours une connexion, mais certaines opérations comme Pragma et Vacuum doivent être faite en dehors de toute transaction. L'astuce consiste à mettre fin à la transaction, exécuter ce que vous devez et redémarrer la transaction (ainsi SQLdb ne sera pas perdu) :
295299
296300``` pascal
297301 // commit any pending operations or use a "fresh" sqlconnection
298302 Conn.ExecuteDirect('End Transaction'); // End the transaction started by SQLdb
299303 Conn.ExecuteDirect('Vacuum');
300304 Conn.ExecuteDirect('Begin Transaction'); //Start a transaction for SQLdb to use
301305```
302306
303307## En utilisant TSQLite3Dataset
304308
305309Cette section détaille comment utiliser les composants TSQLite2Dataset et TSQLite3Dataset pour accéder aux bases de données SQLite. par Luiz Américo luizmed(at)oi(dot)com(dot)br
306310
307311#### Pré-requis
308312
309313- Pour les bases de données sqlite2 (système "patrimonial") :
310314 - FPC 2.0.0 ou supérieur
311315 - Lazarus 0.9.10 ou supérieur
312316 - Bibliothèque d'exécution SQLite 2.8.15 ou supérieure
313317
314318- Sqlite2 n'est plus maintenu et le binaire ne peut pas être trouvé sur le site Web SQLite.
315319
316320- Pour les bases de données sqlite3 :
317321 - FPC 2.0.2 ou supérieur
318322 - Lazarus 0.9.11 (révision svn 8443) ou supérieur
319323 - Bibliothèque d'exécution SQLite 3.2.1 ou supérieure (obtenez-la depuis [www.sqlite.org](http://www.sqlite.org))
320324
321325**Avant de commencer un projet Lazarus, assurez-vous que :**
322326
323327- la bibliothèque sqlite est soit
324328 - dans le chemin système PATH ou
325329 - dans le dossier de sortie de l'exécutable et dans le dossier de Lazarus (ou dans le projet courant) - cette option pourrait marcher dans Windows seulement.
326330- Sous Linux, mettre `cmem` comme première unité dans la clause Uses de votre programme principal.
327331 - Dans Debian, Ubuntu et autre distro dérivée de Debian, en vue de construire l'EDI de Lazarus, vous devez ajouter le paquet libsqlite-dev/libsqlite3-dev, et pas seulement sqlite/sqlite3 (s'applique aussi à OpenSuse).
328332
329333#### Comment l'utiliser (Usage basique)
330334
331335Installez le paquet trouvé dans le répertoire /components/sqlite directory (voir les instructions [[Install Packages/fr|ici]]).
332336
333337En conception, définissez les propriétés suivantes :
334338
335339- FileName : chemin vers le fichier sqlite \[requis\]
336340- TableName : nom de la table utilisée dans l'ordre SQL \[requis\]
337341- SQL : un ordre SELECT en SQL \[optionnel\]
338342- SaveOnClose : La valeur par défaut est False, ce qui signifie que les changements ne sont pas enregistrés. On peut le changer à vrai. \[optionnel\]
339343- Active : Demande à être mis à True en conception ou au démarrage du programme. \[requis\]
340344
341345**Création d'une table (Dataset)**
342346
343347Double-cliquez sur l'icône du composant ou utilisez l'entrée 'Create Table' du menu surgissant (clic droit). Un simple éditeur de table intuitif sera affiché.
344348
345349Voici tous les types de champ pris en charge par TSqliteDataset et TSqlite3Dataset :
346350
347351- Integer
348352- AutoInc
349353- String
350354- Memo
351355- Bool
352356- Float
353357- Word
354358- DateTime
355359- Date
356360- Time
357361- LargeInt
358362- Currency
359363
360364**Récupération des données**
361365
362366Après avoir créer la table ou avec une table déjà créée, ouvrez le DataSet avec la méthode Open.
363367
364368Si la propriété SQL n'était pas définie alors tous les champs de tous les enregistrement seront récupérés, comme si vous aviez passé l'ordre SQL :
365369
366370``` pascal
367371SQL := 'Select * from TABLENAME';
368372```
369373
370374**Application des mises à jour au fichier de données sous-jacent**
371375
372376Pour utiliser la fonction ApplyUpdates, le DataSet doit contenir au moins un champ qui remplit les conditions pour une clé primaire (ses valeurs doivent être UNIQUES et non NULLES).
373377
374378Il est possible de faire ceci de deux façons :
375379
376380- Définissez la propriété PrimaryKey avec le nom du champ de clé primaire.
377381- Ajoutez un champ AutoInc (ce qui est plus facile depuis que le TSqliteDataSet le manipule automatiquement comme une clé primaire).
378382
379383Si l'une de ces conditions est satisfaite, appelez seulement :
380384
381385``` pascal
382386ApplyUpdates;
383387```
384388
385389> **Note:** Si les deux conditions sont satisfaites, le champ correspondant à la clé primaire est utilisé pour appliquer les mise à jour.
386390
387391> **Note:** Définir PrimaryKey à un champ qui n'est pas une clé primaire amènera à des pertes de données si ApplyUpdates est appelée, assurez-vous donc que le champ choisi contient bien des valeurs uniques et non nulles avant de l'utiliser.
388392
389393##### Exemple de relation maître/détail
390394
391395Divers exemples de realtions maître/détail (p.ex. la relation entre client et commandes) :
392396
393397- la manière générique de SQLdb pour faire ceci utilise le [[TDataSource/fr|TDataSource]] et la propriété [[MasterDetail/fr|MasterDetail]]
394398- un exemple spécifique TSQLite3 utilisant locate: [[TSqlite3 Master Detail Example/frf|Exemple de maître/détail avec TSqlite3]].
395399
396400#### Remarques
397401
398402- Bien que cela ait été testé avec 10 000 enregistrements et ait fonctionné très bien, TSqliteDataset conserve toutes les données en mémoire, aussi gardez en mémoire de ne récupérer que les données nécessaire en mémoire (en particulier avec les champs Memo).
399403- Le même fichier de données (propriété FileName) peut héberger plusieurs tables/DataSets.
400404- Plusieurs DataSets (différentes combinaisons de champs) peurvent être créés en utilisant en même temps la même table (ce sont des copies des données en mémoire).
401405- Il est possible de filtrer les données en utilisant les clauses WHERE dans le SQL, en fermant et réouvrant le DataSet (ou en appelant la méthode RefetchData). Mais dans ce cas, l'ordre et le nombre des champs doit rester le même (i.e. on ne "bricole" la liste de champs du SELECT).
402406- Il est possible d'utiliser des ordres SQL complexes en utilisant des alias, des jointures, des vues pour de multiples tables (rappelez-vous qu'elle doivent résider dans le même fichier de données), mais dans ce cas ApplyUpdates ne fonctionnera pas.
403407- La définition du nom du fichier vers une fichier de données SQLite mais pas créé par TSqliteDataset et l'ouverture est permise mais le type de certains champs ne sera pas détecté correctement. Ils seront traités comme des champs de type String.
404408
405409Des exemples génériques peuvent être trouvés dans le répertoire SVN fpc/fcl-db/src/sqlite.
406410
407411## Voir aussi
408412
409413- [[SQLdb Tutorial1/fr|Tutoriel 1 sur SQLdb]] Tutoriel pour Sqlite
410414- [[SqlDBHowto/fr|SqlDBHowto]] Information générale sur SQLDB
411415- [[Working With TSQLQuery/fr|Travailler avec le TSQLQquery]] Informations sur le TSQLQuery de SQLDB.
412416- [Site SQLite](http://www.sqlite.org)
413417
414418---
415419*From the Free Pascal wiki, page "SQLite/fr", as it stood on 2021-09-09 after a change by Jpasj, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history