Copie du wikimiroir

Ceci est un miroir du wiki de pascal.chat. La modification, l’historique et la connexion se trouvent là-bas.

SQLite/fr

English · Español · Français · Polski · Русский · 中文(中国) · 日本語

SQLite et prise en charge par FPC/Lazarus

SQLite 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.

Win64: veuillez voir l'avertissement ici sur l'impossibilité d'utiliser certaines versions de FPC/Lazarus Win64.

Accès direct à SQLite

Vous 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.

Vous pouvez télécharger une version d'essai du produit commercial depuis Composants Lazarus.

SQLDB intégré

FPC/Lazarus offre des composants SQLdb intégrés qui incluent la prise en charge des bases de données SQLite (TSQLite3Connection) depuis l'onglet SQLdb de la 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 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.

Prise en charge de Spatialite

Spatialite sont des extensions SIG à SQLite que vous pouvez utiliser à partir de SQLdb. Voyez Spatialite.

Prise en charge du chiffrement

Dans 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.

Exemples:

sqlite3backup

sqlite3backup 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.

Cas de Debian Jessie

(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 :

text
sudo ln -s libsqlite3.so.0 libsqlite3.so

La 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.

Cela résoud aussi les problèmes rencontrés lors de l'installation de la bibliotèque ZeosLib qui provoquait la même erreur.

Zeos

Zeos

SQLitePass

Composants SqlitePass . Etat: inconnu.

TSQLite3Dataset et TSQLiteDataset

Il 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 pour trouver l'API de référence et plus de tutoriels.

TSqliteDataset et TSqlite3Dataset sont des descendants de 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.

Ci-dessous est une liste des principaux avantages et inconvénients comparés à d'autres méthodes d'accès/pilotes SQLite pour FPC/Lazarus :

Avantages :

Inconvénients :

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

Utilisation des composants SQLdb avec SQLite

Ces 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 qui continet des informations intéressantes sur les composants SQLdb.

Voyez le 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).

Nous 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.

Les 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 :

TSQLite3Connection :

Note : 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 :

pascal
SQLiteLibraryName:='./sqlite3.so';

TSQLQuery :

Aprè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.

Création d'une base de données

La méthode TSQLite3Connection.CreateDB 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 :

(Code extrait de l'exemple sqlite_encryption_pragma fourni avec Lazarus 1.3)

pascal
var
  newFile : Boolean;
begin

  SQLite3Connection1.Close; // Ensure the connection is closed when we start

  try
    // Since we're making this database for the first time,
    // check whether the file already exists
    newFile := not FileExists(SQLite3Connection1.DatabaseName);

    if newFile then
    begin
      // Create the database and the tables
      try
        SQLite3Connection1.Open;
        SQLTransaction1.Active := true;

        // Here we're setting up a table named "DATA" in the new database
        SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
                    ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
                    ' "Current_Time" DateTime NOT NULL,'+
                    ' "User_Name" Char(128) NOT NULL,'+
                    ' "Info" Char(128) NOT NULL);');

        // Creating an index based upon id in the DATA Table
        SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');

        SQLTransaction1.Commit;

        ShowMessage('Succesfully created database.');
      except
        ShowMessage('Unable to Create new Database');
      end;
    end;
  except
    ShowMessage('Unable to check if database file exists');
  end;
 end;

Création de collations personnalisées

pascal
// utf8 case-sensitive compare callback function
function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
var S1, S2: AnsiString;
begin
  SetString(S1, data1, len1);
  SetString(S2, data2, len2);
  Result := UnicodeCompareStr(UTF8Decode(S1), UTF8Decode(S2));
end;

// utf8 case-insensitive compare callback function
function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
var S1, S2: AnsiString;
begin
  SetString(S1, data1, len1);
  SetString(S2, data2, len2);
  Result := UnicodeCompareText(UTF8Decode(S1), UTF8Decode(S2));
end;

// register collation using SQLite3 API (requires sqlite3dyn unit):
sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
// or using method of TSQLite3Connection:
CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);  

// now we can use case-insensitive comparison in SQL like:
// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'á'

// but this does not work for LIKE operator
// in order to support also LIKE operator we must overload default LIKE function using sqlite3_create_function()
// http://www.sqlite.org/lang_corefunc.html#like

Création de fonctions personnalisées

pascal
// example overloading default LOWER() function with user supplied function
procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
var S: AnsiString;
begin
  SetString(S, sqlite3_value_text(V[0]), sqlite3_value_bytes(V[0]));
  S := UTF8Encode(AnsiLowerCase(UTF8Decode(S)));
  sqlite3_result_text(ctx, PAnsiChar(S), Length(S), sqlite3_destructor_type(SQLITE_TRANSIENT));
end;

// register function LOWER() using SQLite3 API (requires sqlite3dyn unit):
sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);

SQLite3 et les dates

Valeurs par défaut en temps local au lieu de UTC

CURRENT_TIME, CURRENT_DATE et CURRENT_TIMESTAMP retournent la date UTC et/ou l'heure. Pour des dates et/ou heures locales, vous pouvez utilisez :

text
 DEFAULT (datetime('now','localtime')) pour les valeurs datetime formatées en YYYY-MM-DD HH:MM:SS
 DEFAULT (date('now','localtime')) pour les valeurs date formatées en YYYY-MM-DD
 DEFAULT (time('now','localtime')) pour les valeurs time formatées en HH:MM:SS.

Résolution de problème sur SQLDB et SQLite

pascal
interface
    procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);overload;
    procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);overload;  
 
implementation
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
//This procedure refreshes a dataset and positions cursor to last record
//To be used if Dataset is not guaranteed to be sorted by an autoincrement primary key
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  //Get last inserted ID in the database
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  //Now come back to respective row
  if vUpdateStatus = usInserted then begin
    pDataset.Refresh;
    //Refresh and go back to respective row
    pDataset.Locate(pKeyField,vLastID,[]);
  end;
end;
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
//This procedure refreshes a dataset and positions cursor to last record
//To be used only if DataSet is guaranteed to be sorted by an autoincrement primary key
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  if vUpdateStatus = usInserted then begin
    pDataset.Refresh;
    //Dangerous!
    pDataSet.Last;
  end;
end;

procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
begin
  RefreshADatasetAfterInsert(Dataset as TSQLQuery); //If your dataset is sorted by primary key
end;  

procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
begin
  RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //if you are not sure that the dataset is always sorted by primary key
end;

Vacuum et autres opérations qui doivent être faites en dehors d'une transaction

SQLdb 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) :

pascal
  // commit any pending operations or use a "fresh" sqlconnection
  Conn.ExecuteDirect('End Transaction');  // End the transaction started by SQLdb
  Conn.ExecuteDirect('Vacuum');
  Conn.ExecuteDirect('Begin Transaction'); //Start a transaction for SQLdb to use

En utilisant TSQLite3Dataset

Cette 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

Pré-requis

Avant de commencer un projet Lazarus, assurez-vous que :

Comment l'utiliser (Usage basique)

Installez le paquet trouvé dans le répertoire /components/sqlite directory (voir les instructions ici).

En conception, définissez les propriétés suivantes :

Création d'une table (Dataset)

Double-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é.

Voici tous les types de champ pris en charge par TSqliteDataset et TSqlite3Dataset :

Récupération des données

Après avoir créer la table ou avec une table déjà créée, ouvrez le DataSet avec la méthode Open.

Si 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 :

pascal
SQL := 'Select * from TABLENAME';

Application des mises à jour au fichier de données sous-jacent

Pour 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).

Il est possible de faire ceci de deux façons :

Si l'une de ces conditions est satisfaite, appelez seulement :

pascal
ApplyUpdates;

Note: Si les deux conditions sont satisfaites, le champ correspondant à la clé primaire est utilisé pour appliquer les mise à jour.

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.

Exemple de relation maître/détail

Divers exemples de realtions maître/détail (p.ex. la relation entre client et commandes) :

Remarques

Des exemples génériques peuvent être trouvés dans le répertoire SVN fpc/fcl-db/src/sqlite.

Voir aussi


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.

Version 3, dernière modification par WikiArchive .